aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorleonidlazarev <leonidlazarev@yandex-team.com>2023-08-01 12:39:29 +0300
committerleonidlazarev <leonidlazarev@yandex-team.com>2023-08-01 12:39:29 +0300
commita3b63938a35abe460ed6b601e55e57bb44449c83 (patch)
treeb6a8b6b9a486f68bf4dd1627fca351e9513897b2
parent1ab00fd81ce534b158e55f27450d5559833cb70a (diff)
downloadydb-a3b63938a35abe460ed6b601e55e57bb44449c83.tar.gz
feat grpc: update to grpc 1.54.2
update grpc to 1.54.2 update grpcio to 1.54.2 Added patches: pr33239_fix_use_after_free.patch Removed patches: pr32547-fix-race.patch - exists in upstream
-rw-r--r--contrib/libs/grpc/CMakeLists.darwin-x86_64.txt64
-rw-r--r--contrib/libs/grpc/CMakeLists.linux-aarch64.txt64
-rw-r--r--contrib/libs/grpc/CMakeLists.linux-x86_64.txt64
-rw-r--r--contrib/libs/grpc/CMakeLists.windows-x86_64.txt64
-rw-r--r--contrib/libs/grpc/include/grpc/event_engine/event_engine.h44
-rw-r--r--contrib/libs/grpc/include/grpc/grpc_security.h4
-rw-r--r--contrib/libs/grpc/include/grpc/support/port_platform.h8
-rw-r--r--contrib/libs/grpc/include/grpcpp/alarm.h3
-rw-r--r--contrib/libs/grpc/include/grpcpp/ext/call_metric_recorder.h15
-rw-r--r--contrib/libs/grpc/include/grpcpp/ext/server_metric_recorder.h6
-rw-r--r--contrib/libs/grpc/include/grpcpp/security/tls_certificate_verifier.h7
-rw-r--r--contrib/libs/grpc/include/grpcpp/support/client_interceptor.h19
-rw-r--r--contrib/libs/grpc/include/grpcpp/version_info.h6
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/backend_metrics/backend_metric_filter.cc11
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/backend_metric.cc6
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/backup_poller.cc13
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/backup_poller.h3
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.cc1659
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.h304
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel_internal.h114
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/config_selector.h7
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_call_state_internal.h39
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/backend_metric_data.h7
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc35
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc285
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc16
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc24
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_round_robin/weighted_round_robin.cc98
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc14
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc9
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc7
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.cc4
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc67
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc8
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc30
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h29
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc46
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc210
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/polling_resolver.cc3
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/polling_resolver.h3
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc6
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/retry_filter.cc197
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.cc6
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel_stream_client.cc53
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel_stream_client.h13
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/http/client/http_client_filter.cc6
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/http/http_filters_plugin.cc13
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/http/message_compress/compression_filter.cc38
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.cc366
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.h51
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_filter.cc13
-rw-r--r--contrib/libs/grpc/src/core/ext/gcp/metadata_query.cc137
-rw-r--r--contrib/libs/grpc/src/core/ext/gcp/metadata_query.h88
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/binder/transport/binder_transport.cc1
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.cc88
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.h10
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc125
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_transport.cc174
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/flow_control.cc7
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/flow_control.h3
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/frame_settings.cc5
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/internal.h20
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/parsing.cc5
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/writing.cc15
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.cc34
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c8
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h22
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c8
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h22
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.c28
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.h97
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c25
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h120
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.c9
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.h22
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c30
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h123
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c16
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h36
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/trace/v3/opentelemetry.upb.c1
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c18
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h68
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c8
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h24
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c8
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h24
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/type/matcher/v3/http_inputs.upb.c15
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/type/matcher/v3/http_inputs.upb.h49
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c33
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h78
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c378
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.c275
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/proxy_protocol.upbdefs.c46
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/proxy_protocol.upbdefs.h5
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c21
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.h15
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/quic_config.upbdefs.c99
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c254
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.h5
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c197
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/trace/v3/opentelemetry.upbdefs.c33
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c536
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.c234
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/discovery/v3/ads.upbdefs.c10
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c10
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c10
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/http_inputs.upbdefs.c21
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/http_inputs.upbdefs.h5
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_channel_stack_modifier.cc3
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_client_stats.cc44
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_client_stats.h44
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_endpoint.cc7
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_endpoint.h10
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.cc2
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_lb_policy_registry.cc13
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_transport_grpc.cc2
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/call_finalization.h2
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/call_tracer.cc51
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/call_tracer.h140
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/connected_channel.cc1533
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/context.h9
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/promise_based_filter.cc148
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/promise_based_filter.h40
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/server_call_tracer_filter.cc110
-rw-r--r--contrib/libs/grpc/src/core/lib/config/config_vars.cc151
-rw-r--r--contrib/libs/grpc/src/core/lib/config/config_vars.h128
-rw-r--r--contrib/libs/grpc/src/core/lib/config/config_vars_non_generated.cc52
-rw-r--r--contrib/libs/grpc/src/core/lib/config/load_config.cc66
-rw-r--r--contrib/libs/grpc/src/core/lib/config/load_config.h50
-rw-r--r--contrib/libs/grpc/src/core/lib/debug/trace.cc12
-rw-r--r--contrib/libs/grpc/src/core/lib/debug/trace.h5
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/event_engine.cc39
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/handle_containers.h29
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/memory_allocator_factory.h47
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/posix_engine/ev_poll_posix.cc4
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/posix_engine/event_poller_posix_default.cc12
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_endpoint.cc63
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_endpoint.h16
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_engine.cc11
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc9
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc45
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/posix_engine/tcp_socket_utils.h3
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/resolved_address.cc3
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/windows/win_socket.cc1
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.cc211
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.h26
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.cc57
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.h3
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/windows/windows_listener.cc370
-rw-r--r--contrib/libs/grpc/src/core/lib/event_engine/windows/windows_listener.h155
-rw-r--r--contrib/libs/grpc/src/core/lib/experiments/config.cc13
-rw-r--r--contrib/libs/grpc/src/core/lib/experiments/experiments.cc7
-rw-r--r--contrib/libs/grpc/src/core/lib/experiments/experiments.h10
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/android/log.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/log_android.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/iphone/cpu.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/cpu_iphone.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/linux/cpu.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/cpu_linux.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/linux/log.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/log_linux.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/log.cc43
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/msys/tmpfile.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/tmpfile_msys.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/posix/cpu.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/cpu_posix.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/posix/log.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/log_posix.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/posix/string.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/string_posix.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/posix/sync.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/sync_posix.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/posix/time.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/time_posix.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/posix/tmpfile.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/tmpfile_posix.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/windows/cpu.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/cpu_windows.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/windows/log.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/log_windows.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/windows/string.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/string_windows.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/windows/string_util.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/string_util_windows.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/windows/sync.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/sync_windows.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/windows/time.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/time_windows.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/windows/tmpfile.cc (renamed from contrib/libs/grpc/src/core/lib/gpr/tmpfile_windows.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/fork.cc22
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/global_config.h93
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/global_config_env.cc141
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/global_config_env.h133
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/global_config_generic.h40
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/linux/env.cc (renamed from contrib/libs/grpc/src/core/lib/gprpp/env_linux.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/orphanable.h7
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/per_cpu.h12
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/posix/env.cc (renamed from contrib/libs/grpc/src/core/lib/gprpp/env_posix.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/posix/stat.cc (renamed from contrib/libs/grpc/src/core/lib/gprpp/stat_posix.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/posix/thd.cc (renamed from contrib/libs/grpc/src/core/lib/gprpp/thd_posix.cc)69
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/ref_counted.h67
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/thd.h16
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/time.cc1
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/time.h8
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/windows/env.cc (renamed from contrib/libs/grpc/src/core/lib/gprpp/env_windows.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/windows/stat.cc (renamed from contrib/libs/grpc/src/core/lib/gprpp/stat_windows.cc)0
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/windows/thd.cc (renamed from contrib/libs/grpc/src/core/lib/gprpp/thd_windows.cc)4
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/call_combiner.h4
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/endpoint_cfstream.cc6
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/ev_posix.cc66
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/ev_posix.h3
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/event_engine_shims/endpoint.cc179
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/iomgr.cc12
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/iomgr_windows.cc10
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/pollset_set_windows.cc18
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/pollset_windows.cc2
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/socket_utils_common_posix.cc19
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/tcp_client_windows.cc4
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/tcp_posix.cc1
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/tcp_server_posix.cc21
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/tcp_server_windows.cc185
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/tcp_windows.cc20
-rw-r--r--contrib/libs/grpc/src/core/lib/load_balancing/lb_policy.cc22
-rw-r--r--contrib/libs/grpc/src/core/lib/load_balancing/lb_policy.h6
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/activity.cc28
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/activity.h85
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/cancel_callback.h77
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/detail/basic_seq.h2
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/detail/promise_factory.h4
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/for_each.h177
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/if.h9
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/interceptor_list.h25
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/intra_activity_waiter.h56
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/latch.h92
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/loop.h22
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/map.h7
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/party.cc286
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/party.h500
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/pipe.h254
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/poll.h48
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/promise.h4
-rw-r--r--contrib/libs/grpc/src/core/lib/resource_quota/arena.cc22
-rw-r--r--contrib/libs/grpc/src/core/lib/resource_quota/arena.h124
-rw-r--r--contrib/libs/grpc/src/core/lib/resource_quota/memory_quota.cc2
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.cc47
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.h1
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc59
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc15
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h2
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc13
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h2
-rw-r--r--contrib/libs/grpc/src/core/lib/security/security_connector/load_system_roots_supported.cc15
-rw-r--r--contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc36
-rw-r--r--contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils_config.cc32
-rw-r--r--contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils_config.h29
-rw-r--r--contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc12
-rw-r--r--contrib/libs/grpc/src/core/lib/security/transport/secure_endpoint.cc6
-rw-r--r--contrib/libs/grpc/src/core/lib/security/transport/server_auth_filter.cc23
-rw-r--r--contrib/libs/grpc/src/core/lib/slice/slice.cc2
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/builtins.cc2
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/call.cc1950
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/call.h10
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/lame_client.cc1
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/version.cc4
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/batch_builder.cc179
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/batch_builder.h469
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/bdp_estimator.cc14
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/bdp_estimator.h17
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/custom_metadata.h30
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/metadata_batch.cc7
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/metadata_batch.h18
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/timeout_encoding.cc7
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/transport.cc32
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/transport.h84
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/transport_impl.h7
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/transport_op_string.cc94
-rw-r--r--contrib/libs/grpc/src/core/plugin_registry/grpc_plugin_registry.cc4
-rw-r--r--contrib/libs/grpc/src/core/tsi/alts/frame_protector/alts_frame_protector.cc1
-rw-r--r--contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.cc25
-rw-r--r--contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.h5
-rw-r--r--contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc2
-rw-r--r--contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc6
-rw-r--r--contrib/libs/grpc/src/cpp/client/client_interceptor.cc3
-rw-r--r--contrib/libs/grpc/src/cpp/client/client_stats_interceptor.cc40
-rw-r--r--contrib/libs/grpc/src/cpp/common/channel_filter.h13
-rw-r--r--contrib/libs/grpc/src/cpp/common/tls_certificate_verifier.cc7
-rw-r--r--contrib/libs/grpc/src/cpp/server/backend_metric_recorder.cc85
-rw-r--r--contrib/libs/grpc/src/cpp/server/backend_metric_recorder.h5
-rw-r--r--contrib/libs/grpc/third_party/README.md17
-rw-r--r--contrib/libs/grpc/ya.make68
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/CMakeLists.txt1
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.darwin-x86_64.txt45
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.linux-aarch64.txt46
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.linux-x86_64.txt46
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.txt17
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.windows-x86_64.txt45
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/commandlineflag.cc34
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/commandlineflag.h200
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/config.h68
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/declare.h73
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/flag.cc38
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/flag.h310
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/commandlineflag.cc (renamed from contrib/libs/grpc/src/core/lib/gprpp/global_config_custom.h)25
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/commandlineflag.h68
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag.cc615
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag.h800
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag_msvc.inc116
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/parse.h63
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/path_util.h62
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/private_handle_accessor.cc65
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/private_handle_accessor.h61
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/program_name.cc60
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/program_name.h50
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/registry.h97
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/sequence_lock.h187
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/usage.cc526
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/usage.h104
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/marshalling.cc241
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/marshalling.h356
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/parse.cc890
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/parse.h60
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/reflection.cc354
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/reflection.h90
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage.cc65
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage.h43
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage_config.cc165
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage_config.h135
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/flags/ya.make44
-rw-r--r--yt/yt/core/rpc/grpc/channel.cpp116
312 files changed, 17439 insertions, 7195 deletions
diff --git a/contrib/libs/grpc/CMakeLists.darwin-x86_64.txt b/contrib/libs/grpc/CMakeLists.darwin-x86_64.txt
index 306fcc0322..572d29d420 100644
--- a/contrib/libs/grpc/CMakeLists.darwin-x86_64.txt
+++ b/contrib/libs/grpc/CMakeLists.darwin-x86_64.txt
@@ -43,6 +43,7 @@ target_link_libraries(contrib-libs-grpc PUBLIC
abseil-cpp-tstring-y_absl-algorithm
abseil-cpp-tstring-y_absl-base
abseil-cpp-tstring-y_absl-container
+ abseil-cpp-tstring-y_absl-flags
abseil-cpp-tstring-y_absl-functional
abseil-cpp-tstring-y_absl-hash
abseil-cpp-tstring-y_absl-memory
@@ -105,7 +106,6 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc
@@ -133,6 +133,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_service_config_parser.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/gcp/metadata_query.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/binder_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create_impl.cc
@@ -519,6 +520,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/backoff/backoff.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/backoff/random_early_detection.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/call_tracer.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channel_args.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channel_args_preconditioning.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channel_stack.cc
@@ -529,11 +531,15 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channelz_registry.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/connected_channel.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/promise_based_filter.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/server_call_tracer_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/status_util.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/compression.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/compression_internal.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/message_compress.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/config_vars.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/config_vars_non_generated.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/core_configuration.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/load_config.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/event_log.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/histogram_view.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/stats.cc
@@ -576,56 +582,56 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/win_socket.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_listener.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/experiments/config.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/experiments/experiments.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/alloc.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/android/log.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/atm.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_iphone.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_linux.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/iphone/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/linux/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/linux/log.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_android.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_linux.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/msys/tmpfile.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/log.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/string.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/sync.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/time.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/tmpfile.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string_util_windows.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync_abseil.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time_posix.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time_precise.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time_windows.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_msys.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/log.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/string.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/string_util.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/sync.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/time.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/tmpfile.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/wrap_memcpy.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/crash.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/env_linux.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/env_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/env_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/examine_stack.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/fork.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/global_config_env.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/host_port.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/linux/env.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/load_file.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/mpscq.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/stat_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/stat_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/posix/env.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/posix/stat.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/posix/thd.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/status_helper.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/strerror.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/tchar.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/thd_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/thd_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/time.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/time_averaged_stats.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/time_util.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/validation_errors.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/windows/env.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/windows/stat.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/windows/thd.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/work_serializer.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/handshaker/proxy_mapper_registry.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/http/format_request.cc
@@ -717,6 +723,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/load_balancing/lb_policy_registry.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/matchers/matchers.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/activity.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/party.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/sleep.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/trace.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resolver/resolver.cc
@@ -783,7 +790,6 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils_config.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/transport/client_auth_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/transport/secure_endpoint.cc
@@ -821,6 +827,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/server.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/validate_metadata.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/version.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/batch_builder.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/bdp_estimator.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/connectivity_state.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/error_utils.cc
@@ -871,6 +878,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_callback.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_context.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_interceptor.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_stats_interceptor.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/create_channel.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/create_channel_internal.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/create_channel_posix.cc
diff --git a/contrib/libs/grpc/CMakeLists.linux-aarch64.txt b/contrib/libs/grpc/CMakeLists.linux-aarch64.txt
index 0bb6dd8e1a..db254378e1 100644
--- a/contrib/libs/grpc/CMakeLists.linux-aarch64.txt
+++ b/contrib/libs/grpc/CMakeLists.linux-aarch64.txt
@@ -44,6 +44,7 @@ target_link_libraries(contrib-libs-grpc PUBLIC
abseil-cpp-tstring-y_absl-algorithm
abseil-cpp-tstring-y_absl-base
abseil-cpp-tstring-y_absl-container
+ abseil-cpp-tstring-y_absl-flags
abseil-cpp-tstring-y_absl-functional
abseil-cpp-tstring-y_absl-hash
abseil-cpp-tstring-y_absl-memory
@@ -106,7 +107,6 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc
@@ -134,6 +134,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_service_config_parser.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/gcp/metadata_query.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/binder_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create_impl.cc
@@ -520,6 +521,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/backoff/backoff.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/backoff/random_early_detection.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/call_tracer.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channel_args.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channel_args_preconditioning.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channel_stack.cc
@@ -530,11 +532,15 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channelz_registry.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/connected_channel.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/promise_based_filter.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/server_call_tracer_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/status_util.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/compression.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/compression_internal.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/message_compress.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/config_vars.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/config_vars_non_generated.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/core_configuration.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/load_config.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/event_log.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/histogram_view.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/stats.cc
@@ -577,56 +583,56 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/win_socket.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_listener.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/experiments/config.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/experiments/experiments.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/alloc.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/android/log.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/atm.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_iphone.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_linux.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/iphone/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/linux/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/linux/log.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_android.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_linux.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/msys/tmpfile.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/log.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/string.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/sync.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/time.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/tmpfile.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string_util_windows.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync_abseil.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time_posix.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time_precise.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time_windows.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_msys.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/log.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/string.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/string_util.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/sync.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/time.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/tmpfile.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/wrap_memcpy.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/crash.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/env_linux.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/env_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/env_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/examine_stack.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/fork.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/global_config_env.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/host_port.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/linux/env.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/load_file.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/mpscq.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/stat_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/stat_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/posix/env.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/posix/stat.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/posix/thd.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/status_helper.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/strerror.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/tchar.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/thd_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/thd_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/time.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/time_averaged_stats.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/time_util.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/validation_errors.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/windows/env.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/windows/stat.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/windows/thd.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/work_serializer.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/handshaker/proxy_mapper_registry.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/http/format_request.cc
@@ -718,6 +724,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/load_balancing/lb_policy_registry.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/matchers/matchers.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/activity.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/party.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/sleep.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/trace.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resolver/resolver.cc
@@ -784,7 +791,6 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils_config.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/transport/client_auth_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/transport/secure_endpoint.cc
@@ -822,6 +828,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/server.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/validate_metadata.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/version.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/batch_builder.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/bdp_estimator.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/connectivity_state.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/error_utils.cc
@@ -872,6 +879,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_callback.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_context.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_interceptor.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_stats_interceptor.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/create_channel.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/create_channel_internal.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/create_channel_posix.cc
diff --git a/contrib/libs/grpc/CMakeLists.linux-x86_64.txt b/contrib/libs/grpc/CMakeLists.linux-x86_64.txt
index 0bb6dd8e1a..db254378e1 100644
--- a/contrib/libs/grpc/CMakeLists.linux-x86_64.txt
+++ b/contrib/libs/grpc/CMakeLists.linux-x86_64.txt
@@ -44,6 +44,7 @@ target_link_libraries(contrib-libs-grpc PUBLIC
abseil-cpp-tstring-y_absl-algorithm
abseil-cpp-tstring-y_absl-base
abseil-cpp-tstring-y_absl-container
+ abseil-cpp-tstring-y_absl-flags
abseil-cpp-tstring-y_absl-functional
abseil-cpp-tstring-y_absl-hash
abseil-cpp-tstring-y_absl-memory
@@ -106,7 +107,6 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc
@@ -134,6 +134,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_service_config_parser.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/gcp/metadata_query.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/binder_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create_impl.cc
@@ -520,6 +521,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/backoff/backoff.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/backoff/random_early_detection.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/call_tracer.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channel_args.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channel_args_preconditioning.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channel_stack.cc
@@ -530,11 +532,15 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channelz_registry.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/connected_channel.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/promise_based_filter.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/server_call_tracer_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/status_util.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/compression.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/compression_internal.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/message_compress.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/config_vars.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/config_vars_non_generated.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/core_configuration.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/load_config.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/event_log.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/histogram_view.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/stats.cc
@@ -577,56 +583,56 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/win_socket.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_listener.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/experiments/config.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/experiments/experiments.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/alloc.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/android/log.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/atm.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_iphone.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_linux.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/iphone/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/linux/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/linux/log.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_android.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_linux.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/msys/tmpfile.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/log.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/string.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/sync.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/time.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/tmpfile.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string_util_windows.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync_abseil.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time_posix.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time_precise.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time_windows.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_msys.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/log.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/string.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/string_util.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/sync.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/time.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/tmpfile.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/wrap_memcpy.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/crash.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/env_linux.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/env_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/env_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/examine_stack.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/fork.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/global_config_env.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/host_port.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/linux/env.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/load_file.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/mpscq.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/stat_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/stat_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/posix/env.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/posix/stat.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/posix/thd.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/status_helper.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/strerror.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/tchar.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/thd_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/thd_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/time.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/time_averaged_stats.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/time_util.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/validation_errors.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/windows/env.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/windows/stat.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/windows/thd.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/work_serializer.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/handshaker/proxy_mapper_registry.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/http/format_request.cc
@@ -718,6 +724,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/load_balancing/lb_policy_registry.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/matchers/matchers.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/activity.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/party.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/sleep.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/trace.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resolver/resolver.cc
@@ -784,7 +791,6 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils_config.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/transport/client_auth_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/transport/secure_endpoint.cc
@@ -822,6 +828,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/server.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/validate_metadata.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/version.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/batch_builder.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/bdp_estimator.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/connectivity_state.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/error_utils.cc
@@ -872,6 +879,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_callback.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_context.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_interceptor.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_stats_interceptor.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/create_channel.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/create_channel_internal.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/create_channel_posix.cc
diff --git a/contrib/libs/grpc/CMakeLists.windows-x86_64.txt b/contrib/libs/grpc/CMakeLists.windows-x86_64.txt
index 6a6ffd925a..be7c6442d8 100644
--- a/contrib/libs/grpc/CMakeLists.windows-x86_64.txt
+++ b/contrib/libs/grpc/CMakeLists.windows-x86_64.txt
@@ -42,6 +42,7 @@ target_link_libraries(contrib-libs-grpc PUBLIC
abseil-cpp-tstring-y_absl-algorithm
abseil-cpp-tstring-y_absl-base
abseil-cpp-tstring-y_absl-container
+ abseil-cpp-tstring-y_absl-flags
abseil-cpp-tstring-y_absl-functional
abseil-cpp-tstring-y_absl-hash
abseil-cpp-tstring-y_absl-memory
@@ -104,7 +105,6 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc
@@ -132,6 +132,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_service_config_parser.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/gcp/metadata_query.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/binder_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create_impl.cc
@@ -518,6 +519,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/backoff/backoff.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/backoff/random_early_detection.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/call_tracer.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channel_args.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channel_args_preconditioning.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channel_stack.cc
@@ -528,11 +530,15 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/channelz_registry.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/connected_channel.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/promise_based_filter.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/server_call_tracer_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/status_util.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/compression.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/compression_internal.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/message_compress.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/config_vars.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/config_vars_non_generated.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/core_configuration.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/load_config.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/event_log.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/histogram_view.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/stats.cc
@@ -575,56 +581,56 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/win_socket.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_listener.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/experiments/config.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/experiments/experiments.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/alloc.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/android/log.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/atm.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_iphone.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_linux.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/cpu_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/iphone/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/linux/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/linux/log.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_android.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_linux.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/log_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/msys/tmpfile.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/log.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/string.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/sync.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/time.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/posix/tmpfile.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string_util_windows.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/string_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync_abseil.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/sync_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time_posix.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time_precise.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/time_windows.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_msys.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/cpu.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/log.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/string.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/string_util.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/sync.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/time.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/windows/tmpfile.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/wrap_memcpy.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/crash.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/env_linux.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/env_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/env_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/examine_stack.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/fork.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/global_config_env.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/host_port.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/linux/env.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/load_file.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/mpscq.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/stat_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/stat_windows.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/posix/env.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/posix/stat.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/posix/thd.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/status_helper.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/strerror.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/tchar.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/thd_posix.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/thd_windows.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/time.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/time_averaged_stats.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/time_util.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/validation_errors.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/windows/env.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/windows/stat.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/windows/thd.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/work_serializer.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/handshaker/proxy_mapper_registry.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/http/format_request.cc
@@ -716,6 +722,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/load_balancing/lb_policy_registry.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/matchers/matchers.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/activity.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/party.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/sleep.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/trace.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resolver/resolver.cc
@@ -782,7 +789,6 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc
- ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils_config.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/transport/client_auth_filter.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/transport/secure_endpoint.cc
@@ -820,6 +826,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/server.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/validate_metadata.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/version.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/batch_builder.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/bdp_estimator.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/connectivity_state.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/error_utils.cc
@@ -870,6 +877,7 @@ target_sources(contrib-libs-grpc PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_callback.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_context.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_interceptor.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/client_stats_interceptor.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/create_channel.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/create_channel_internal.cc
${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/cpp/client/create_channel_posix.cc
diff --git a/contrib/libs/grpc/include/grpc/event_engine/event_engine.h b/contrib/libs/grpc/include/grpc/event_engine/event_engine.h
index 3f466721b9..07afeb67a0 100644
--- a/contrib/libs/grpc/include/grpc/event_engine/event_engine.h
+++ b/contrib/libs/grpc/include/grpc/event_engine/event_engine.h
@@ -122,15 +122,21 @@ class EventEngine : public std::enable_shared_from_this<EventEngine> {
/// \a Cancel method.
struct TaskHandle {
intptr_t keys[2];
+ static const TaskHandle kInvalid;
+ friend bool operator==(const TaskHandle& lhs, const TaskHandle& rhs);
+ friend bool operator!=(const TaskHandle& lhs, const TaskHandle& rhs);
};
- static constexpr TaskHandle kInvalidTaskHandle{-1, -1};
/// A handle to a cancellable connection attempt.
///
/// Returned by \a Connect, and can be passed to \a CancelConnect.
struct ConnectionHandle {
intptr_t keys[2];
+ static const ConnectionHandle kInvalid;
+ friend bool operator==(const ConnectionHandle& lhs,
+ const ConnectionHandle& rhs);
+ friend bool operator!=(const ConnectionHandle& lhs,
+ const ConnectionHandle& rhs);
};
- static constexpr ConnectionHandle kInvalidConnectionHandle{-1, -1};
/// Thin wrapper around a platform-specific sockaddr type. A sockaddr struct
/// exists on all platforms that gRPC supports.
///
@@ -181,10 +187,13 @@ class EventEngine : public std::enable_shared_from_this<EventEngine> {
/// Reads data from the Endpoint.
///
/// When data is available on the connection, that data is moved into the
- /// \a buffer, and the \a on_read callback is called. The caller must ensure
- /// that the callback has access to the buffer when executed later.
- /// Ownership of the buffer is not transferred. Valid slices *may* be placed
- /// into the buffer even if the callback is invoked with a non-OK Status.
+ /// \a buffer. If the read succeeds immediately, it returns true and the \a
+ /// on_read callback is not executed. Otherwise it returns false and the \a
+ /// on_read callback executes asynchronously when the read completes. The
+ /// caller must ensure that the callback has access to the buffer when it
+ /// executes. Ownership of the buffer is not transferred. Valid slices *may*
+ /// be placed into the buffer even if the callback is invoked with a non-OK
+ /// Status.
///
/// There can be at most one outstanding read per Endpoint at any given
/// time. An outstanding read is one in which the \a on_read callback has
@@ -195,7 +204,7 @@ class EventEngine : public std::enable_shared_from_this<EventEngine> {
/// For failed read operations, implementations should pass the appropriate
/// statuses to \a on_read. For example, callbacks might expect to receive
/// CANCELLED on endpoint shutdown.
- virtual void Read(y_absl::AnyInvocable<void(y_absl::Status)> on_read,
+ virtual bool Read(y_absl::AnyInvocable<void(y_absl::Status)> on_read,
SliceBuffer* buffer, const ReadArgs* args) = 0;
/// A struct representing optional arguments that may be provided to an
/// EventEngine Endpoint Write API call.
@@ -213,12 +222,14 @@ class EventEngine : public std::enable_shared_from_this<EventEngine> {
};
/// Writes data out on the connection.
///
- /// \a on_writable is called when the connection is ready for more data. The
- /// Slices within the \a data buffer may be mutated at will by the Endpoint
- /// until \a on_writable is called. The \a data SliceBuffer will remain
- /// valid after calling \a Write, but its state is otherwise undefined. All
- /// bytes in \a data must have been written before calling \a on_writable
- /// unless an error has occurred.
+ /// If the write succeeds immediately, it returns true and the
+ /// \a on_writable callback is not executed. Otherwise it returns false and
+ /// the \a on_writable callback is called asynchronously when the connection
+ /// is ready for more data. The Slices within the \a data buffer may be
+ /// mutated at will by the Endpoint until \a on_writable is called. The \a
+ /// data SliceBuffer will remain valid after calling \a Write, but its state
+ /// is otherwise undefined. All bytes in \a data must have been written
+ /// before calling \a on_writable unless an error has occurred.
///
/// There can be at most one outstanding write per Endpoint at any given
/// time. An outstanding write is one in which the \a on_writable callback
@@ -229,7 +240,7 @@ class EventEngine : public std::enable_shared_from_this<EventEngine> {
/// For failed write operations, implementations should pass the appropriate
/// statuses to \a on_writable. For example, callbacks might expect to
/// receive CANCELLED on endpoint shutdown.
- virtual void Write(y_absl::AnyInvocable<void(y_absl::Status)> on_writable,
+ virtual bool Write(y_absl::AnyInvocable<void(y_absl::Status)> on_writable,
SliceBuffer* data, const WriteArgs* args) = 0;
/// Returns an address in the format described in DNSResolver. The returned
/// values are expected to remain valid for the life of the Endpoint.
@@ -314,6 +325,11 @@ class EventEngine : public std::enable_shared_from_this<EventEngine> {
/// Task handle for DNS Resolution requests.
struct LookupTaskHandle {
intptr_t keys[2];
+ static const LookupTaskHandle kInvalid;
+ friend bool operator==(const LookupTaskHandle& lhs,
+ const LookupTaskHandle& rhs);
+ friend bool operator!=(const LookupTaskHandle& lhs,
+ const LookupTaskHandle& rhs);
};
/// Optional configuration for DNSResolvers.
struct ResolverOptions {
diff --git a/contrib/libs/grpc/include/grpc/grpc_security.h b/contrib/libs/grpc/include/grpc/grpc_security.h
index 63810f6fa9..d7ea4cc669 100644
--- a/contrib/libs/grpc/include/grpc/grpc_security.h
+++ b/contrib/libs/grpc/include/grpc/grpc_security.h
@@ -931,6 +931,10 @@ typedef struct grpc_tls_custom_verification_check_request {
* grpc_security_constants.h.
* TODO(ZhenLian): Consider fixing this in the future. */
const char* peer_cert_full_chain;
+ /* The verified root cert subject.
+ * This value will only be filled if the cryptographic peer certificate
+ * verification was successful */
+ const char* verified_root_cert_subject;
} peer_info;
} grpc_tls_custom_verification_check_request;
diff --git a/contrib/libs/grpc/include/grpc/support/port_platform.h b/contrib/libs/grpc/include/grpc/support/port_platform.h
index 9f9cac0054..1e99dc628e 100644
--- a/contrib/libs/grpc/include/grpc/support/port_platform.h
+++ b/contrib/libs/grpc/include/grpc/support/port_platform.h
@@ -625,7 +625,7 @@ typedef unsigned __int64 uint64_t;
#define GPR_ATTRIBUTE_NORETURN
#endif
-#if GPR_FORBID_UNREACHABLE_CODE
+#if defined(GPR_FORBID_UNREACHABLE_CODE) && GPR_FORBID_UNREACHABLE_CODE
#define GPR_UNREACHABLE_CODE(STATEMENT)
#else
#ifdef __cplusplus
@@ -776,12 +776,12 @@ extern void gpr_unreachable_code(const char* reason, const char* file,
#define GRPC_CALLBACK_API_NONEXPERIMENTAL
-/* clang 11 with msan miscompiles destruction of [[no_unique_address]] members
- * of zero size - for a repro see:
+/* clang 12 and lower with msan miscompiles destruction of [[no_unique_address]]
+ * members of zero size - for a repro see:
* test/core/compiler_bugs/miscompile_with_no_unique_address_test.cc
*/
#ifdef __clang__
-#if __clang__ && __clang_major__ <= 11 && __has_feature(memory_sanitizer)
+#if __clang__ && __clang_major__ <= 12 && __has_feature(memory_sanitizer)
#undef GPR_NO_UNIQUE_ADDRESS
#define GPR_NO_UNIQUE_ADDRESS
#endif
diff --git a/contrib/libs/grpc/include/grpcpp/alarm.h b/contrib/libs/grpc/include/grpcpp/alarm.h
index 319fc29f1e..b35dca2771 100644
--- a/contrib/libs/grpc/include/grpcpp/alarm.h
+++ b/contrib/libs/grpc/include/grpcpp/alarm.h
@@ -71,8 +71,7 @@ class Alarm : private grpc::internal::GrpcLibrary {
/// Alarms are movable.
Alarm(Alarm&& rhs) noexcept : alarm_(rhs.alarm_) { rhs.alarm_ = nullptr; }
Alarm& operator=(Alarm&& rhs) noexcept {
- alarm_ = rhs.alarm_;
- rhs.alarm_ = nullptr;
+ std::swap(alarm_, rhs.alarm_);
return *this;
}
diff --git a/contrib/libs/grpc/include/grpcpp/ext/call_metric_recorder.h b/contrib/libs/grpc/include/grpcpp/ext/call_metric_recorder.h
index 66a0e99d33..9e40770187 100644
--- a/contrib/libs/grpc/include/grpcpp/ext/call_metric_recorder.h
+++ b/contrib/libs/grpc/include/grpcpp/ext/call_metric_recorder.h
@@ -54,6 +54,11 @@ class CallMetricRecorder {
/// Values outside of the valid range [0, infy) are ignored.
virtual CallMetricRecorder& RecordQpsMetric(double value) = 0;
+ /// Records a call metric measurement for errors per second.
+ /// Multiple calls to this method will override the stored value.
+ /// Values outside of the valid range [0, infy) are ignored.
+ virtual CallMetricRecorder& RecordEpsMetric(double value) = 0;
+
/// Records a call metric measurement for utilization.
/// Multiple calls to this method with the same name will
/// override the corresponding stored value. The lifetime of the
@@ -74,6 +79,16 @@ class CallMetricRecorder {
/// are global constants.
virtual CallMetricRecorder& RecordRequestCostMetric(string_ref name,
double value) = 0;
+
+ /// Records an application-specific opaque metric measurement.
+ /// Multiple calls to this method with the same name will
+ /// override the corresponding stored value. The lifetime of the
+ /// name string needs to be longer than the lifetime of the RPC
+ /// itself, since it's going to be sent as trailers after the RPC
+ /// finishes. It is assumed the strings are common names that
+ /// are global constants.
+ virtual CallMetricRecorder& RecordNamedMetric(string_ref name,
+ double value) = 0;
};
} // namespace experimental
diff --git a/contrib/libs/grpc/include/grpcpp/ext/server_metric_recorder.h b/contrib/libs/grpc/include/grpcpp/ext/server_metric_recorder.h
index 6333072214..2fa3eae267 100644
--- a/contrib/libs/grpc/include/grpcpp/ext/server_metric_recorder.h
+++ b/contrib/libs/grpc/include/grpcpp/ext/server_metric_recorder.h
@@ -55,6 +55,10 @@ class ServerMetricRecorder {
/// Values outside of the valid range are rejected.
/// Overrides the stored value when called again with a valid value.
void SetQps(double value);
+ /// Records number of errors per second to the server in the range [0, infy).
+ /// Values outside of the valid range are rejected.
+ /// Overrides the stored value when called again with a valid value.
+ void SetEps(double value);
/// Records a named resource utilization value in the range [0, 1].
/// Values outside of the valid range are rejected.
/// Overrides the stored value when called again with the same name.
@@ -74,6 +78,8 @@ class ServerMetricRecorder {
void ClearMemoryUtilization();
/// Clears number of queries per second to the server if recorded.
void ClearQps();
+ /// Clears number of errors per second to the server if recorded.
+ void ClearEps();
/// Clears a named utilization value if exists.
void ClearNamedUtilization(string_ref name);
diff --git a/contrib/libs/grpc/include/grpcpp/security/tls_certificate_verifier.h b/contrib/libs/grpc/include/grpcpp/security/tls_certificate_verifier.h
index 9d0d65a2bf..6c5a91ee74 100644
--- a/contrib/libs/grpc/include/grpcpp/security/tls_certificate_verifier.h
+++ b/contrib/libs/grpc/include/grpcpp/security/tls_certificate_verifier.h
@@ -62,6 +62,13 @@ class TlsCustomVerificationCheckRequest {
grpc::string_ref peer_cert() const;
grpc::string_ref peer_cert_full_chain() const;
grpc::string_ref common_name() const;
+ // The subject name of the root certificate used to verify the peer chain
+ // If verification fails or the peer cert is self-signed, this will be an
+ // empty string. If verification is successful, it is a comma-separated list,
+ // where the entries are of the form "FIELD_ABBREVIATION=string"
+ // ex: "CN=testca,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU"
+ // ex: "CN=GTS Root R1,O=Google Trust Services LLC,C=US"
+ grpc::string_ref verified_root_cert_subject() const;
std::vector<grpc::string_ref> uri_names() const;
std::vector<grpc::string_ref> dns_names() const;
std::vector<grpc::string_ref> email_names() const;
diff --git a/contrib/libs/grpc/include/grpcpp/support/client_interceptor.h b/contrib/libs/grpc/include/grpcpp/support/client_interceptor.h
index ef84d18439..b2b9dc7691 100644
--- a/contrib/libs/grpc/include/grpcpp/support/client_interceptor.h
+++ b/contrib/libs/grpc/include/grpcpp/support/client_interceptor.h
@@ -57,7 +57,10 @@ class ClientInterceptorFactoryInterface {
namespace internal {
extern experimental::ClientInterceptorFactoryInterface*
g_global_client_interceptor_factory;
-}
+
+extern experimental::ClientInterceptorFactoryInterface*
+ g_global_client_stats_interceptor_factory;
+} // namespace internal
/// ClientRpcInfo represents the state of a particular RPC as it
/// appears to an interceptor. It is created and owned by the library and
@@ -144,10 +147,22 @@ class ClientRpcInfo {
const std::vector<std::unique_ptr<
experimental::ClientInterceptorFactoryInterface>>& creators,
size_t interceptor_pos) {
- if (interceptor_pos > creators.size()) {
+ // TODO(yashykt): This calculation seems broken for the case where an
+ // interceptor factor returns nullptr.
+ size_t num_interceptors =
+ creators.size() +
+ (internal::g_global_client_stats_interceptor_factory != nullptr) +
+ (internal::g_global_client_interceptor_factory != nullptr);
+ if (interceptor_pos > num_interceptors) {
// No interceptors to register
return;
}
+ if (internal::g_global_client_stats_interceptor_factory != nullptr) {
+ interceptors_.push_back(std::unique_ptr<experimental::Interceptor>(
+ internal::g_global_client_stats_interceptor_factory
+ ->CreateClientInterceptor(this)));
+ --interceptor_pos;
+ }
// NOTE: The following is not a range-based for loop because it will only
// iterate over a portion of the creators vector.
for (auto it = creators.begin() + interceptor_pos; it != creators.end();
diff --git a/contrib/libs/grpc/include/grpcpp/version_info.h b/contrib/libs/grpc/include/grpcpp/version_info.h
index 13742e57c7..b24fbff552 100644
--- a/contrib/libs/grpc/include/grpcpp/version_info.h
+++ b/contrib/libs/grpc/include/grpcpp/version_info.h
@@ -19,9 +19,9 @@
#define GRPCPP_VERSION_INFO_H
#define GRPC_CPP_VERSION_MAJOR 1
-#define GRPC_CPP_VERSION_MINOR 53
-#define GRPC_CPP_VERSION_PATCH 1
+#define GRPC_CPP_VERSION_MINOR 54
+#define GRPC_CPP_VERSION_PATCH 2
#define GRPC_CPP_VERSION_TAG ""
-#define GRPC_CPP_VERSION_STRING "1.53.1"
+#define GRPC_CPP_VERSION_STRING "1.54.2"
#endif // GRPCPP_VERSION_INFO_H
diff --git a/contrib/libs/grpc/src/core/ext/filters/backend_metrics/backend_metric_filter.cc b/contrib/libs/grpc/src/core/ext/filters/backend_metrics/backend_metric_filter.cc
index 1c8de12c43..eaa8bd0d0d 100644
--- a/contrib/libs/grpc/src/core/ext/filters/backend_metrics/backend_metric_filter.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/backend_metrics/backend_metric_filter.cc
@@ -71,6 +71,10 @@ y_absl::optional<TString> BackendMetricFilter::MaybeSerializeBackendMetrics(
xds_data_orca_v3_OrcaLoadReport_set_rps_fractional(response, data.qps);
has_data = true;
}
+ if (data.eps != -1) {
+ xds_data_orca_v3_OrcaLoadReport_set_eps(response, data.eps);
+ has_data = true;
+ }
for (const auto& p : data.request_cost) {
xds_data_orca_v3_OrcaLoadReport_request_cost_set(
response,
@@ -85,6 +89,13 @@ y_absl::optional<TString> BackendMetricFilter::MaybeSerializeBackendMetrics(
p.second, arena.ptr());
has_data = true;
}
+ for (const auto& p : data.named_metrics) {
+ xds_data_orca_v3_OrcaLoadReport_named_metrics_set(
+ response,
+ upb_StringView_FromDataAndSize(p.first.data(), p.first.size()),
+ p.second, arena.ptr());
+ has_data = true;
+ }
if (!has_data) {
return y_absl::nullopt;
}
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/backend_metric.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/backend_metric.cc
index 4b49e3f97c..b57f40322c 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/backend_metric.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/backend_metric.cc
@@ -70,6 +70,7 @@ const BackendMetricData* ParseBackendMetricData(
xds_data_orca_v3_OrcaLoadReport_mem_utilization(msg);
backend_metric_data->qps =
xds_data_orca_v3_OrcaLoadReport_rps_fractional(msg);
+ backend_metric_data->eps = xds_data_orca_v3_OrcaLoadReport_eps(msg);
backend_metric_data->request_cost =
ParseMap<xds_data_orca_v3_OrcaLoadReport_RequestCostEntry>(
msg, xds_data_orca_v3_OrcaLoadReport_request_cost_next,
@@ -80,6 +81,11 @@ const BackendMetricData* ParseBackendMetricData(
msg, xds_data_orca_v3_OrcaLoadReport_utilization_next,
xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_key,
xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_value, allocator);
+ backend_metric_data->named_metrics =
+ ParseMap<xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry>(
+ msg, xds_data_orca_v3_OrcaLoadReport_named_metrics_next,
+ xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry_key,
+ xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry_value, allocator);
return backend_metric_data;
}
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/backup_poller.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/backup_poller.cc
index 660e8ba253..66d3ce2b47 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/backup_poller.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/backup_poller.cc
@@ -28,7 +28,7 @@
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
-#include "src/core/lib/gprpp/global_config.h"
+#include "src/core/lib/config/config_vars.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/closure.h"
@@ -61,19 +61,10 @@ static backup_poller* g_poller = nullptr; // guarded by g_poller_mu
static grpc_core::Duration g_poll_interval =
grpc_core::Duration::Milliseconds(DEFAULT_POLL_INTERVAL_MS);
-GPR_GLOBAL_CONFIG_DEFINE_INT32(
- grpc_client_channel_backup_poll_interval_ms, DEFAULT_POLL_INTERVAL_MS,
- "Declares the interval in ms between two backup polls on client channels. "
- "These polls are run in the timer thread so that gRPC can process "
- "connection failures while there is no active polling thread. "
- "They help reconnect disconnected client channels (mostly due to "
- "idleness), so that the next RPC on this channel won't fail. Set to 0 to "
- "turn off the backup polls.");
-
void grpc_client_channel_global_init_backup_polling() {
gpr_mu_init(&g_poller_mu);
int32_t poll_interval_ms =
- GPR_GLOBAL_CONFIG_GET(grpc_client_channel_backup_poll_interval_ms);
+ grpc_core::ConfigVars::Get().ClientChannelBackupPollIntervalMs();
if (poll_interval_ms < 0) {
gpr_log(GPR_ERROR,
"Invalid GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS: %d, "
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/backup_poller.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/backup_poller.h
index 6c03b788d3..e2982bbe3c 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/backup_poller.h
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/backup_poller.h
@@ -21,11 +21,8 @@
#include <grpc/support/port_platform.h>
-#include "src/core/lib/gprpp/global_config_generic.h"
#include "src/core/lib/iomgr/iomgr_fwd.h"
-GPR_GLOBAL_CONFIG_DECLARE_INT32(grpc_client_channel_backup_poll_interval_ms);
-
// Initializes backup polling.
void grpc_client_channel_global_init_backup_polling();
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.cc
index 4e31f34091..ebdd04e36d 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.cc
@@ -24,9 +24,11 @@
#include <algorithm>
#include <functional>
#include <new>
-#include <set>
+#include <type_traits>
+#include <utility>
#include <vector>
+#include "y_absl/cleanup/cleanup.h"
#include "y_absl/status/status.h"
#include "y_absl/status/statusor.h"
#include "y_absl/strings/cord.h"
@@ -47,6 +49,7 @@
#include "src/core/ext/filters/client_channel/backend_metric.h"
#include "src/core/ext/filters/client_channel/backup_poller.h"
#include "src/core/ext/filters/client_channel/client_channel_channelz.h"
+#include "src/core/ext/filters/client_channel/client_channel_internal.h"
#include "src/core/ext/filters/client_channel/client_channel_service_config.h"
#include "src/core/ext/filters/client_channel/config_selector.h"
#include "src/core/ext/filters/client_channel/dynamic_filters.h"
@@ -67,6 +70,7 @@
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/gprpp/sync.h"
+#include "src/core/lib/gprpp/unique_type_name.h"
#include "src/core/lib/gprpp/work_serializer.h"
#include "src/core/lib/handshaker/proxy_mapper_registry.h"
#include "src/core/lib/iomgr/exec_ctx.h"
@@ -79,6 +83,7 @@
#include "src/core/lib/resolver/server_address.h"
#include "src/core/lib/service_config/service_config_call_data.h"
#include "src/core/lib/service_config/service_config_impl.h"
+#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/connectivity_state.h"
@@ -106,6 +111,75 @@ TraceFlag grpc_client_channel_lb_call_trace(false, "client_channel_lb_call");
class ClientChannel::CallData {
public:
+ // Removes the call from the channel's list of calls queued
+ // for name resolution.
+ void RemoveCallFromResolverQueuedCallsLocked()
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_);
+
+ // Called by the channel for each queued call when a new resolution
+ // result becomes available.
+ virtual void RetryCheckResolutionLocked()
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_) = 0;
+
+ RefCountedPtr<DynamicFilters> dynamic_filters() const {
+ return dynamic_filters_;
+ }
+
+ protected:
+ CallData() = default;
+ virtual ~CallData() = default;
+
+ // Checks whether a resolver result is available. The following
+ // outcomes are possible:
+ // - No resolver result is available yet. The call will be queued and
+ // y_absl::nullopt will be returned. Later, when a resolver result
+ // becomes available, RetryCheckResolutionLocked() will be called.
+ // - The resolver has returned a transient failure. If the call is
+ // not wait_for_ready, a non-OK status will be returned. (If the
+ // call *is* wait_for_ready, it will be queued instead.)
+ // - There is a valid resolver result. The service config will be
+ // stored in the call context and an OK status will be returned.
+ y_absl::optional<y_absl::Status> CheckResolution(bool was_queued);
+
+ private:
+ // Accessors for data stored in the subclass.
+ virtual ClientChannel* chand() const = 0;
+ virtual Arena* arena() const = 0;
+ virtual grpc_polling_entity* pollent() const = 0;
+ virtual grpc_metadata_batch* send_initial_metadata() = 0;
+ virtual grpc_call_context_element* call_context() const = 0;
+
+ // Helper function for CheckResolution(). Returns true if the call
+ // can continue (i.e., there is a valid resolution result, or there is
+ // an invalid resolution result but the call is not wait_for_ready).
+ bool CheckResolutionLocked(
+ y_absl::StatusOr<RefCountedPtr<ConfigSelector>>* config_selector)
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_);
+
+ // Adds the call to the channel's list of calls queued for name resolution.
+ void AddCallToResolverQueuedCallsLocked()
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_);
+
+ // Called when adding the call to the resolver queue.
+ virtual void OnAddToQueueLocked()
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_) {}
+
+ // Applies service config to the call. Must be invoked once we know
+ // that the resolver has returned results to the channel.
+ // If an error is returned, the error indicates the status with which
+ // the call should be failed.
+ grpc_error_handle ApplyServiceConfigToCallLocked(
+ const y_absl::StatusOr<RefCountedPtr<ConfigSelector>>& config_selector);
+
+ // Called to reset the deadline based on the service config obtained
+ // from the resolver.
+ virtual void ResetDeadline(Duration timeout) = 0;
+
+ RefCountedPtr<DynamicFilters> dynamic_filters_;
+};
+
+class ClientChannel::FilterBasedCallData : public ClientChannel::CallData {
+ public:
static grpc_error_handle Init(grpc_call_element* elem,
const grpc_call_element_args* args);
static void Destroy(grpc_call_element* elem,
@@ -115,31 +189,33 @@ class ClientChannel::CallData {
grpc_call_element* elem, grpc_transport_stream_op_batch* batch);
static void SetPollent(grpc_call_element* elem, grpc_polling_entity* pollent);
- // Invoked by channel for queued calls when name resolution is completed.
- static void CheckResolution(void* arg, grpc_error_handle error);
- // Helper function for applying the service config to a call while
- // holding ClientChannel::resolution_mu_.
- // Returns true if the service config has been applied to the call, in which
- // case the caller must invoke ResolutionDone() or AsyncResolutionDone()
- // with the returned error.
- bool CheckResolutionLocked(grpc_call_element* elem, grpc_error_handle* error)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_);
- // Schedules a callback to continue processing the call once
- // resolution is complete. The callback will not run until after this
- // method returns.
- void AsyncResolutionDone(grpc_call_element* elem, grpc_error_handle error);
-
private:
class ResolverQueuedCallCanceller;
- CallData(grpc_call_element* elem, const ClientChannel& chand,
- const grpc_call_element_args& args);
- ~CallData();
+ FilterBasedCallData(grpc_call_element* elem,
+ const grpc_call_element_args& args);
+ ~FilterBasedCallData() override;
+
+ grpc_call_element* elem() const { return deadline_state_.elem; }
+ grpc_call_stack* owning_call() const { return deadline_state_.call_stack; }
+ CallCombiner* call_combiner() const { return deadline_state_.call_combiner; }
+
+ ClientChannel* chand() const override {
+ return static_cast<ClientChannel*>(elem()->channel_data);
+ }
+ Arena* arena() const override { return deadline_state_.arena; }
+ grpc_polling_entity* pollent() const override { return pollent_; }
+ grpc_metadata_batch* send_initial_metadata() override {
+ return pending_batches_[0]
+ ->payload->send_initial_metadata.send_initial_metadata;
+ }
+ grpc_call_context_element* call_context() const override {
+ return call_context_;
+ }
// Returns the index into pending_batches_ to be used for batch.
static size_t GetBatchIndex(grpc_transport_stream_op_batch* batch);
- void PendingBatchesAdd(grpc_call_element* elem,
- grpc_transport_stream_op_batch* batch);
+ void PendingBatchesAdd(grpc_transport_stream_op_batch* batch);
static void FailPendingBatchInCallCombiner(void* arg,
grpc_error_handle error);
// A predicate type and some useful implementations for PendingBatchesFail().
@@ -159,67 +235,55 @@ class ClientChannel::CallData {
// If yield_call_combiner_predicate returns true, assumes responsibility for
// yielding the call combiner.
void PendingBatchesFail(
- grpc_call_element* elem, grpc_error_handle error,
+ grpc_error_handle error,
YieldCallCombinerPredicate yield_call_combiner_predicate);
static void ResumePendingBatchInCallCombiner(void* arg,
grpc_error_handle ignored);
- // Resumes all pending batches on lb_call_.
- void PendingBatchesResume(grpc_call_element* elem);
+ // Resumes all pending batches on dynamic_call_.
+ void PendingBatchesResume();
- // Applies service config to the call. Must be invoked once we know
- // that the resolver has returned results to the channel.
- // If an error is returned, the error indicates the status with which
- // the call should be failed.
- grpc_error_handle ApplyServiceConfigToCallLocked(
- grpc_call_element* elem, grpc_metadata_batch* initial_metadata)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_);
- // Invoked when the resolver result is applied to the caller, on both
- // success or failure.
- static void ResolutionDone(void* arg, grpc_error_handle error);
- // Removes the call (if present) from the channel's list of calls queued
- // for name resolution.
- void MaybeRemoveCallFromResolverQueuedCallsLocked(grpc_call_element* elem)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_);
- // Adds the call (if not already present) to the channel's list of
- // calls queued for name resolution.
- void MaybeAddCallToResolverQueuedCallsLocked(grpc_call_element* elem)
+ // Called to check for a resolution result, both when the call is
+ // initially started and when it is queued and the channel gets a new
+ // resolution result.
+ void TryCheckResolution(bool was_queued);
+
+ void OnAddToQueueLocked() override
Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_);
- static void RecvTrailingMetadataReadyForConfigSelectorCommitCallback(
- void* arg, grpc_error_handle error);
+ void RetryCheckResolutionLocked() override
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_);
- void CreateDynamicCall(grpc_call_element* elem);
+ void ResetDeadline(Duration timeout) override {
+ const Timestamp per_method_deadline =
+ Timestamp::FromCycleCounterRoundUp(call_start_time_) + timeout;
+ if (per_method_deadline < deadline_) {
+ deadline_ = per_method_deadline;
+ grpc_deadline_state_reset(&deadline_state_, deadline_);
+ }
+ }
- Arena* arena() const { return deadline_state_.arena; }
- grpc_call_stack* owning_call() const { return deadline_state_.call_stack; }
- CallCombiner* call_combiner() const { return deadline_state_.call_combiner; }
+ void CreateDynamicCall();
- // State for handling deadlines.
- grpc_deadline_state deadline_state_;
+ static void RecvTrailingMetadataReadyForConfigSelectorCommitCallback(
+ void* arg, grpc_error_handle error);
grpc_slice path_; // Request path.
+ grpc_call_context_element* call_context_;
gpr_cycle_counter call_start_time_;
Timestamp deadline_;
- grpc_call_context_element* call_context_;
- grpc_polling_entity* pollent_ = nullptr;
+ // State for handling deadlines.
+ grpc_deadline_state deadline_state_;
- grpc_closure resolution_done_closure_;
+ grpc_polling_entity* pollent_ = nullptr;
// Accessed while holding ClientChannel::resolution_mu_.
- bool service_config_applied_ Y_ABSL_GUARDED_BY(&ClientChannel::resolution_mu_) =
- false;
- bool queued_pending_resolver_result_
- Y_ABSL_GUARDED_BY(&ClientChannel::resolution_mu_) = false;
- ClientChannel::ResolverQueuedCall resolver_queued_call_
- Y_ABSL_GUARDED_BY(&ClientChannel::resolution_mu_);
ResolverQueuedCallCanceller* resolver_call_canceller_
Y_ABSL_GUARDED_BY(&ClientChannel::resolution_mu_) = nullptr;
grpc_closure* original_recv_trailing_metadata_ready_ = nullptr;
grpc_closure recv_trailing_metadata_ready_;
- RefCountedPtr<DynamicFilters> dynamic_filters_;
RefCountedPtr<DynamicFilters::Call> dynamic_call_;
// Batches are added to this list when received from above.
@@ -238,13 +302,13 @@ class ClientChannel::CallData {
//
const grpc_channel_filter ClientChannel::kFilterVtable = {
- ClientChannel::CallData::StartTransportStreamOpBatch,
+ ClientChannel::FilterBasedCallData::StartTransportStreamOpBatch,
nullptr,
ClientChannel::StartTransportOp,
- sizeof(ClientChannel::CallData),
- ClientChannel::CallData::Init,
- ClientChannel::CallData::SetPollent,
- ClientChannel::CallData::Destroy,
+ sizeof(ClientChannel::FilterBasedCallData),
+ ClientChannel::FilterBasedCallData::Init,
+ ClientChannel::FilterBasedCallData::SetPollent,
+ ClientChannel::FilterBasedCallData::Destroy,
sizeof(ClientChannel),
ClientChannel::Init,
grpc_channel_stack_no_post_init,
@@ -363,7 +427,7 @@ class DynamicTerminationFilter::CallData {
CallCombiner* call_combiner_;
grpc_call_context_element* call_context_;
- OrphanablePtr<ClientChannel::LoadBalancedCall> lb_call_;
+ OrphanablePtr<ClientChannel::FilterBasedLoadBalancedCall> lb_call_;
};
const grpc_channel_filter DynamicTerminationFilter::kFilterVtable = {
@@ -520,20 +584,18 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface {
}
private:
- // Subchannel and SubchannelInterface have different interfaces for
- // their respective ConnectivityStateWatcherInterface classes.
- // The one in Subchannel updates the ConnectedSubchannel along with
- // the state, whereas the one in SubchannelInterface does not expose
- // the ConnectedSubchannel.
- //
- // This wrapper provides a bridge between the two. It implements
- // Subchannel::ConnectivityStateWatcherInterface and wraps
+ // This wrapper provides a bridge between the internal Subchannel API
+ // and the SubchannelInterface API that we expose to LB policies.
+ // It implements Subchannel::ConnectivityStateWatcherInterface and wraps
// the instance of SubchannelInterface::ConnectivityStateWatcherInterface
// that was passed in by the LB policy. We pass an instance of this
// class to the underlying Subchannel, and when we get updates from
// the subchannel, we pass those on to the wrapped watcher to return
- // the update to the LB policy. This allows us to set the connected
- // subchannel before passing the result back to the LB policy.
+ // the update to the LB policy.
+ //
+ // This class handles things like hopping into the WorkSerializer
+ // before passing notifications to the LB policy and propagating
+ // keepalive information betwen subchannels.
class WatcherWrapper : public Subchannel::ConnectivityStateWatcherInterface {
public:
WatcherWrapper(
@@ -571,16 +633,7 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface {
}
grpc_pollset_set* interested_parties() override {
- SubchannelInterface::ConnectivityStateWatcherInterface* watcher =
- watcher_.get();
- if (watcher_ == nullptr) watcher = replacement_->watcher_.get();
- return watcher->interested_parties();
- }
-
- WatcherWrapper* MakeReplacement() {
- auto* replacement = new WatcherWrapper(std::move(watcher_), parent_);
- replacement_ = replacement;
- return replacement;
+ return watcher_->interested_parties();
}
private:
@@ -638,7 +691,6 @@ class ClientChannel::SubchannelWrapper : public SubchannelInterface {
std::unique_ptr<SubchannelInterface::ConnectivityStateWatcherInterface>
watcher_;
RefCountedPtr<SubchannelWrapper> parent_;
- WatcherWrapper* replacement_ = nullptr;
};
ClientChannel* chand_;
@@ -1065,15 +1117,16 @@ ClientChannel::~ClientChannel() {
grpc_pollset_set_destroy(interested_parties_);
}
-OrphanablePtr<ClientChannel::LoadBalancedCall>
+OrphanablePtr<ClientChannel::FilterBasedLoadBalancedCall>
ClientChannel::CreateLoadBalancedCall(
const grpc_call_element_args& args, grpc_polling_entity* pollent,
grpc_closure* on_call_destruction_complete,
ConfigSelector::CallDispatchController* call_dispatch_controller,
bool is_transparent_retry) {
- return OrphanablePtr<LoadBalancedCall>(args.arena->New<LoadBalancedCall>(
- this, args, pollent, on_call_destruction_complete,
- call_dispatch_controller, is_transparent_retry));
+ return OrphanablePtr<FilterBasedLoadBalancedCall>(
+ args.arena->New<FilterBasedLoadBalancedCall>(
+ this, args, pollent, on_call_destruction_complete,
+ call_dispatch_controller, is_transparent_retry));
}
ChannelArgs ClientChannel::MakeSubchannelArgs(
@@ -1099,6 +1152,14 @@ ChannelArgs ClientChannel::MakeSubchannelArgs(
.Remove(GRPC_ARG_CHANNELZ_CHANNEL_NODE);
}
+void ClientChannel::ReprocessQueuedResolverCalls() {
+ for (CallData* calld : resolver_queued_calls_) {
+ calld->RemoveCallFromResolverQueuedCallsLocked();
+ calld->RetryCheckResolutionLocked();
+ }
+ resolver_queued_calls_.clear();
+}
+
namespace {
RefCountedPtr<LoadBalancingPolicy::Config> ChooseLbPolicy(
@@ -1305,26 +1366,19 @@ void ClientChannel::OnResolverErrorLocked(y_absl::Status status) {
// result, then we continue to let it set the connectivity state.
// Otherwise, we go into TRANSIENT_FAILURE.
if (lb_policy_ == nullptr) {
+ // Update connectivity state.
+ // TODO(roth): We should be updating the connectivity state here but
+ // not the picker.
+ UpdateStateAndPickerLocked(
+ GRPC_CHANNEL_TRANSIENT_FAILURE, status, "resolver failure",
+ MakeRefCounted<LoadBalancingPolicy::TransientFailurePicker>(status));
{
MutexLock lock(&resolution_mu_);
// Update resolver transient failure.
resolver_transient_failure_error_ =
MaybeRewriteIllegalStatusCode(status, "resolver");
- // Process calls that were queued waiting for the resolver result.
- for (ResolverQueuedCall* call = resolver_queued_calls_; call != nullptr;
- call = call->next) {
- grpc_call_element* elem = call->elem;
- CallData* calld = static_cast<CallData*>(elem->call_data);
- grpc_error_handle error;
- if (calld->CheckResolutionLocked(elem, &error)) {
- calld->AsyncResolutionDone(elem, error);
- }
- }
+ ReprocessQueuedResolverCalls();
}
- // Update connectivity state.
- UpdateStateAndPickerLocked(
- GRPC_CHANNEL_TRANSIENT_FAILURE, status, "resolver failure",
- MakeRefCounted<LoadBalancingPolicy::TransientFailurePicker>(status));
}
}
@@ -1378,30 +1432,6 @@ OrphanablePtr<LoadBalancingPolicy> ClientChannel::CreateLbPolicyLocked(
return lb_policy;
}
-void ClientChannel::AddResolverQueuedCall(ResolverQueuedCall* call,
- grpc_polling_entity* pollent) {
- // Add call to queued calls list.
- call->next = resolver_queued_calls_;
- resolver_queued_calls_ = call;
- // Add call's pollent to channel's interested_parties, so that I/O
- // can be done under the call's CQ.
- grpc_polling_entity_add_to_pollset_set(pollent, interested_parties_);
-}
-
-void ClientChannel::RemoveResolverQueuedCall(ResolverQueuedCall* to_remove,
- grpc_polling_entity* pollent) {
- // Remove call's pollent from channel's interested_parties.
- grpc_polling_entity_del_from_pollset_set(pollent, interested_parties_);
- // Remove from queued calls list.
- for (ResolverQueuedCall** call = &resolver_queued_calls_; *call != nullptr;
- call = &(*call)->next) {
- if (*call == to_remove) {
- *call = to_remove->next;
- return;
- }
- }
-}
-
void ClientChannel::UpdateServiceConfigInControlPlaneLocked(
RefCountedPtr<ServiceConfig> service_config,
RefCountedPtr<ConfigSelector> config_selector, TString lb_policy_name) {
@@ -1468,25 +1498,8 @@ void ClientChannel::UpdateServiceConfigInDataPlaneLocked() {
service_config_.swap(service_config);
config_selector_.swap(config_selector);
dynamic_filters_.swap(dynamic_filters);
- // Process calls that were queued waiting for the resolver result.
- for (ResolverQueuedCall* call = resolver_queued_calls_; call != nullptr;
- call = call->next) {
- // If there are a lot of queued calls here, resuming them all may cause us
- // to stay inside C-core for a long period of time. All of that work would
- // be done using the same ExecCtx instance and therefore the same cached
- // value of "now". The longer it takes to finish all of this work and exit
- // from C-core, the more stale the cached value of "now" may become. This
- // can cause problems whereby (e.g.) we calculate a timer deadline based
- // on the stale value, which results in the timer firing too early. To
- // avoid this, we invalidate the cached value for each call we process.
- ExecCtx::Get()->InvalidateNow();
- grpc_call_element* elem = call->elem;
- CallData* calld = static_cast<CallData*>(elem->call_data);
- grpc_error_handle error;
- if (calld->CheckResolutionLocked(elem, &error)) {
- calld->AsyncResolutionDone(elem, error);
- }
- }
+ // Re-process queued calls asynchronously.
+ ReprocessQueuedResolverCalls();
}
// Old values will be unreffed after lock is released when they go out
// of scope.
@@ -1502,6 +1515,10 @@ void ClientChannel::CreateResolverLocked() {
// Since the validity of the args was checked when the channel was created,
// CreateResolver() must return a non-null result.
GPR_ASSERT(resolver_ != nullptr);
+ // TODO(roth): We should be updating the connectivity state here but
+ // not the picker. But we need to make sure that we are initializing
+ // the picker to a queueing picker somewhere, in case the LB policy
+ // does not immediately return a new picker.
UpdateStateAndPickerLocked(
GRPC_CHANNEL_CONNECTING, y_absl::Status(), "started resolving",
MakeRefCounted<LoadBalancingPolicy::QueuePicker>(nullptr));
@@ -1562,29 +1579,18 @@ void ClientChannel::UpdateStateAndPickerLocked(
channelz::ChannelNode::GetChannelConnectivityStateChangeString(
state)));
}
- // Grab data plane lock to update the picker.
+ // Grab the LB lock to update the picker and trigger reprocessing of the
+ // queued picks.
+ // Old picker will be unreffed after releasing the lock.
{
- MutexLock lock(&data_plane_mu_);
- // Swap out the picker.
- // Note: Original value will be destroyed after the lock is released.
+ MutexLock lock(&lb_mu_);
picker_.swap(picker);
- // Re-process queued picks.
- for (LbQueuedCall* call = lb_queued_calls_; call != nullptr;
- call = call->next) {
- // If there are a lot of queued calls here, resuming them all may cause us
- // to stay inside C-core for a long period of time. All of that work would
- // be done using the same ExecCtx instance and therefore the same cached
- // value of "now". The longer it takes to finish all of this work and exit
- // from C-core, the more stale the cached value of "now" may become. This
- // can cause problems whereby (e.g.) we calculate a timer deadline based
- // on the stale value, which results in the timer firing too early. To
- // avoid this, we invalidate the cached value for each call we process.
- ExecCtx::Get()->InvalidateNow();
- grpc_error_handle error;
- if (call->lb_call->PickSubchannelLocked(&error)) {
- call->lb_call->AsyncPickDone(error);
- }
+ // Reprocess queued picks.
+ for (LoadBalancedCall* call : lb_queued_calls_) {
+ call->RemoveCallFromLbQueuedCallsLocked();
+ call->RetryPickLocked();
}
+ lb_queued_calls_.clear();
}
}
@@ -1628,7 +1634,7 @@ grpc_error_handle ClientChannel::DoPingLocked(grpc_transport_op* op) {
}
LoadBalancingPolicy::PickResult result;
{
- MutexLock lock(&data_plane_mu_);
+ MutexLock lock(&lb_mu_);
result = picker_->Pick(LoadBalancingPolicy::PickArgs());
}
return HandlePickResult<grpc_error_handle>(
@@ -1712,6 +1718,9 @@ void ClientChannel::StartTransportOpLocked(grpc_transport_op* op) {
GRPC_CHANNEL_SHUTDOWN, y_absl::Status(), "shutdown from API",
MakeRefCounted<LoadBalancingPolicy::TransientFailurePicker>(
grpc_error_to_absl_status(op->disconnect_with_error)));
+ // TODO(roth): If this happens when we're still waiting for a
+ // resolver result, we need to trigger failures for all calls in
+ // the resolver queue here.
}
}
GRPC_CHANNEL_STACK_UNREF(owning_stack_, "start_transport_op");
@@ -1748,30 +1757,6 @@ void ClientChannel::GetChannelInfo(grpc_channel_element* elem,
}
}
-void ClientChannel::AddLbQueuedCall(LbQueuedCall* call,
- grpc_polling_entity* pollent) {
- // Add call to queued picks list.
- call->next = lb_queued_calls_;
- lb_queued_calls_ = call;
- // Add call's pollent to channel's interested_parties, so that I/O
- // can be done under the call's CQ.
- grpc_polling_entity_add_to_pollset_set(pollent, interested_parties_);
-}
-
-void ClientChannel::RemoveLbQueuedCall(LbQueuedCall* to_remove,
- grpc_polling_entity* pollent) {
- // Remove call's pollent from channel's interested_parties.
- grpc_polling_entity_del_from_pollset_set(pollent, interested_parties_);
- // Remove from queued picks list.
- for (LbQueuedCall** call = &lb_queued_calls_; *call != nullptr;
- call = &(*call)->next) {
- if (*call == to_remove) {
- *call = to_remove->next;
- return;
- }
- }
-}
-
void ClientChannel::TryToConnectLocked() {
if (lb_policy_ != nullptr) {
lb_policy_->ExitIdleLocked();
@@ -1812,23 +1797,178 @@ void ClientChannel::RemoveConnectivityWatcher(
// CallData implementation
//
-ClientChannel::CallData::CallData(grpc_call_element* elem,
- const ClientChannel& chand,
- const grpc_call_element_args& args)
- : deadline_state_(elem, args,
- GPR_LIKELY(chand.deadline_checking_enabled_)
- ? args.deadline
- : Timestamp::InfFuture()),
- path_(CSliceRef(args.path)),
+void ClientChannel::CallData::RemoveCallFromResolverQueuedCallsLocked() {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
+ gpr_log(GPR_INFO,
+ "chand=%p calld=%p: removing from resolver queued picks list",
+ chand(), this);
+ }
+ // Remove call's pollent from channel's interested_parties.
+ grpc_polling_entity_del_from_pollset_set(pollent(),
+ chand()->interested_parties_);
+ // Note: There's no need to actually remove the call from the queue
+ // here, because that will be done in
+ // ResolverQueuedCallCanceller::CancelLocked() or
+ // ClientChannel::ReprocessQueuedResolverCalls().
+}
+
+void ClientChannel::CallData::AddCallToResolverQueuedCallsLocked() {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
+ gpr_log(GPR_INFO, "chand=%p calld=%p: adding to resolver queued picks list",
+ chand(), this);
+ }
+ // Add call's pollent to channel's interested_parties, so that I/O
+ // can be done under the call's CQ.
+ grpc_polling_entity_add_to_pollset_set(pollent(),
+ chand()->interested_parties_);
+ // Add to queue.
+ chand()->resolver_queued_calls_.insert(this);
+ OnAddToQueueLocked();
+}
+
+grpc_error_handle ClientChannel::CallData::ApplyServiceConfigToCallLocked(
+ const y_absl::StatusOr<RefCountedPtr<ConfigSelector>>& config_selector) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
+ gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call",
+ chand(), this);
+ }
+ if (!config_selector.ok()) return config_selector.status();
+ // Use the ConfigSelector to determine the config for the call.
+ auto call_config =
+ (*config_selector)->GetCallConfig({send_initial_metadata(), arena()});
+ if (!call_config.ok()) {
+ return absl_status_to_grpc_error(
+ MaybeRewriteIllegalStatusCode(call_config.status(), "ConfigSelector"));
+ }
+ // Create a ClientChannelServiceConfigCallData for the call. This stores
+ // a ref to the ServiceConfig and caches the right set of parsed configs
+ // to use for the call. The ClientChannelServiceConfigCallData will store
+ // itself in the call context, so that it can be accessed by filters
+ // below us in the stack, and it will be cleaned up when the call ends.
+ auto* service_config_call_data =
+ arena()->New<ClientChannelServiceConfigCallData>(
+ std::move(call_config->service_config), call_config->method_configs,
+ std::move(call_config->call_attributes),
+ call_config->call_dispatch_controller, call_context());
+ // Apply our own method params to the call.
+ auto* method_params = static_cast<ClientChannelMethodParsedConfig*>(
+ service_config_call_data->GetMethodParsedConfig(
+ chand()->service_config_parser_index_));
+ if (method_params != nullptr) {
+ // If the deadline from the service config is shorter than the one
+ // from the client API, reset the deadline timer.
+ if (chand()->deadline_checking_enabled_ &&
+ method_params->timeout() != Duration::Zero()) {
+ ResetDeadline(method_params->timeout());
+ }
+ // If the service config set wait_for_ready and the application
+ // did not explicitly set it, use the value from the service config.
+ auto* wait_for_ready =
+ send_initial_metadata()->GetOrCreatePointer(WaitForReady());
+ if (method_params->wait_for_ready().has_value() &&
+ !wait_for_ready->explicitly_set) {
+ wait_for_ready->value = method_params->wait_for_ready().value();
+ }
+ }
+ return y_absl::OkStatus();
+}
+
+y_absl::optional<y_absl::Status> ClientChannel::CallData::CheckResolution(
+ bool was_queued) {
+ // Check if we have a resolver result to use.
+ y_absl::StatusOr<RefCountedPtr<ConfigSelector>> config_selector;
+ {
+ MutexLock lock(&chand()->resolution_mu_);
+ bool result_ready = CheckResolutionLocked(&config_selector);
+ // If no result is available, queue the call.
+ if (!result_ready) {
+ AddCallToResolverQueuedCallsLocked();
+ return y_absl::nullopt;
+ }
+ }
+ // We have a result. Apply service config to call.
+ grpc_error_handle error = ApplyServiceConfigToCallLocked(config_selector);
+ // ConfigSelector must be unreffed inside the WorkSerializer.
+ if (config_selector.ok()) {
+ chand()->work_serializer_->Run(
+ [config_selector = std::move(*config_selector)]() mutable {
+ config_selector.reset();
+ },
+ DEBUG_LOCATION);
+ }
+ // Handle errors.
+ if (!error.ok()) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
+ gpr_log(GPR_INFO,
+ "chand=%p calld=%p: error applying config to call: error=%s",
+ chand(), this, StatusToString(error).c_str());
+ }
+ return error;
+ }
+ // If the call was queued, add trace annotation.
+ if (was_queued) {
+ auto* call_tracer = static_cast<CallTracerAnnotationInterface*>(
+ call_context()[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].value);
+ if (call_tracer != nullptr) {
+ call_tracer->RecordAnnotation("Delayed name resolution complete.");
+ }
+ }
+ return y_absl::OkStatus();
+}
+
+bool ClientChannel::CallData::CheckResolutionLocked(
+ y_absl::StatusOr<RefCountedPtr<ConfigSelector>>* config_selector) {
+ // If we don't yet have a resolver result, we need to queue the call
+ // until we get one.
+ if (GPR_UNLIKELY(!chand()->received_service_config_data_)) {
+ // If the resolver returned transient failure before returning the
+ // first service config, fail any non-wait_for_ready calls.
+ y_absl::Status resolver_error = chand()->resolver_transient_failure_error_;
+ if (!resolver_error.ok() &&
+ !send_initial_metadata()->GetOrCreatePointer(WaitForReady())->value) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
+ gpr_log(GPR_INFO, "chand=%p calld=%p: resolution failed, failing call",
+ chand(), this);
+ }
+ *config_selector = absl_status_to_grpc_error(resolver_error);
+ return true;
+ }
+ // Either the resolver has not yet returned a result, or it has
+ // returned transient failure but the call is wait_for_ready. In
+ // either case, queue the call.
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
+ gpr_log(GPR_INFO, "chand=%p calld=%p: no resolver result yet", chand(),
+ this);
+ }
+ return false;
+ }
+ // Result found.
+ *config_selector = chand()->config_selector_;
+ dynamic_filters_ = chand()->dynamic_filters_;
+ return true;
+}
+
+//
+// FilterBasedCallData implementation
+//
+
+ClientChannel::FilterBasedCallData::FilterBasedCallData(
+ grpc_call_element* elem, const grpc_call_element_args& args)
+ : path_(CSliceRef(args.path)),
+ call_context_(args.context),
call_start_time_(args.start_time),
deadline_(args.deadline),
- call_context_(args.context) {
+ deadline_state_(elem, args,
+ GPR_LIKELY(static_cast<ClientChannel*>(elem->channel_data)
+ ->deadline_checking_enabled_)
+ ? args.deadline
+ : Timestamp::InfFuture()) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
- gpr_log(GPR_INFO, "chand=%p calld=%p: created call", &chand, this);
+ gpr_log(GPR_INFO, "chand=%p calld=%p: created call", chand(), this);
}
}
-ClientChannel::CallData::~CallData() {
+ClientChannel::FilterBasedCallData::~FilterBasedCallData() {
CSliceUnref(path_);
// Make sure there are no remaining pending batches.
for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) {
@@ -1836,20 +1976,19 @@ ClientChannel::CallData::~CallData() {
}
}
-grpc_error_handle ClientChannel::CallData::Init(
+grpc_error_handle ClientChannel::FilterBasedCallData::Init(
grpc_call_element* elem, const grpc_call_element_args* args) {
- ClientChannel* chand = static_cast<ClientChannel*>(elem->channel_data);
- new (elem->call_data) CallData(elem, *chand, *args);
+ new (elem->call_data) FilterBasedCallData(elem, *args);
return y_absl::OkStatus();
}
-void ClientChannel::CallData::Destroy(
+void ClientChannel::FilterBasedCallData::Destroy(
grpc_call_element* elem, const grpc_call_final_info* /*final_info*/,
grpc_closure* then_schedule_closure) {
- CallData* calld = static_cast<CallData*>(elem->call_data);
+ auto* calld = static_cast<FilterBasedCallData*>(elem->call_data);
RefCountedPtr<DynamicFilters::Call> dynamic_call =
std::move(calld->dynamic_call_);
- calld->~CallData();
+ calld->~FilterBasedCallData();
if (GPR_LIKELY(dynamic_call != nullptr)) {
dynamic_call->SetAfterCallStackDestroy(then_schedule_closure);
} else {
@@ -1858,14 +1997,14 @@ void ClientChannel::CallData::Destroy(
}
}
-void ClientChannel::CallData::StartTransportStreamOpBatch(
+void ClientChannel::FilterBasedCallData::StartTransportStreamOpBatch(
grpc_call_element* elem, grpc_transport_stream_op_batch* batch) {
- CallData* calld = static_cast<CallData*>(elem->call_data);
+ auto* calld = static_cast<FilterBasedCallData*>(elem->call_data);
ClientChannel* chand = static_cast<ClientChannel*>(elem->channel_data);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace) &&
!GRPC_TRACE_FLAG_ENABLED(grpc_trace_channel)) {
gpr_log(GPR_INFO, "chand=%p calld=%p: batch started from above: %s", chand,
- calld, grpc_transport_stream_op_batch_string(batch).c_str());
+ calld, grpc_transport_stream_op_batch_string(batch, false).c_str());
}
if (GPR_LIKELY(chand->deadline_checking_enabled_)) {
grpc_deadline_state_client_start_transport_stream_op_batch(
@@ -1879,7 +2018,7 @@ void ClientChannel::CallData::StartTransportStreamOpBatch(
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_,
RecvTrailingMetadataReadyForConfigSelectorCommitCallback,
- elem, nullptr);
+ calld, nullptr);
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
&calld->recv_trailing_metadata_ready_;
}
@@ -1920,14 +2059,14 @@ void ClientChannel::CallData::StartTransportStreamOpBatch(
calld, StatusToString(calld->cancel_error_).c_str());
}
// Fail all pending batches.
- calld->PendingBatchesFail(elem, calld->cancel_error_, NoYieldCallCombiner);
+ calld->PendingBatchesFail(calld->cancel_error_, NoYieldCallCombiner);
// Note: This will release the call combiner.
grpc_transport_stream_op_batch_finish_with_failure(
batch, calld->cancel_error_, calld->call_combiner());
return;
}
// Add the batch to the pending list.
- calld->PendingBatchesAdd(elem, batch);
+ calld->PendingBatchesAdd(batch);
// For batches containing a send_initial_metadata op, acquire the
// channel's resolution mutex to apply the service config to the call,
// after which we will create a dynamic call.
@@ -1938,7 +2077,23 @@ void ClientChannel::CallData::StartTransportStreamOpBatch(
"config",
chand, calld);
}
- CheckResolution(elem, y_absl::OkStatus());
+ // If we're still in IDLE, we need to start resolving.
+ if (GPR_UNLIKELY(chand->CheckConnectivityState(false) ==
+ GRPC_CHANNEL_IDLE)) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
+ gpr_log(GPR_INFO, "chand=%p calld=%p: triggering exit idle", chand,
+ calld);
+ }
+ // Bounce into the control plane work serializer to start resolving.
+ GRPC_CHANNEL_STACK_REF(chand->owning_stack_, "ExitIdle");
+ chand->work_serializer_->Run(
+ [chand]() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(*chand->work_serializer_) {
+ chand->CheckConnectivityState(/*try_to_connect=*/true);
+ GRPC_CHANNEL_STACK_UNREF(chand->owning_stack_, "ExitIdle");
+ },
+ DEBUG_LOCATION);
+ }
+ calld->TryCheckResolution(/*was_queued=*/false);
} else {
// For all other batches, release the call combiner.
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
@@ -1951,21 +2106,16 @@ void ClientChannel::CallData::StartTransportStreamOpBatch(
}
}
-void ClientChannel::CallData::SetPollent(grpc_call_element* elem,
- grpc_polling_entity* pollent) {
- CallData* calld = static_cast<CallData*>(elem->call_data);
+void ClientChannel::FilterBasedCallData::SetPollent(
+ grpc_call_element* elem, grpc_polling_entity* pollent) {
+ auto* calld = static_cast<FilterBasedCallData*>(elem->call_data);
calld->pollent_ = pollent;
}
-//
-// pending_batches management
-//
-
-size_t ClientChannel::CallData::GetBatchIndex(
+size_t ClientChannel::FilterBasedCallData::GetBatchIndex(
grpc_transport_stream_op_batch* batch) {
// Note: It is important the send_initial_metadata be the first entry
- // here, since the code in ApplyServiceConfigToCallLocked() and
- // CheckResolutionLocked() assumes it will be.
+ // here, since the code in CheckResolution() assumes it will be.
if (batch->send_initial_metadata) return 0;
if (batch->send_message) return 1;
if (batch->send_trailing_metadata) return 2;
@@ -1976,14 +2126,13 @@ size_t ClientChannel::CallData::GetBatchIndex(
}
// This is called via the call combiner, so access to calld is synchronized.
-void ClientChannel::CallData::PendingBatchesAdd(
- grpc_call_element* elem, grpc_transport_stream_op_batch* batch) {
- ClientChannel* chand = static_cast<ClientChannel*>(elem->channel_data);
+void ClientChannel::FilterBasedCallData::PendingBatchesAdd(
+ grpc_transport_stream_op_batch* batch) {
const size_t idx = GetBatchIndex(batch);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
gpr_log(GPR_INFO,
- "chand=%p calld=%p: adding pending batch at index %" PRIuPTR, chand,
- this, idx);
+ "chand=%p calld=%p: adding pending batch at index %" PRIuPTR,
+ chand(), this, idx);
}
grpc_transport_stream_op_batch*& pending = pending_batches_[idx];
GPR_ASSERT(pending == nullptr);
@@ -1991,19 +2140,20 @@ void ClientChannel::CallData::PendingBatchesAdd(
}
// This is called via the call combiner, so access to calld is synchronized.
-void ClientChannel::CallData::FailPendingBatchInCallCombiner(
+void ClientChannel::FilterBasedCallData::FailPendingBatchInCallCombiner(
void* arg, grpc_error_handle error) {
grpc_transport_stream_op_batch* batch =
static_cast<grpc_transport_stream_op_batch*>(arg);
- CallData* calld = static_cast<CallData*>(batch->handler_private.extra_arg);
+ auto* calld =
+ static_cast<FilterBasedCallData*>(batch->handler_private.extra_arg);
// Note: This will release the call combiner.
grpc_transport_stream_op_batch_finish_with_failure(batch, error,
calld->call_combiner());
}
// This is called via the call combiner, so access to calld is synchronized.
-void ClientChannel::CallData::PendingBatchesFail(
- grpc_call_element* elem, grpc_error_handle error,
+void ClientChannel::FilterBasedCallData::PendingBatchesFail(
+ grpc_error_handle error,
YieldCallCombinerPredicate yield_call_combiner_predicate) {
GPR_ASSERT(!error.ok());
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
@@ -2011,9 +2161,9 @@ void ClientChannel::CallData::PendingBatchesFail(
for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) {
if (pending_batches_[i] != nullptr) ++num_batches;
}
- gpr_log(
- GPR_INFO, "chand=%p calld=%p: failing %" PRIuPTR " pending batches: %s",
- elem->channel_data, this, num_batches, StatusToString(error).c_str());
+ gpr_log(GPR_INFO,
+ "chand=%p calld=%p: failing %" PRIuPTR " pending batches: %s",
+ chand(), this, num_batches, StatusToString(error).c_str());
}
CallCombinerClosureList closures;
for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) {
@@ -2036,20 +2186,18 @@ void ClientChannel::CallData::PendingBatchesFail(
}
// This is called via the call combiner, so access to calld is synchronized.
-void ClientChannel::CallData::ResumePendingBatchInCallCombiner(
+void ClientChannel::FilterBasedCallData::ResumePendingBatchInCallCombiner(
void* arg, grpc_error_handle /*ignored*/) {
grpc_transport_stream_op_batch* batch =
static_cast<grpc_transport_stream_op_batch*>(arg);
- auto* elem =
- static_cast<grpc_call_element*>(batch->handler_private.extra_arg);
- auto* calld = static_cast<CallData*>(elem->call_data);
+ auto* calld =
+ static_cast<FilterBasedCallData*>(batch->handler_private.extra_arg);
// Note: This will release the call combiner.
calld->dynamic_call_->StartTransportStreamOpBatch(batch);
}
// This is called via the call combiner, so access to calld is synchronized.
-void ClientChannel::CallData::PendingBatchesResume(grpc_call_element* elem) {
- ClientChannel* chand = static_cast<ClientChannel*>(elem->channel_data);
+void ClientChannel::FilterBasedCallData::PendingBatchesResume() {
// Retries not enabled; send down batches as-is.
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
size_t num_batches = 0;
@@ -2059,13 +2207,13 @@ void ClientChannel::CallData::PendingBatchesResume(grpc_call_element* elem) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: starting %" PRIuPTR
" pending batches on dynamic_call=%p",
- chand, this, num_batches, dynamic_call_.get());
+ chand(), this, num_batches, dynamic_call_.get());
}
CallCombinerClosureList closures;
for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) {
grpc_transport_stream_op_batch*& batch = pending_batches_[i];
if (batch != nullptr) {
- batch->handler_private.extra_arg = elem;
+ batch->handler_private.extra_arg = this;
GRPC_CLOSURE_INIT(&batch->handler_private.closure,
ResumePendingBatchInCallCombiner, batch, nullptr);
closures.Add(&batch->handler_private.closure, y_absl::OkStatus(),
@@ -2077,16 +2225,12 @@ void ClientChannel::CallData::PendingBatchesResume(grpc_call_element* elem) {
closures.RunClosures(call_combiner());
}
-//
-// name resolution
-//
-
// A class to handle the call combiner cancellation callback for a
// queued pick.
-class ClientChannel::CallData::ResolverQueuedCallCanceller {
+class ClientChannel::FilterBasedCallData::ResolverQueuedCallCanceller {
public:
- explicit ResolverQueuedCallCanceller(grpc_call_element* elem) : elem_(elem) {
- auto* calld = static_cast<CallData*>(elem->call_data);
+ explicit ResolverQueuedCallCanceller(FilterBasedCallData* calld)
+ : calld_(calld) {
GRPC_CALL_STACK_REF(calld->owning_call(), "ResolverQueuedCallCanceller");
GRPC_CLOSURE_INIT(&closure_, &CancelLocked, this,
grpc_schedule_on_exec_ctx);
@@ -2096,8 +2240,8 @@ class ClientChannel::CallData::ResolverQueuedCallCanceller {
private:
static void CancelLocked(void* arg, grpc_error_handle error) {
auto* self = static_cast<ResolverQueuedCallCanceller*>(arg);
- auto* chand = static_cast<ClientChannel*>(self->elem_->channel_data);
- auto* calld = static_cast<CallData*>(self->elem_->call_data);
+ auto* calld = self->calld_;
+ auto* chand = calld->chand();
{
MutexLock lock(&chand->resolution_mu_);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
@@ -2109,9 +2253,10 @@ class ClientChannel::CallData::ResolverQueuedCallCanceller {
}
if (calld->resolver_call_canceller_ == self && !error.ok()) {
// Remove pick from list of queued picks.
- calld->MaybeRemoveCallFromResolverQueuedCallsLocked(self->elem_);
+ calld->RemoveCallFromResolverQueuedCallsLocked();
+ chand->resolver_queued_calls_.erase(calld);
// Fail pending batches on the call.
- calld->PendingBatchesFail(self->elem_, error,
+ calld->PendingBatchesFail(error,
YieldCallCombinerIfPendingBatchesFound);
}
}
@@ -2119,115 +2264,71 @@ class ClientChannel::CallData::ResolverQueuedCallCanceller {
delete self;
}
- grpc_call_element* elem_;
+ FilterBasedCallData* calld_;
grpc_closure closure_;
};
-void ClientChannel::CallData::MaybeRemoveCallFromResolverQueuedCallsLocked(
- grpc_call_element* elem) {
- if (!queued_pending_resolver_result_) return;
- auto* chand = static_cast<ClientChannel*>(elem->channel_data);
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p calld=%p: removing from resolver queued picks list",
- chand, this);
- }
- chand->RemoveResolverQueuedCall(&resolver_queued_call_, pollent_);
- queued_pending_resolver_result_ = false;
- // Lame the call combiner canceller.
- resolver_call_canceller_ = nullptr;
- // Add trace annotation
- auto* call_tracer =
- static_cast<CallTracer*>(call_context_[GRPC_CONTEXT_CALL_TRACER].value);
- if (call_tracer != nullptr) {
- call_tracer->RecordAnnotation("Delayed name resolution complete.");
+void ClientChannel::FilterBasedCallData::TryCheckResolution(bool was_queued) {
+ auto result = CheckResolution(was_queued);
+ if (result.has_value()) {
+ if (!result->ok()) {
+ PendingBatchesFail(*result, YieldCallCombiner);
+ return;
+ }
+ CreateDynamicCall();
}
}
-void ClientChannel::CallData::MaybeAddCallToResolverQueuedCallsLocked(
- grpc_call_element* elem) {
- if (queued_pending_resolver_result_) return;
- auto* chand = static_cast<ClientChannel*>(elem->channel_data);
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
- gpr_log(GPR_INFO, "chand=%p calld=%p: adding to resolver queued picks list",
- chand, this);
- }
- queued_pending_resolver_result_ = true;
- resolver_queued_call_.elem = elem;
- chand->AddResolverQueuedCall(&resolver_queued_call_, pollent_);
+void ClientChannel::FilterBasedCallData::OnAddToQueueLocked() {
// Register call combiner cancellation callback.
- resolver_call_canceller_ = new ResolverQueuedCallCanceller(elem);
+ resolver_call_canceller_ = new ResolverQueuedCallCanceller(this);
}
-grpc_error_handle ClientChannel::CallData::ApplyServiceConfigToCallLocked(
- grpc_call_element* elem, grpc_metadata_batch* initial_metadata) {
- ClientChannel* chand = static_cast<ClientChannel*>(elem->channel_data);
+void ClientChannel::FilterBasedCallData::RetryCheckResolutionLocked() {
+ // Lame the call combiner canceller.
+ resolver_call_canceller_ = nullptr;
+ // Do an async callback to resume call processing, so that we're not
+ // doing it while holding the channel's resolution mutex.
+ chand()->owning_stack_->EventEngine()->Run([this]() {
+ ApplicationCallbackExecCtx application_exec_ctx;
+ ExecCtx exec_ctx;
+ TryCheckResolution(/*was_queued=*/true);
+ });
+}
+
+void ClientChannel::FilterBasedCallData::CreateDynamicCall() {
+ DynamicFilters::Call::Args args = {dynamic_filters(), pollent_, path_,
+ call_start_time_, deadline_, arena(),
+ call_context_, call_combiner()};
+ grpc_error_handle error;
+ DynamicFilters* channel_stack = args.channel_stack.get();
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
- gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call",
- chand, this);
- }
- ConfigSelector* config_selector = chand->config_selector_.get();
- if (config_selector != nullptr) {
- // Use the ConfigSelector to determine the config for the call.
- auto call_config =
- config_selector->GetCallConfig({&path_, initial_metadata, arena()});
- if (!call_config.ok()) {
- return absl_status_to_grpc_error(MaybeRewriteIllegalStatusCode(
- call_config.status(), "ConfigSelector"));
- }
- // Create a ClientChannelServiceConfigCallData for the call. This stores
- // a ref to the ServiceConfig and caches the right set of parsed configs
- // to use for the call. The ClientChannelServiceConfigCallData will store
- // itself in the call context, so that it can be accessed by filters
- // below us in the stack, and it will be cleaned up when the call ends.
- auto* service_config_call_data =
- arena()->New<ClientChannelServiceConfigCallData>(
- std::move(call_config->service_config), call_config->method_configs,
- std::move(call_config->call_attributes),
- call_config->call_dispatch_controller, call_context_);
- // Apply our own method params to the call.
- auto* method_params = static_cast<ClientChannelMethodParsedConfig*>(
- service_config_call_data->GetMethodParsedConfig(
- chand->service_config_parser_index_));
- if (method_params != nullptr) {
- // If the deadline from the service config is shorter than the one
- // from the client API, reset the deadline timer.
- if (chand->deadline_checking_enabled_ &&
- method_params->timeout() != Duration::Zero()) {
- const Timestamp per_method_deadline =
- Timestamp::FromCycleCounterRoundUp(call_start_time_) +
- method_params->timeout();
- if (per_method_deadline < deadline_) {
- deadline_ = per_method_deadline;
- grpc_deadline_state_reset(&deadline_state_, deadline_);
- }
- }
- // If the service config set wait_for_ready and the application
- // did not explicitly set it, use the value from the service config.
- auto* wait_for_ready =
- pending_batches_[0]
- ->payload->send_initial_metadata.send_initial_metadata
- ->GetOrCreatePointer(WaitForReady());
- if (method_params->wait_for_ready().has_value() &&
- !wait_for_ready->explicitly_set) {
- wait_for_ready->value = method_params->wait_for_ready().value();
- }
+ gpr_log(
+ GPR_INFO,
+ "chand=%p calld=%p: creating dynamic call stack on channel_stack=%p",
+ chand(), this, channel_stack);
+ }
+ dynamic_call_ = channel_stack->CreateCall(std::move(args), &error);
+ if (!error.ok()) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
+ gpr_log(GPR_INFO,
+ "chand=%p calld=%p: failed to create dynamic call: error=%s",
+ chand(), this, StatusToString(error).c_str());
}
- // Set the dynamic filter stack.
- dynamic_filters_ = chand->dynamic_filters_;
+ PendingBatchesFail(error, YieldCallCombiner);
+ return;
}
- return y_absl::OkStatus();
+ PendingBatchesResume();
}
-void ClientChannel::CallData::
+void ClientChannel::FilterBasedCallData::
RecvTrailingMetadataReadyForConfigSelectorCommitCallback(
void* arg, grpc_error_handle error) {
- auto* elem = static_cast<grpc_call_element*>(arg);
- auto* chand = static_cast<ClientChannel*>(elem->channel_data);
- auto* calld = static_cast<CallData*>(elem->call_data);
+ auto* calld = static_cast<FilterBasedCallData*>(arg);
+ auto* chand = calld->chand();
auto* service_config_call_data =
static_cast<ClientChannelServiceConfigCallData*>(
- calld->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
+ calld->call_context()[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: got recv_trailing_metadata_ready: error=%s "
@@ -2243,145 +2344,24 @@ void ClientChannel::CallData::
error);
}
-void ClientChannel::CallData::AsyncResolutionDone(grpc_call_element* elem,
- grpc_error_handle error) {
- // TODO(roth): Does this callback need to hold a ref to the call stack?
- GRPC_CLOSURE_INIT(&resolution_done_closure_, ResolutionDone, elem, nullptr);
- ExecCtx::Run(DEBUG_LOCATION, &resolution_done_closure_, error);
-}
+//
+// ClientChannel::LoadBalancedCall::LbCallState
+//
-void ClientChannel::CallData::ResolutionDone(void* arg,
- grpc_error_handle error) {
- grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
- ClientChannel* chand = static_cast<ClientChannel*>(elem->channel_data);
- CallData* calld = static_cast<CallData*>(elem->call_data);
- if (!error.ok()) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p calld=%p: error applying config to call: error=%s",
- chand, calld, StatusToString(error).c_str());
- }
- calld->PendingBatchesFail(elem, error, YieldCallCombiner);
- return;
- }
- calld->CreateDynamicCall(elem);
-}
+class ClientChannel::LoadBalancedCall::LbCallState
+ : public ClientChannelLbCallState {
+ public:
+ explicit LbCallState(LoadBalancedCall* lb_call) : lb_call_(lb_call) {}
-void ClientChannel::CallData::CheckResolution(void* arg,
- grpc_error_handle error) {
- grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
- CallData* calld = static_cast<CallData*>(elem->call_data);
- ClientChannel* chand = static_cast<ClientChannel*>(elem->channel_data);
- bool resolution_complete;
- {
- MutexLock lock(&chand->resolution_mu_);
- resolution_complete = calld->CheckResolutionLocked(elem, &error);
- }
- if (resolution_complete) {
- ResolutionDone(elem, error);
- }
-}
+ void* Alloc(size_t size) override { return lb_call_->arena()->Alloc(size); }
-bool ClientChannel::CallData::CheckResolutionLocked(grpc_call_element* elem,
- grpc_error_handle* error) {
- ClientChannel* chand = static_cast<ClientChannel*>(elem->channel_data);
- // If we're still in IDLE, we need to start resolving.
- if (GPR_UNLIKELY(chand->CheckConnectivityState(false) == GRPC_CHANNEL_IDLE)) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
- gpr_log(GPR_INFO, "chand=%p calld=%p: triggering exit idle", chand, this);
- }
- // Bounce into the control plane work serializer to start resolving,
- // in case we are still in IDLE state. Since we are holding on to the
- // resolution mutex here, we offload it on the ExecCtx so that we don't
- // deadlock with ourselves.
- GRPC_CHANNEL_STACK_REF(chand->owning_stack_, "CheckResolutionLocked");
- ExecCtx::Run(
- DEBUG_LOCATION,
- GRPC_CLOSURE_CREATE(
- [](void* arg, grpc_error_handle /*error*/) {
- auto* chand = static_cast<ClientChannel*>(arg);
- chand->work_serializer_->Run(
- [chand]()
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(*chand->work_serializer_) {
- chand->CheckConnectivityState(/*try_to_connect=*/true);
- GRPC_CHANNEL_STACK_UNREF(chand->owning_stack_,
- "CheckResolutionLocked");
- },
- DEBUG_LOCATION);
- },
- chand, nullptr),
- y_absl::OkStatus());
- }
- // Get send_initial_metadata batch and flags.
- auto& send_initial_metadata =
- pending_batches_[0]->payload->send_initial_metadata;
- grpc_metadata_batch* initial_metadata_batch =
- send_initial_metadata.send_initial_metadata;
- // If we don't yet have a resolver result, we need to queue the call
- // until we get one.
- if (GPR_UNLIKELY(!chand->received_service_config_data_)) {
- // If the resolver returned transient failure before returning the
- // first service config, fail any non-wait_for_ready calls.
- y_absl::Status resolver_error = chand->resolver_transient_failure_error_;
- if (!resolver_error.ok() &&
- !initial_metadata_batch->GetOrCreatePointer(WaitForReady())->value) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
- gpr_log(GPR_INFO, "chand=%p calld=%p: resolution failed, failing call",
- chand, this);
- }
- MaybeRemoveCallFromResolverQueuedCallsLocked(elem);
- *error = absl_status_to_grpc_error(resolver_error);
- return true;
- }
- // Either the resolver has not yet returned a result, or it has
- // returned transient failure but the call is wait_for_ready. In
- // either case, queue the call.
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
- gpr_log(GPR_INFO, "chand=%p calld=%p: queuing to wait for resolution",
- chand, this);
- }
- MaybeAddCallToResolverQueuedCallsLocked(elem);
- return false;
- }
- // Apply service config to call if not yet applied.
- if (GPR_LIKELY(!service_config_applied_)) {
- service_config_applied_ = true;
- *error = ApplyServiceConfigToCallLocked(elem, initial_metadata_batch);
- }
- MaybeRemoveCallFromResolverQueuedCallsLocked(elem);
- return true;
-}
+ // Internal API to allow first-party LB policies to access per-call
+ // attributes set by the ConfigSelector.
+ y_absl::string_view GetCallAttribute(UniqueTypeName type) override;
-void ClientChannel::CallData::CreateDynamicCall(grpc_call_element* elem) {
- auto* chand = static_cast<ClientChannel*>(elem->channel_data);
- DynamicFilters::Call::Args args = {std::move(dynamic_filters_),
- pollent_,
- path_,
- call_start_time_,
- deadline_,
- arena(),
- call_context_,
- call_combiner()};
- grpc_error_handle error;
- DynamicFilters* channel_stack = args.channel_stack.get();
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
- gpr_log(
- GPR_INFO,
- "chand=%p calld=%p: creating dynamic call stack on channel_stack=%p",
- chand, this, channel_stack);
- }
- dynamic_call_ = channel_stack->CreateCall(std::move(args), &error);
- if (!error.ok()) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p calld=%p: failed to create dynamic call: error=%s",
- chand, this, StatusToString(error).c_str());
- }
- PendingBatchesFail(elem, error, YieldCallCombiner);
- return;
- }
- PendingBatchesResume(elem);
-}
+ private:
+ LoadBalancedCall* lb_call_;
+};
//
// ClientChannel::LoadBalancedCall::Metadata
@@ -2466,7 +2446,7 @@ y_absl::string_view
ClientChannel::LoadBalancedCall::LbCallState::GetCallAttribute(
UniqueTypeName type) {
auto* service_config_call_data = static_cast<ServiceConfigCallData*>(
- lb_call_->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
+ lb_call_->call_context()[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
auto& call_attributes = service_config_call_data->call_attributes();
auto it = call_attributes.find(type);
if (it == call_attributes.end()) return y_absl::string_view();
@@ -2480,15 +2460,16 @@ ClientChannel::LoadBalancedCall::LbCallState::GetCallAttribute(
class ClientChannel::LoadBalancedCall::BackendMetricAccessor
: public LoadBalancingPolicy::BackendMetricAccessor {
public:
- explicit BackendMetricAccessor(LoadBalancedCall* lb_call)
- : lb_call_(lb_call) {}
+ BackendMetricAccessor(LoadBalancedCall* lb_call,
+ grpc_metadata_batch* recv_trailing_metadata)
+ : lb_call_(lb_call), recv_trailing_metadata_(recv_trailing_metadata) {}
const BackendMetricData* GetBackendMetricData() override {
if (lb_call_->backend_metric_data_ == nullptr &&
- lb_call_->recv_trailing_metadata_ != nullptr) {
- if (const auto* md = lb_call_->recv_trailing_metadata_->get_pointer(
+ recv_trailing_metadata_ != nullptr) {
+ if (const auto* md = recv_trailing_metadata_->get_pointer(
EndpointLoadMetricsBinMetadata())) {
- BackendMetricAllocator allocator(lb_call_->arena_);
+ BackendMetricAllocator allocator(lb_call_->arena());
lb_call_->backend_metric_data_ =
ParseBackendMetricData(md->as_string_view(), &allocator);
}
@@ -2514,6 +2495,7 @@ class ClientChannel::LoadBalancedCall::BackendMetricAccessor
};
LoadBalancedCall* lb_call_;
+ grpc_metadata_batch* recv_trailing_metadata_;
};
//
@@ -2522,19 +2504,20 @@ class ClientChannel::LoadBalancedCall::BackendMetricAccessor
namespace {
-CallTracer::CallAttemptTracer* GetCallAttemptTracer(
+ClientCallTracer::CallAttemptTracer* CreateCallAttemptTracer(
grpc_call_context_element* context, bool is_transparent_retry) {
- auto* call_tracer =
- static_cast<CallTracer*>(context[GRPC_CONTEXT_CALL_TRACER].value);
+ auto* call_tracer = static_cast<ClientCallTracer*>(
+ context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].value);
if (call_tracer == nullptr) return nullptr;
- return call_tracer->StartNewAttempt(is_transparent_retry);
+ auto* tracer = call_tracer->StartNewAttempt(is_transparent_retry);
+ context[GRPC_CONTEXT_CALL_TRACER].value = tracer;
+ return tracer;
}
} // namespace
ClientChannel::LoadBalancedCall::LoadBalancedCall(
- ClientChannel* chand, const grpc_call_element_args& args,
- grpc_polling_entity* pollent, grpc_closure* on_call_destruction_complete,
+ ClientChannel* chand, grpc_call_context_element* call_context,
ConfigSelector::CallDispatchController* call_dispatch_controller,
bool is_transparent_retry)
: InternallyRefCounted(
@@ -2542,17 +2525,8 @@ ClientChannel::LoadBalancedCall::LoadBalancedCall(
? "LoadBalancedCall"
: nullptr),
chand_(chand),
- path_(CSliceRef(args.path)),
- deadline_(args.deadline),
- arena_(args.arena),
- owning_call_(args.call_stack),
- call_combiner_(args.call_combiner),
- call_context_(args.context),
- pollent_(pollent),
- on_call_destruction_complete_(on_call_destruction_complete),
- call_dispatch_controller_(call_dispatch_controller),
- call_attempt_tracer_(
- GetCallAttemptTracer(args.context, is_transparent_retry)) {
+ call_dispatch_controller_(call_dispatch_controller) {
+ CreateCallAttemptTracer(call_context, is_transparent_retry);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
gpr_log(GPR_INFO, "chand=%p lb_call=%p: created", chand_, this);
}
@@ -2562,6 +2536,245 @@ ClientChannel::LoadBalancedCall::~LoadBalancedCall() {
if (backend_metric_data_ != nullptr) {
backend_metric_data_->BackendMetricData::~BackendMetricData();
}
+}
+
+void ClientChannel::LoadBalancedCall::Orphan() {
+ // Compute latency and report it to the tracer.
+ if (call_attempt_tracer() != nullptr) {
+ gpr_timespec latency =
+ gpr_cycle_counter_sub(gpr_get_cycle_counter(), lb_call_start_time_);
+ call_attempt_tracer()->RecordEnd(latency);
+ }
+ Unref();
+}
+
+void ClientChannel::LoadBalancedCall::RecordCallCompletion(
+ y_absl::Status status, grpc_metadata_batch* recv_trailing_metadata,
+ grpc_transport_stream_stats* transport_stream_stats,
+ y_absl::string_view peer_address) {
+ // If we have a tracer, notify it.
+ if (call_attempt_tracer() != nullptr) {
+ call_attempt_tracer()->RecordReceivedTrailingMetadata(
+ status, recv_trailing_metadata, transport_stream_stats);
+ }
+ // If the LB policy requested a callback for trailing metadata, invoke
+ // the callback.
+ if (lb_subchannel_call_tracker_ != nullptr) {
+ Metadata trailing_metadata(recv_trailing_metadata);
+ BackendMetricAccessor backend_metric_accessor(this, recv_trailing_metadata);
+ LoadBalancingPolicy::SubchannelCallTrackerInterface::FinishArgs args = {
+ peer_address, status, &trailing_metadata, &backend_metric_accessor};
+ lb_subchannel_call_tracker_->Finish(args);
+ lb_subchannel_call_tracker_.reset();
+ }
+}
+
+void ClientChannel::LoadBalancedCall::RemoveCallFromLbQueuedCallsLocked() {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
+ gpr_log(GPR_INFO, "chand=%p lb_call=%p: removing from queued picks list",
+ chand_, this);
+ }
+ // Remove pollset_set linkage.
+ grpc_polling_entity_del_from_pollset_set(pollent(),
+ chand_->interested_parties_);
+ // Note: There's no need to actually remove the call from the queue
+ // here, beacuse that will be done in either
+ // LbQueuedCallCanceller::CancelLocked() or
+ // in ClientChannel::UpdateStateAndPickerLocked().
+}
+
+void ClientChannel::LoadBalancedCall::AddCallToLbQueuedCallsLocked() {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
+ gpr_log(GPR_INFO, "chand=%p lb_call=%p: adding to queued picks list",
+ chand_, this);
+ }
+ // Add call's pollent to channel's interested_parties, so that I/O
+ // can be done under the call's CQ.
+ grpc_polling_entity_add_to_pollset_set(pollent(),
+ chand_->interested_parties_);
+ // Add to queue.
+ chand_->lb_queued_calls_.insert(this);
+ OnAddToQueueLocked();
+}
+
+y_absl::optional<y_absl::Status> ClientChannel::LoadBalancedCall::PickSubchannel(
+ bool was_queued) {
+ // We may accumulate multiple pickers here, because if a picker says
+ // to queue the call, we check again to see if the picker has been
+ // updated before we queue it.
+ // We need to unref pickers in the WorkSerializer.
+ std::vector<RefCountedPtr<LoadBalancingPolicy::SubchannelPicker>> pickers;
+ auto cleanup = y_absl::MakeCleanup([&]() {
+ chand_->work_serializer_->Run(
+ [pickers = std::move(pickers)]() mutable {
+ for (auto& picker : pickers) {
+ picker.reset(DEBUG_LOCATION, "PickSubchannel");
+ }
+ },
+ DEBUG_LOCATION);
+ });
+ // Grab mutex and take a ref to the picker.
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
+ gpr_log(GPR_INFO, "chand=%p lb_call=%p: grabbing LB mutex to get picker",
+ chand_, this);
+ }
+ {
+ MutexLock lock(&chand_->lb_mu_);
+ pickers.emplace_back(chand_->picker_);
+ }
+ while (true) {
+ // Do pick.
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
+ gpr_log(GPR_INFO, "chand=%p lb_call=%p: performing pick with picker=%p",
+ chand_, this, pickers.back().get());
+ }
+ grpc_error_handle error;
+ bool pick_complete = PickSubchannelImpl(pickers.back().get(), &error);
+ if (!pick_complete) {
+ MutexLock lock(&chand_->lb_mu_);
+ // If picker has been swapped out since we grabbed it, try again.
+ if (chand_->picker_ != pickers.back()) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
+ gpr_log(GPR_INFO,
+ "chand=%p lb_call=%p: pick not complete, but picker changed",
+ chand_, this);
+ }
+ pickers.emplace_back(chand_->picker_);
+ continue;
+ }
+ // Otherwise queue the pick to try again later when we get a new picker.
+ AddCallToLbQueuedCallsLocked();
+ return y_absl::nullopt;
+ }
+ // Pick is complete.
+ // If it was queued, add a trace annotation.
+ if (was_queued && call_attempt_tracer() != nullptr) {
+ call_attempt_tracer()->RecordAnnotation("Delayed LB pick complete.");
+ }
+ // If the pick failed, fail the call.
+ if (!error.ok()) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
+ gpr_log(GPR_INFO,
+ "chand=%p lb_call=%p: failed to pick subchannel: error=%s",
+ chand_, this, StatusToString(error).c_str());
+ }
+ return error;
+ }
+ // Pick succeeded.
+ call_dispatch_controller_->Commit();
+ return y_absl::OkStatus();
+ }
+}
+
+bool ClientChannel::LoadBalancedCall::PickSubchannelImpl(
+ LoadBalancingPolicy::SubchannelPicker* picker, grpc_error_handle* error) {
+ GPR_ASSERT(connected_subchannel_ == nullptr);
+ // Perform LB pick.
+ LoadBalancingPolicy::PickArgs pick_args;
+ Slice* path = send_initial_metadata()->get_pointer(HttpPathMetadata());
+ GPR_ASSERT(path != nullptr);
+ pick_args.path = path->as_string_view();
+ LbCallState lb_call_state(this);
+ pick_args.call_state = &lb_call_state;
+ Metadata initial_metadata(send_initial_metadata());
+ pick_args.initial_metadata = &initial_metadata;
+ auto result = picker->Pick(pick_args);
+ return HandlePickResult<bool>(
+ &result,
+ // CompletePick
+ [this](LoadBalancingPolicy::PickResult::Complete* complete_pick) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
+ gpr_log(GPR_INFO,
+ "chand=%p lb_call=%p: LB pick succeeded: subchannel=%p",
+ chand_, this, complete_pick->subchannel.get());
+ }
+ GPR_ASSERT(complete_pick->subchannel != nullptr);
+ // Grab a ref to the connected subchannel while we're still
+ // holding the data plane mutex.
+ SubchannelWrapper* subchannel =
+ static_cast<SubchannelWrapper*>(complete_pick->subchannel.get());
+ connected_subchannel_ = subchannel->connected_subchannel();
+ // If the subchannel has no connected subchannel (e.g., if the
+ // subchannel has moved out of state READY but the LB policy hasn't
+ // yet seen that change and given us a new picker), then just
+ // queue the pick. We'll try again as soon as we get a new picker.
+ if (connected_subchannel_ == nullptr) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
+ gpr_log(GPR_INFO,
+ "chand=%p lb_call=%p: subchannel returned by LB picker "
+ "has no connected subchannel; queueing pick",
+ chand_, this);
+ }
+ return false;
+ }
+ lb_subchannel_call_tracker_ =
+ std::move(complete_pick->subchannel_call_tracker);
+ if (lb_subchannel_call_tracker_ != nullptr) {
+ lb_subchannel_call_tracker_->Start();
+ }
+ return true;
+ },
+ // QueuePick
+ [this](LoadBalancingPolicy::PickResult::Queue* /*queue_pick*/) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
+ gpr_log(GPR_INFO, "chand=%p lb_call=%p: LB pick queued", chand_,
+ this);
+ }
+ return false;
+ },
+ // FailPick
+ [this, &error](LoadBalancingPolicy::PickResult::Fail* fail_pick) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
+ gpr_log(GPR_INFO, "chand=%p lb_call=%p: LB pick failed: %s", chand_,
+ this, fail_pick->status.ToString().c_str());
+ }
+ // If wait_for_ready is false, then the error indicates the RPC
+ // attempt's final status.
+ if (!send_initial_metadata()
+ ->GetOrCreatePointer(WaitForReady())
+ ->value) {
+ *error = absl_status_to_grpc_error(MaybeRewriteIllegalStatusCode(
+ std::move(fail_pick->status), "LB pick"));
+ return true;
+ }
+ // If wait_for_ready is true, then queue to retry when we get a new
+ // picker.
+ return false;
+ },
+ // DropPick
+ [this, &error](LoadBalancingPolicy::PickResult::Drop* drop_pick) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
+ gpr_log(GPR_INFO, "chand=%p lb_call=%p: LB pick dropped: %s", chand_,
+ this, drop_pick->status.ToString().c_str());
+ }
+ *error = grpc_error_set_int(
+ absl_status_to_grpc_error(MaybeRewriteIllegalStatusCode(
+ std::move(drop_pick->status), "LB drop")),
+ StatusIntProperty::kLbPolicyDrop, 1);
+ return true;
+ });
+}
+
+//
+// ClientChannel::FilterBasedLoadBalancedCall
+//
+
+ClientChannel::FilterBasedLoadBalancedCall::FilterBasedLoadBalancedCall(
+ ClientChannel* chand, const grpc_call_element_args& args,
+ grpc_polling_entity* pollent, grpc_closure* on_call_destruction_complete,
+ ConfigSelector::CallDispatchController* call_dispatch_controller,
+ bool is_transparent_retry)
+ : LoadBalancedCall(chand, args.context, call_dispatch_controller,
+ is_transparent_retry),
+ deadline_(args.deadline),
+ arena_(args.arena),
+ call_context_(args.context),
+ owning_call_(args.call_stack),
+ call_combiner_(args.call_combiner),
+ pollent_(pollent),
+ on_call_destruction_complete_(on_call_destruction_complete) {}
+
+ClientChannel::FilterBasedLoadBalancedCall::~FilterBasedLoadBalancedCall() {
// Make sure there are no remaining pending batches.
for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) {
GPR_ASSERT(pending_batches_[i] == nullptr);
@@ -2572,26 +2785,22 @@ ClientChannel::LoadBalancedCall::~LoadBalancedCall() {
}
}
-void ClientChannel::LoadBalancedCall::Orphan() {
+void ClientChannel::FilterBasedLoadBalancedCall::Orphan() {
// If the recv_trailing_metadata op was never started, then notify
// about call completion here, as best we can. We assume status
// CANCELLED in this case.
if (recv_trailing_metadata_ == nullptr) {
- RecordCallCompletion(y_absl::CancelledError("call cancelled"));
- }
- // Compute latency and report it to the tracer.
- if (call_attempt_tracer_ != nullptr) {
- gpr_timespec latency =
- gpr_cycle_counter_sub(gpr_get_cycle_counter(), lb_call_start_time_);
- call_attempt_tracer_->RecordEnd(latency);
+ RecordCallCompletion(y_absl::CancelledError("call cancelled"), nullptr,
+ nullptr, "");
}
- Unref();
+ // Delegate to parent.
+ LoadBalancedCall::Orphan();
}
-size_t ClientChannel::LoadBalancedCall::GetBatchIndex(
+size_t ClientChannel::FilterBasedLoadBalancedCall::GetBatchIndex(
grpc_transport_stream_op_batch* batch) {
// Note: It is important the send_initial_metadata be the first entry
- // here, since the code in PickSubchannelLocked() assumes it will be.
+ // here, since the code in PickSubchannelImpl() assumes it will be.
if (batch->send_initial_metadata) return 0;
if (batch->send_message) return 1;
if (batch->send_trailing_metadata) return 2;
@@ -2602,31 +2811,32 @@ size_t ClientChannel::LoadBalancedCall::GetBatchIndex(
}
// This is called via the call combiner, so access to calld is synchronized.
-void ClientChannel::LoadBalancedCall::PendingBatchesAdd(
+void ClientChannel::FilterBasedLoadBalancedCall::PendingBatchesAdd(
grpc_transport_stream_op_batch* batch) {
const size_t idx = GetBatchIndex(batch);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
gpr_log(GPR_INFO,
"chand=%p lb_call=%p: adding pending batch at index %" PRIuPTR,
- chand_, this, idx);
+ chand(), this, idx);
}
GPR_ASSERT(pending_batches_[idx] == nullptr);
pending_batches_[idx] = batch;
}
// This is called via the call combiner, so access to calld is synchronized.
-void ClientChannel::LoadBalancedCall::FailPendingBatchInCallCombiner(
+void ClientChannel::FilterBasedLoadBalancedCall::FailPendingBatchInCallCombiner(
void* arg, grpc_error_handle error) {
grpc_transport_stream_op_batch* batch =
static_cast<grpc_transport_stream_op_batch*>(arg);
- auto* self = static_cast<LoadBalancedCall*>(batch->handler_private.extra_arg);
+ auto* self = static_cast<FilterBasedLoadBalancedCall*>(
+ batch->handler_private.extra_arg);
// Note: This will release the call combiner.
grpc_transport_stream_op_batch_finish_with_failure(batch, error,
self->call_combiner_);
}
// This is called via the call combiner, so access to calld is synchronized.
-void ClientChannel::LoadBalancedCall::PendingBatchesFail(
+void ClientChannel::FilterBasedLoadBalancedCall::PendingBatchesFail(
grpc_error_handle error,
YieldCallCombinerPredicate yield_call_combiner_predicate) {
GPR_ASSERT(!error.ok());
@@ -2638,7 +2848,7 @@ void ClientChannel::LoadBalancedCall::PendingBatchesFail(
}
gpr_log(GPR_INFO,
"chand=%p lb_call=%p: failing %" PRIuPTR " pending batches: %s",
- chand_, this, num_batches, StatusToString(error).c_str());
+ chand(), this, num_batches, StatusToString(error).c_str());
}
CallCombinerClosureList closures;
for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) {
@@ -2661,8 +2871,8 @@ void ClientChannel::LoadBalancedCall::PendingBatchesFail(
}
// This is called via the call combiner, so access to calld is synchronized.
-void ClientChannel::LoadBalancedCall::ResumePendingBatchInCallCombiner(
- void* arg, grpc_error_handle /*ignored*/) {
+void ClientChannel::FilterBasedLoadBalancedCall::
+ ResumePendingBatchInCallCombiner(void* arg, grpc_error_handle /*ignored*/) {
grpc_transport_stream_op_batch* batch =
static_cast<grpc_transport_stream_op_batch*>(arg);
SubchannelCall* subchannel_call =
@@ -2672,7 +2882,7 @@ void ClientChannel::LoadBalancedCall::ResumePendingBatchInCallCombiner(
}
// This is called via the call combiner, so access to calld is synchronized.
-void ClientChannel::LoadBalancedCall::PendingBatchesResume() {
+void ClientChannel::FilterBasedLoadBalancedCall::PendingBatchesResume() {
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
size_t num_batches = 0;
for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) {
@@ -2681,7 +2891,7 @@ void ClientChannel::LoadBalancedCall::PendingBatchesResume() {
gpr_log(GPR_INFO,
"chand=%p lb_call=%p: starting %" PRIuPTR
" pending batches on subchannel_call=%p",
- chand_, this, num_batches, subchannel_call_.get());
+ chand(), this, num_batches, subchannel_call_.get());
}
CallCombinerClosureList closures;
for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) {
@@ -2700,38 +2910,30 @@ void ClientChannel::LoadBalancedCall::PendingBatchesResume() {
closures.RunClosures(call_combiner_);
}
-void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch(
+void ClientChannel::FilterBasedLoadBalancedCall::StartTransportStreamOpBatch(
grpc_transport_stream_op_batch* batch) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace) ||
GRPC_TRACE_FLAG_ENABLED(grpc_trace_channel)) {
gpr_log(GPR_INFO,
"chand=%p lb_call=%p: batch started from above: %s, "
- "call_attempt_tracer_=%p",
- chand_, this, grpc_transport_stream_op_batch_string(batch).c_str(),
- call_attempt_tracer_);
+ "call_attempt_tracer()=%p",
+ chand(), this,
+ grpc_transport_stream_op_batch_string(batch, false).c_str(),
+ call_attempt_tracer());
}
// Handle call tracing.
- if (call_attempt_tracer_ != nullptr) {
+ if (call_attempt_tracer() != nullptr) {
// Record send ops in tracer.
if (batch->cancel_stream) {
- call_attempt_tracer_->RecordCancel(
+ call_attempt_tracer()->RecordCancel(
batch->payload->cancel_stream.cancel_error);
}
if (batch->send_initial_metadata) {
- call_attempt_tracer_->RecordSendInitialMetadata(
+ call_attempt_tracer()->RecordSendInitialMetadata(
batch->payload->send_initial_metadata.send_initial_metadata);
- peer_string_ = batch->payload->send_initial_metadata.peer_string;
- original_send_initial_metadata_on_complete_ = batch->on_complete;
- GRPC_CLOSURE_INIT(&send_initial_metadata_on_complete_,
- SendInitialMetadataOnComplete, this, nullptr);
- batch->on_complete = &send_initial_metadata_on_complete_;
- }
- if (batch->send_message) {
- call_attempt_tracer_->RecordSendMessage(
- *batch->payload->send_message.send_message);
}
if (batch->send_trailing_metadata) {
- call_attempt_tracer_->RecordSendTrailingMetadata(
+ call_attempt_tracer()->RecordSendTrailingMetadata(
batch->payload->send_trailing_metadata.send_trailing_metadata);
}
// Intercept recv ops.
@@ -2745,13 +2947,6 @@ void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch(
batch->payload->recv_initial_metadata.recv_initial_metadata_ready =
&recv_initial_metadata_ready_;
}
- if (batch->recv_message) {
- recv_message_ = batch->payload->recv_message.recv_message;
- original_recv_message_ready_ =
- batch->payload->recv_message.recv_message_ready;
- GRPC_CLOSURE_INIT(&recv_message_ready_, RecvMessageReady, this, nullptr);
- batch->payload->recv_message.recv_message_ready = &recv_message_ready_;
- }
}
// Intercept recv_trailing_metadata even if there is no call tracer,
// since we may need to notify the LB policy about trailing metadata.
@@ -2775,7 +2970,7 @@ void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch(
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
gpr_log(GPR_INFO,
"chand=%p lb_call=%p: starting batch on subchannel_call=%p",
- chand_, this, subchannel_call_.get());
+ chand(), this, subchannel_call_.get());
}
subchannel_call_->StartTransportStreamOpBatch(batch);
return;
@@ -2786,7 +2981,7 @@ void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch(
if (GPR_UNLIKELY(!cancel_error_.ok())) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
gpr_log(GPR_INFO, "chand=%p lb_call=%p: failing batch with error: %s",
- chand_, this, StatusToString(cancel_error_).c_str());
+ chand(), this, StatusToString(cancel_error_).c_str());
}
// Note: This will release the call combiner.
grpc_transport_stream_op_batch_finish_with_failure(batch, cancel_error_,
@@ -2803,7 +2998,7 @@ void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch(
cancel_error_ = batch->payload->cancel_stream.cancel_error;
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
gpr_log(GPR_INFO, "chand=%p lb_call=%p: recording cancel_error=%s",
- chand_, this, StatusToString(cancel_error_).c_str());
+ chand(), this, StatusToString(cancel_error_).c_str());
}
// Fail all pending batches.
PendingBatchesFail(cancel_error_, NoYieldCallCombiner);
@@ -2815,86 +3010,55 @@ void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch(
// Add the batch to the pending list.
PendingBatchesAdd(batch);
// For batches containing a send_initial_metadata op, acquire the
- // channel's data plane mutex to pick a subchannel.
+ // channel's LB mutex to pick a subchannel.
if (GPR_LIKELY(batch->send_initial_metadata)) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p lb_call=%p: grabbing data plane mutex to perform pick",
- chand_, this);
- }
- PickSubchannel(this, y_absl::OkStatus());
+ TryPick(/*was_queued=*/false);
} else {
// For all other batches, release the call combiner.
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
gpr_log(GPR_INFO,
"chand=%p lb_call=%p: saved batch, yielding call combiner",
- chand_, this);
+ chand(), this);
}
GRPC_CALL_COMBINER_STOP(call_combiner_,
"batch does not include send_initial_metadata");
}
}
-void ClientChannel::LoadBalancedCall::SendInitialMetadataOnComplete(
- void* arg, grpc_error_handle error) {
- auto* self = static_cast<LoadBalancedCall*>(arg);
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p lb_call=%p: got on_complete for send_initial_metadata: "
- "error=%s",
- self->chand_, self, StatusToString(error).c_str());
- }
- self->call_attempt_tracer_->RecordOnDoneSendInitialMetadata(
- self->peer_string_);
- Closure::Run(DEBUG_LOCATION,
- self->original_send_initial_metadata_on_complete_, error);
-}
-
-void ClientChannel::LoadBalancedCall::RecvInitialMetadataReady(
+void ClientChannel::FilterBasedLoadBalancedCall::RecvInitialMetadataReady(
void* arg, grpc_error_handle error) {
- auto* self = static_cast<LoadBalancedCall*>(arg);
+ auto* self = static_cast<FilterBasedLoadBalancedCall*>(arg);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
gpr_log(GPR_INFO,
"chand=%p lb_call=%p: got recv_initial_metadata_ready: error=%s",
- self->chand_, self, StatusToString(error).c_str());
+ self->chand(), self, StatusToString(error).c_str());
}
if (error.ok()) {
// recv_initial_metadata_flags is not populated for clients
- self->call_attempt_tracer_->RecordReceivedInitialMetadata(
- self->recv_initial_metadata_, 0 /* recv_initial_metadata_flags */);
+ self->call_attempt_tracer()->RecordReceivedInitialMetadata(
+ self->recv_initial_metadata_);
+ auto* peer_string = self->recv_initial_metadata_->get_pointer(PeerString());
+ if (peer_string != nullptr) self->peer_string_ = peer_string->Ref();
}
Closure::Run(DEBUG_LOCATION, self->original_recv_initial_metadata_ready_,
error);
}
-void ClientChannel::LoadBalancedCall::RecvMessageReady(
- void* arg, grpc_error_handle error) {
- auto* self = static_cast<LoadBalancedCall*>(arg);
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
- gpr_log(GPR_INFO, "chand=%p lb_call=%p: got recv_message_ready: error=%s",
- self->chand_, self, StatusToString(error).c_str());
- }
- if (self->recv_message_->has_value()) {
- self->call_attempt_tracer_->RecordReceivedMessage(**self->recv_message_);
- }
- Closure::Run(DEBUG_LOCATION, self->original_recv_message_ready_, error);
-}
-
-void ClientChannel::LoadBalancedCall::RecvTrailingMetadataReady(
+void ClientChannel::FilterBasedLoadBalancedCall::RecvTrailingMetadataReady(
void* arg, grpc_error_handle error) {
- auto* self = static_cast<LoadBalancedCall*>(arg);
+ auto* self = static_cast<FilterBasedLoadBalancedCall*>(arg);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
gpr_log(GPR_INFO,
"chand=%p lb_call=%p: got recv_trailing_metadata_ready: error=%s "
- "call_attempt_tracer_=%p lb_subchannel_call_tracker_=%p "
+ "call_attempt_tracer()=%p lb_subchannel_call_tracker_=%p "
"failure_error_=%s",
- self->chand_, self, StatusToString(error).c_str(),
- self->call_attempt_tracer_, self->lb_subchannel_call_tracker_.get(),
+ self->chand(), self, StatusToString(error).c_str(),
+ self->call_attempt_tracer(), self->lb_subchannel_call_tracker(),
StatusToString(self->failure_error_).c_str());
}
// Check if we have a tracer or an LB callback to invoke.
- if (self->call_attempt_tracer_ != nullptr ||
- self->lb_subchannel_call_tracker_ != nullptr) {
+ if (self->call_attempt_tracer() != nullptr ||
+ self->lb_subchannel_call_tracker() != nullptr) {
// Get the call's status.
y_absl::Status status;
if (!error.ok()) {
@@ -2917,7 +3081,12 @@ void ClientChannel::LoadBalancedCall::RecvTrailingMetadataReady(
status = y_absl::Status(static_cast<y_absl::StatusCode>(code), message);
}
}
- self->RecordCallCompletion(status);
+ y_absl::string_view peer_string;
+ if (self->peer_string_.has_value()) {
+ peer_string = self->peer_string_->as_string_view();
+ }
+ self->RecordCallCompletion(status, self->recv_trailing_metadata_,
+ self->transport_stream_stats_, peer_string);
}
// Chain to original callback.
if (!self->failure_error_.ok()) {
@@ -2928,54 +3097,6 @@ void ClientChannel::LoadBalancedCall::RecvTrailingMetadataReady(
error);
}
-void ClientChannel::LoadBalancedCall::RecordCallCompletion(
- y_absl::Status status) {
- // If we have a tracer, notify it.
- if (call_attempt_tracer_ != nullptr) {
- call_attempt_tracer_->RecordReceivedTrailingMetadata(
- status, recv_trailing_metadata_, transport_stream_stats_);
- }
- // If the LB policy requested a callback for trailing metadata, invoke
- // the callback.
- if (lb_subchannel_call_tracker_ != nullptr) {
- Metadata trailing_metadata(recv_trailing_metadata_);
- BackendMetricAccessor backend_metric_accessor(this);
- const char* peer_string =
- peer_string_ != nullptr
- ? reinterpret_cast<char*>(gpr_atm_acq_load(peer_string_))
- : "";
- LoadBalancingPolicy::SubchannelCallTrackerInterface::FinishArgs args = {
- peer_string, status, &trailing_metadata, &backend_metric_accessor};
- lb_subchannel_call_tracker_->Finish(args);
- lb_subchannel_call_tracker_.reset();
- }
-}
-
-void ClientChannel::LoadBalancedCall::CreateSubchannelCall() {
- SubchannelCall::Args call_args = {
- std::move(connected_subchannel_), pollent_, path_.Ref(), /*start_time=*/0,
- deadline_, arena_,
- // TODO(roth): When we implement hedging support, we will probably
- // need to use a separate call context for each subchannel call.
- call_context_, call_combiner_};
- grpc_error_handle error;
- subchannel_call_ = SubchannelCall::Create(std::move(call_args), &error);
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p lb_call=%p: create subchannel_call=%p: error=%s", chand_,
- this, subchannel_call_.get(), StatusToString(error).c_str());
- }
- if (on_call_destruction_complete_ != nullptr) {
- subchannel_call_->SetAfterCallStackDestroy(on_call_destruction_complete_);
- on_call_destruction_complete_ = nullptr;
- }
- if (GPR_UNLIKELY(!error.ok())) {
- PendingBatchesFail(error, YieldCallCombiner);
- } else {
- PendingBatchesResume();
- }
-}
-
// A class to handle the call combiner cancellation callback for a
// queued pick.
// TODO(roth): When we implement hedging support, we won't be able to
@@ -2983,9 +3104,10 @@ void ClientChannel::LoadBalancedCall::CreateSubchannelCall() {
// because there may be multiple LB picks happening in parallel.
// Instead, we will probably need to maintain a list in the CallData
// object of pending LB picks to be cancelled when the closure runs.
-class ClientChannel::LoadBalancedCall::LbQueuedCallCanceller {
+class ClientChannel::FilterBasedLoadBalancedCall::LbQueuedCallCanceller {
public:
- explicit LbQueuedCallCanceller(RefCountedPtr<LoadBalancedCall> lb_call)
+ explicit LbQueuedCallCanceller(
+ RefCountedPtr<FilterBasedLoadBalancedCall> lb_call)
: lb_call_(std::move(lb_call)) {
GRPC_CALL_STACK_REF(lb_call_->owning_call_, "LbQueuedCallCanceller");
GRPC_CLOSURE_INIT(&closure_, &CancelLocked, this, nullptr);
@@ -2996,9 +3118,9 @@ class ClientChannel::LoadBalancedCall::LbQueuedCallCanceller {
static void CancelLocked(void* arg, grpc_error_handle error) {
auto* self = static_cast<LbQueuedCallCanceller*>(arg);
auto* lb_call = self->lb_call_.get();
- auto* chand = lb_call->chand_;
+ auto* chand = lb_call->chand();
{
- MutexLock lock(&chand->data_plane_mu_);
+ MutexLock lock(&chand->lb_mu_);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
gpr_log(GPR_INFO,
"chand=%p lb_call=%p: cancelling queued pick: "
@@ -3007,187 +3129,98 @@ class ClientChannel::LoadBalancedCall::LbQueuedCallCanceller {
lb_call->lb_call_canceller_);
}
if (lb_call->lb_call_canceller_ == self && !error.ok()) {
- lb_call->call_dispatch_controller_->Commit();
+ lb_call->call_dispatch_controller()->Commit();
// Remove pick from list of queued picks.
- lb_call->MaybeRemoveCallFromLbQueuedCallsLocked();
+ lb_call->RemoveCallFromLbQueuedCallsLocked();
+ // Remove from queued picks list.
+ chand->lb_queued_calls_.erase(lb_call);
// Fail pending batches on the call.
lb_call->PendingBatchesFail(error,
YieldCallCombinerIfPendingBatchesFound);
}
}
- GRPC_CALL_STACK_UNREF(lb_call->owning_call_, "LbQueuedCallCanceller");
+ // Unref lb_call before unreffing the call stack, since unreffing
+ // the call stack may destroy the arena in which lb_call is allocated.
+ auto* owning_call = lb_call->owning_call_;
+ self->lb_call_.reset();
+ GRPC_CALL_STACK_UNREF(owning_call, "LbQueuedCallCanceller");
delete self;
}
- RefCountedPtr<LoadBalancedCall> lb_call_;
+ RefCountedPtr<FilterBasedLoadBalancedCall> lb_call_;
grpc_closure closure_;
};
-void ClientChannel::LoadBalancedCall::MaybeRemoveCallFromLbQueuedCallsLocked() {
- if (!queued_pending_lb_pick_) return;
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
- gpr_log(GPR_INFO, "chand=%p lb_call=%p: removing from queued picks list",
- chand_, this);
- }
- chand_->RemoveLbQueuedCall(&queued_call_, pollent_);
- queued_pending_lb_pick_ = false;
- // Lame the call combiner canceller.
- lb_call_canceller_ = nullptr;
- // Add trace annotation
- if (call_attempt_tracer_ != nullptr) {
- call_attempt_tracer_->RecordAnnotation("Delayed LB pick complete.");
+void ClientChannel::FilterBasedLoadBalancedCall::TryPick(bool was_queued) {
+ auto result = PickSubchannel(was_queued);
+ if (result.has_value()) {
+ if (!result->ok()) {
+ PendingBatchesFail(*result, YieldCallCombiner);
+ return;
+ }
+ CreateSubchannelCall();
}
}
-void ClientChannel::LoadBalancedCall::MaybeAddCallToLbQueuedCallsLocked() {
- if (queued_pending_lb_pick_) return;
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
- gpr_log(GPR_INFO, "chand=%p lb_call=%p: adding to queued picks list",
- chand_, this);
- }
- queued_pending_lb_pick_ = true;
- queued_call_.lb_call = this;
- chand_->AddLbQueuedCall(&queued_call_, pollent_);
+void ClientChannel::FilterBasedLoadBalancedCall::OnAddToQueueLocked() {
// Register call combiner cancellation callback.
lb_call_canceller_ = new LbQueuedCallCanceller(Ref());
}
-void ClientChannel::LoadBalancedCall::AsyncPickDone(grpc_error_handle error) {
- // TODO(roth): Does this callback need to hold a ref to LoadBalancedCall?
- GRPC_CLOSURE_INIT(&pick_closure_, PickDone, this, grpc_schedule_on_exec_ctx);
- ExecCtx::Run(DEBUG_LOCATION, &pick_closure_, error);
-}
-
-void ClientChannel::LoadBalancedCall::PickDone(void* arg,
- grpc_error_handle error) {
- auto* self = static_cast<LoadBalancedCall*>(arg);
- if (!error.ok()) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p lb_call=%p: failed to pick subchannel: error=%s",
- self->chand_, self, StatusToString(error).c_str());
- }
- self->PendingBatchesFail(error, YieldCallCombiner);
- return;
+void ClientChannel::FilterBasedLoadBalancedCall::RetryPickLocked() {
+ // Lame the call combiner canceller.
+ lb_call_canceller_ = nullptr;
+ // Do an async callback to resume call processing, so that we're not
+ // doing it while holding the channel's LB mutex.
+ // TODO(roth): We should really be using EventEngine::Run() here
+ // instead of ExecCtx::Run(). Unfortunately, doing that seems to cause
+ // a flaky TSAN failure for reasons that I do not fully understand.
+ // However, given that we are working toward eliminating this code as
+ // part of the promise conversion, it doesn't seem worth further
+ // investigation right now.
+ ExecCtx::Run(DEBUG_LOCATION, NewClosure([this](grpc_error_handle) {
+ // If there are a lot of queued calls here, resuming them
+ // all may cause us to stay inside C-core for a long period
+ // of time. All of that work would be done using the same
+ // ExecCtx instance and therefore the same cached value of
+ // "now". The longer it takes to finish all of this work
+ // and exit from C-core, the more stale the cached value of
+ // "now" may become. This can cause problems whereby (e.g.)
+ // we calculate a timer deadline based on the stale value,
+ // which results in the timer firing too early. To avoid
+ // this, we invalidate the cached value for each call we
+ // process.
+ ExecCtx::Get()->InvalidateNow();
+ TryPick(/*was_queued=*/true);
+ }),
+ y_absl::OkStatus());
+}
+
+void ClientChannel::FilterBasedLoadBalancedCall::CreateSubchannelCall() {
+ Slice* path = send_initial_metadata()->get_pointer(HttpPathMetadata());
+ GPR_ASSERT(path != nullptr);
+ SubchannelCall::Args call_args = {
+ connected_subchannel()->Ref(), pollent_, path->Ref(), /*start_time=*/0,
+ deadline_, arena_,
+ // TODO(roth): When we implement hedging support, we will probably
+ // need to use a separate call context for each subchannel call.
+ call_context_, call_combiner_};
+ grpc_error_handle error;
+ subchannel_call_ = SubchannelCall::Create(std::move(call_args), &error);
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
+ gpr_log(GPR_INFO,
+ "chand=%p lb_call=%p: create subchannel_call=%p: error=%s", chand(),
+ this, subchannel_call_.get(), StatusToString(error).c_str());
}
- self->call_dispatch_controller_->Commit();
- self->CreateSubchannelCall();
-}
-
-void ClientChannel::LoadBalancedCall::PickSubchannel(void* arg,
- grpc_error_handle error) {
- auto* self = static_cast<LoadBalancedCall*>(arg);
- bool pick_complete;
- {
- MutexLock lock(&self->chand_->data_plane_mu_);
- pick_complete = self->PickSubchannelLocked(&error);
+ if (on_call_destruction_complete_ != nullptr) {
+ subchannel_call_->SetAfterCallStackDestroy(on_call_destruction_complete_);
+ on_call_destruction_complete_ = nullptr;
}
- if (pick_complete) {
- PickDone(self, error);
+ if (GPR_UNLIKELY(!error.ok())) {
+ PendingBatchesFail(error, YieldCallCombiner);
+ } else {
+ PendingBatchesResume();
}
}
-bool ClientChannel::LoadBalancedCall::PickSubchannelLocked(
- grpc_error_handle* error) {
- GPR_ASSERT(connected_subchannel_ == nullptr);
- GPR_ASSERT(subchannel_call_ == nullptr);
- // Grab initial metadata.
- auto& send_initial_metadata =
- pending_batches_[0]->payload->send_initial_metadata;
- grpc_metadata_batch* initial_metadata_batch =
- send_initial_metadata.send_initial_metadata;
- // Perform LB pick.
- LoadBalancingPolicy::PickArgs pick_args;
- pick_args.path = path_.as_string_view();
- LbCallState lb_call_state(this);
- pick_args.call_state = &lb_call_state;
- Metadata initial_metadata(initial_metadata_batch);
- pick_args.initial_metadata = &initial_metadata;
- auto result = chand_->picker_->Pick(pick_args);
- return HandlePickResult<bool>(
- &result,
- // CompletePick
- [this](LoadBalancingPolicy::PickResult::Complete* complete_pick)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p lb_call=%p: LB pick succeeded: subchannel=%p",
- chand_, this, complete_pick->subchannel.get());
- }
- GPR_ASSERT(complete_pick->subchannel != nullptr);
- // Grab a ref to the connected subchannel while we're still
- // holding the data plane mutex.
- SubchannelWrapper* subchannel = static_cast<SubchannelWrapper*>(
- complete_pick->subchannel.get());
- connected_subchannel_ = subchannel->connected_subchannel();
- // If the subchannel has no connected subchannel (e.g., if the
- // subchannel has moved out of state READY but the LB policy hasn't
- // yet seen that change and given us a new picker), then just
- // queue the pick. We'll try again as soon as we get a new picker.
- if (connected_subchannel_ == nullptr) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p lb_call=%p: subchannel returned by LB picker "
- "has no connected subchannel; queueing pick",
- chand_, this);
- }
- MaybeAddCallToLbQueuedCallsLocked();
- return false;
- }
- lb_subchannel_call_tracker_ =
- std::move(complete_pick->subchannel_call_tracker);
- if (lb_subchannel_call_tracker_ != nullptr) {
- lb_subchannel_call_tracker_->Start();
- }
- MaybeRemoveCallFromLbQueuedCallsLocked();
- return true;
- },
- // QueuePick
- [this](LoadBalancingPolicy::PickResult::Queue* /*queue_pick*/)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
- gpr_log(GPR_INFO, "chand=%p lb_call=%p: LB pick queued", chand_,
- this);
- }
- MaybeAddCallToLbQueuedCallsLocked();
- return false;
- },
- // FailPick
- [this, initial_metadata_batch,
- &error](LoadBalancingPolicy::PickResult::Fail* fail_pick)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
- gpr_log(GPR_INFO, "chand=%p lb_call=%p: LB pick failed: %s",
- chand_, this, fail_pick->status.ToString().c_str());
- }
- // If wait_for_ready is false, then the error indicates the RPC
- // attempt's final status.
- if (!initial_metadata_batch->GetOrCreatePointer(WaitForReady())
- ->value) {
- *error = absl_status_to_grpc_error(MaybeRewriteIllegalStatusCode(
- std::move(fail_pick->status), "LB pick"));
- MaybeRemoveCallFromLbQueuedCallsLocked();
- return true;
- }
- // If wait_for_ready is true, then queue to retry when we get a new
- // picker.
- MaybeAddCallToLbQueuedCallsLocked();
- return false;
- },
- // DropPick
- [this, &error](LoadBalancingPolicy::PickResult::Drop* drop_pick)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
- gpr_log(GPR_INFO, "chand=%p lb_call=%p: LB pick dropped: %s",
- chand_, this, drop_pick->status.ToString().c_str());
- }
- *error = grpc_error_set_int(
- absl_status_to_grpc_error(MaybeRewriteIllegalStatusCode(
- std::move(drop_pick->status), "LB drop")),
- StatusIntProperty::kLbPolicyDrop, 1);
- MaybeRemoveCallFromLbQueuedCallsLocked();
- return true;
- });
-}
-
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.h
index 33df4dd4b0..257ffe2a69 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.h
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.h
@@ -24,24 +24,21 @@
#include <atomic>
#include <map>
#include <memory>
-#include <set>
#include <util/generic/string.h>
#include <util/string/cast.h>
-#include <utility>
#include "y_absl/base/thread_annotations.h"
+#include "y_absl/container/flat_hash_set.h"
#include "y_absl/status/status.h"
#include "y_absl/strings/string_view.h"
#include "y_absl/types/optional.h"
#include <grpc/grpc.h>
#include <grpc/impl/connectivity_state.h>
-#include <grpc/support/atm.h>
#include "src/core/ext/filters/client_channel/client_channel_factory.h"
#include "src/core/ext/filters/client_channel/config_selector.h"
#include "src/core/ext/filters/client_channel/dynamic_filters.h"
-#include "src/core/ext/filters/client_channel/lb_call_state_internal.h"
#include "src/core/ext/filters/client_channel/lb_policy/backend_metric_data.h"
#include "src/core/ext/filters/client_channel/subchannel.h"
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
@@ -57,7 +54,6 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/gprpp/time.h"
-#include "src/core/lib/gprpp/unique_type_name.h"
#include "src/core/lib/gprpp/work_serializer.h"
#include "src/core/lib/iomgr/call_combiner.h"
#include "src/core/lib/iomgr/closure.h"
@@ -68,10 +64,7 @@
#include "src/core/lib/resolver/resolver.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/service_config/service_config.h"
-#include "src/core/lib/service_config/service_config_call_data.h"
-#include "src/core/lib/service_config/service_config_parser.h"
#include "src/core/lib/slice/slice.h"
-#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/metadata_batch.h"
@@ -111,6 +104,7 @@ class ClientChannel {
static const grpc_channel_filter kFilterVtable;
class LoadBalancedCall;
+ class FilterBasedLoadBalancedCall;
// Flag that this object gets stored in channel args as a raw pointer.
struct RawPointerChannelArgTag {};
@@ -164,7 +158,7 @@ class ClientChannel {
void RemoveConnectivityWatcher(
AsyncConnectivityStateWatcherInterface* watcher);
- OrphanablePtr<LoadBalancedCall> CreateLoadBalancedCall(
+ OrphanablePtr<FilterBasedLoadBalancedCall> CreateLoadBalancedCall(
const grpc_call_element_args& args, grpc_polling_entity* pollent,
grpc_closure* on_call_destruction_complete,
ConfigSelector::CallDispatchController* call_dispatch_controller,
@@ -178,6 +172,7 @@ class ClientChannel {
private:
class CallData;
+ class FilterBasedCallData;
class ResolverResultHandler;
class SubchannelWrapper;
class ClientChannelControlHelper;
@@ -223,15 +218,6 @@ class ClientChannel {
std::atomic<bool> done_{false};
};
- struct ResolverQueuedCall {
- grpc_call_element* elem;
- ResolverQueuedCall* next = nullptr;
- };
- struct LbQueuedCall {
- LoadBalancedCall* lb_call;
- LbQueuedCall* next = nullptr;
- };
-
ClientChannel(grpc_channel_element_args* args, grpc_error_handle* error);
~ClientChannel();
@@ -247,6 +233,9 @@ class ClientChannel {
// Note: All methods with "Locked" suffix must be invoked from within
// work_serializer_.
+ void ReprocessQueuedResolverCalls()
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&resolution_mu_);
+
void OnResolverResultChangedLocked(Resolver::Result result)
Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
void OnResolverErrorLocked(y_absl::Status status)
@@ -285,20 +274,6 @@ class ClientChannel {
void TryToConnectLocked() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(*work_serializer_);
- // These methods all require holding resolution_mu_.
- void AddResolverQueuedCall(ResolverQueuedCall* call,
- grpc_polling_entity* pollent)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(resolution_mu_);
- void RemoveResolverQueuedCall(ResolverQueuedCall* to_remove,
- grpc_polling_entity* pollent)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(resolution_mu_);
-
- // These methods all require holding data_plane_mu_.
- void AddLbQueuedCall(LbQueuedCall* call, grpc_polling_entity* pollent)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(data_plane_mu_);
- void RemoveLbQueuedCall(LbQueuedCall* to_remove, grpc_polling_entity* pollent)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(data_plane_mu_);
-
//
// Fields set at construction and never modified.
//
@@ -317,9 +292,9 @@ class ClientChannel {
// Fields related to name resolution. Guarded by resolution_mu_.
//
mutable Mutex resolution_mu_;
- // Linked list of calls queued waiting for resolver result.
- ResolverQueuedCall* resolver_queued_calls_ Y_ABSL_GUARDED_BY(resolution_mu_) =
- nullptr;
+ // List of calls queued waiting for resolver result.
+ y_absl::flat_hash_set<CallData*> resolver_queued_calls_
+ Y_ABSL_GUARDED_BY(resolution_mu_);
// Data from service config.
y_absl::Status resolver_transient_failure_error_
Y_ABSL_GUARDED_BY(resolution_mu_);
@@ -331,13 +306,13 @@ class ClientChannel {
Y_ABSL_GUARDED_BY(resolution_mu_);
//
- // Fields used in the data plane. Guarded by data_plane_mu_.
+ // Fields related to LB picks. Guarded by lb_mu_.
//
- mutable Mutex data_plane_mu_;
+ mutable Mutex lb_mu_;
RefCountedPtr<LoadBalancingPolicy::SubchannelPicker> picker_
- Y_ABSL_GUARDED_BY(data_plane_mu_);
- // Linked list of calls queued waiting for LB pick.
- LbQueuedCall* lb_queued_calls_ Y_ABSL_GUARDED_BY(data_plane_mu_) = nullptr;
+ Y_ABSL_GUARDED_BY(lb_mu_);
+ y_absl::flat_hash_set<LoadBalancedCall*> lb_queued_calls_
+ Y_ABSL_GUARDED_BY(lb_mu_);
//
// Fields used in the control plane. Guarded by work_serializer.
@@ -361,7 +336,7 @@ class ClientChannel {
// The set of SubchannelWrappers that currently exist.
// No need to hold a ref, since the map is updated in the control-plane
// work_serializer when the SubchannelWrappers are created and destroyed.
- std::set<SubchannelWrapper*> subchannel_wrappers_
+ y_absl::flat_hash_set<SubchannelWrapper*> subchannel_wrappers_
Y_ABSL_GUARDED_BY(*work_serializer_);
int keepalive_time_ Y_ABSL_GUARDED_BY(*work_serializer_) = -1;
grpc_error_handle disconnect_error_ Y_ABSL_GUARDED_BY(*work_serializer_);
@@ -390,58 +365,135 @@ class ClientChannel {
// TODO(roth): As part of simplifying cancellation in the filter stack,
// this should no longer need to be ref-counted.
class ClientChannel::LoadBalancedCall
- : public InternallyRefCounted<LoadBalancedCall, kUnrefCallDtor> {
+ : public InternallyRefCounted<LoadBalancedCall, UnrefCallDtor> {
public:
- class LbCallState : public LbCallStateInternal {
- public:
- explicit LbCallState(LoadBalancedCall* lb_call) : lb_call_(lb_call) {}
+ LoadBalancedCall(
+ ClientChannel* chand, grpc_call_context_element* call_context,
+ ConfigSelector::CallDispatchController* call_dispatch_controller,
+ bool is_transparent_retry);
+ ~LoadBalancedCall() override;
- void* Alloc(size_t size) override { return lb_call_->arena_->Alloc(size); }
+ void Orphan() override;
- // Internal API to allow first-party LB policies to access per-call
- // attributes set by the ConfigSelector.
- y_absl::string_view GetCallAttribute(UniqueTypeName type) override;
+ // Called by channel when removing a call from the list of queued calls.
+ void RemoveCallFromLbQueuedCallsLocked()
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::lb_mu_);
- private:
- LoadBalancedCall* lb_call_;
- };
+ // Called by the channel for each queued call when a new picker
+ // becomes available.
+ virtual void RetryPickLocked()
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::lb_mu_) = 0;
+
+ protected:
+ ClientChannel* chand() const { return chand_; }
+ ConfigSelector::CallDispatchController* call_dispatch_controller() const {
+ return call_dispatch_controller_;
+ }
+ ClientCallTracer::CallAttemptTracer* call_attempt_tracer() const {
+ return static_cast<ClientCallTracer::CallAttemptTracer*>(
+ call_context()[GRPC_CONTEXT_CALL_TRACER].value);
+ }
+ gpr_cycle_counter lb_call_start_time() const { return lb_call_start_time_; }
+ ConnectedSubchannel* connected_subchannel() const {
+ return connected_subchannel_.get();
+ }
+ LoadBalancingPolicy::SubchannelCallTrackerInterface*
+ lb_subchannel_call_tracker() const {
+ return lb_subchannel_call_tracker_.get();
+ }
+
+ // Attempts an LB pick. The following outcomes are possible:
+ // - No pick result is available yet. The call will be queued and
+ // nullopt will be returned. The channel will later call
+ // RetryPickLocked() when a new picker is available and the pick
+ // should be retried.
+ // - The pick failed. If the call is not wait_for_ready, a non-OK
+ // status will be returned. (If the call *is* wait_for_ready,
+ // it will be queued instead.)
+ // - The pick completed successfully. A connected subchannel is
+ // stored and an OK status will be returned.
+ y_absl::optional<y_absl::Status> PickSubchannel(bool was_queued);
+
+ void RecordCallCompletion(y_absl::Status status,
+ grpc_metadata_batch* recv_trailing_metadata,
+ grpc_transport_stream_stats* transport_stream_stats,
+ y_absl::string_view peer_address);
+
+ private:
+ class LbCallState;
+ class Metadata;
+ class BackendMetricAccessor;
+
+ virtual Arena* arena() const = 0;
+ virtual grpc_call_context_element* call_context() const = 0;
+ virtual grpc_polling_entity* pollent() const = 0;
+ virtual grpc_metadata_batch* send_initial_metadata() const = 0;
+
+ // Helper function for performing an LB pick with a specified picker.
+ // Returns true if the pick is complete.
+ bool PickSubchannelImpl(LoadBalancingPolicy::SubchannelPicker* picker,
+ grpc_error_handle* error);
+ // Adds the call to the channel's list of queued picks if not already present.
+ void AddCallToLbQueuedCallsLocked()
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::lb_mu_);
+
+ // Called when adding the call to the LB queue.
+ virtual void OnAddToQueueLocked()
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::lb_mu_) {}
+
+ ClientChannel* chand_;
+
+ ConfigSelector::CallDispatchController* call_dispatch_controller_;
+ gpr_cycle_counter lb_call_start_time_ = gpr_get_cycle_counter();
+
+ RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
+ const BackendMetricData* backend_metric_data_ = nullptr;
+ std::unique_ptr<LoadBalancingPolicy::SubchannelCallTrackerInterface>
+ lb_subchannel_call_tracker_;
+};
+
+class ClientChannel::FilterBasedLoadBalancedCall
+ : public ClientChannel::LoadBalancedCall {
+ public:
// If on_call_destruction_complete is non-null, then it will be
// invoked once the LoadBalancedCall is completely destroyed.
// If it is null, then the caller is responsible for checking whether
// the LB call has a subchannel call and ensuring that the
// on_call_destruction_complete closure passed down from the surface
// is not invoked until after the subchannel call stack is destroyed.
- LoadBalancedCall(
+ FilterBasedLoadBalancedCall(
ClientChannel* chand, const grpc_call_element_args& args,
grpc_polling_entity* pollent, grpc_closure* on_call_destruction_complete,
ConfigSelector::CallDispatchController* call_dispatch_controller,
bool is_transparent_retry);
- ~LoadBalancedCall() override;
+ ~FilterBasedLoadBalancedCall() override;
void Orphan() override;
void StartTransportStreamOpBatch(grpc_transport_stream_op_batch* batch);
- // Invoked by channel for queued LB picks when the picker is updated.
- static void PickSubchannel(void* arg, grpc_error_handle error);
- // Helper function for performing an LB pick while holding the data plane
- // mutex. Returns true if the pick is complete, in which case the caller
- // must invoke PickDone() or AsyncPickDone() with the returned error.
- bool PickSubchannelLocked(grpc_error_handle* error)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_);
- // Schedules a callback to process the completed pick. The callback
- // will not run until after this method returns.
- void AsyncPickDone(grpc_error_handle error);
-
RefCountedPtr<SubchannelCall> subchannel_call() const {
return subchannel_call_;
}
private:
class LbQueuedCallCanceller;
- class Metadata;
- class BackendMetricAccessor;
+
+ // Work-around for Windows compilers that don't allow nested classes
+ // to access protected members of the enclosing class's parent class.
+ using LoadBalancedCall::call_dispatch_controller;
+ using LoadBalancedCall::chand;
+
+ Arena* arena() const override { return arena_; }
+ grpc_call_context_element* call_context() const override {
+ return call_context_;
+ }
+ grpc_polling_entity* pollent() const override { return pollent_; }
+ grpc_metadata_batch* send_initial_metadata() const override {
+ return pending_batches_[0]
+ ->payload->send_initial_metadata.send_initial_metadata;
+ }
// Returns the index into pending_batches_ to be used for batch.
static size_t GetBatchIndex(grpc_transport_stream_op_batch* batch);
@@ -474,39 +526,31 @@ class ClientChannel::LoadBalancedCall
static void SendInitialMetadataOnComplete(void* arg, grpc_error_handle error);
static void RecvInitialMetadataReady(void* arg, grpc_error_handle error);
- static void RecvMessageReady(void* arg, grpc_error_handle error);
static void RecvTrailingMetadataReady(void* arg, grpc_error_handle error);
- void RecordCallCompletion(y_absl::Status status);
+ // Called to perform a pick, both when the call is initially started
+ // and when it is queued and the channel gets a new picker.
+ void TryPick(bool was_queued);
- void CreateSubchannelCall();
- // Invoked when a pick is completed, on both success or failure.
- static void PickDone(void* arg, grpc_error_handle error);
- // Removes the call from the channel's list of queued picks if present.
- void MaybeRemoveCallFromLbQueuedCallsLocked()
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_);
- // Adds the call to the channel's list of queued picks if not already present.
- void MaybeAddCallToLbQueuedCallsLocked()
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_);
+ void OnAddToQueueLocked() override
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::lb_mu_);
- ClientChannel* chand_;
+ void RetryPickLocked() override
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::lb_mu_);
+
+ void CreateSubchannelCall();
// TODO(roth): Instead of duplicating these fields in every filter
// that uses any one of them, we should store them in the call
// context. This will save per-call memory overhead.
- Slice path_; // Request path.
Timestamp deadline_;
Arena* arena_;
+ grpc_call_context_element* call_context_;
grpc_call_stack* owning_call_;
CallCombiner* call_combiner_;
- grpc_call_context_element* call_context_;
grpc_polling_entity* pollent_;
grpc_closure* on_call_destruction_complete_;
- ConfigSelector::CallDispatchController* call_dispatch_controller_;
-
- CallTracer::CallAttemptTracer* call_attempt_tracer_;
-
- gpr_cycle_counter lb_call_start_time_ = gpr_get_cycle_counter();
+ y_absl::optional<Slice> peer_string_;
// Set when we get a cancel_stream op.
grpc_error_handle cancel_error_;
@@ -514,38 +558,17 @@ class ClientChannel::LoadBalancedCall
// Set when we fail inside the LB call.
grpc_error_handle failure_error_;
- grpc_closure pick_closure_;
-
- // Accessed while holding ClientChannel::data_plane_mu_.
- ClientChannel::LbQueuedCall queued_call_
- Y_ABSL_GUARDED_BY(&ClientChannel::data_plane_mu_);
- bool queued_pending_lb_pick_ Y_ABSL_GUARDED_BY(&ClientChannel::data_plane_mu_) =
- false;
+ // Accessed while holding ClientChannel::lb_mu_.
LbQueuedCallCanceller* lb_call_canceller_
- Y_ABSL_GUARDED_BY(&ClientChannel::data_plane_mu_) = nullptr;
-
- RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
- const BackendMetricData* backend_metric_data_ = nullptr;
- std::unique_ptr<LoadBalancingPolicy::SubchannelCallTrackerInterface>
- lb_subchannel_call_tracker_;
+ Y_ABSL_GUARDED_BY(&ClientChannel::lb_mu_) = nullptr;
RefCountedPtr<SubchannelCall> subchannel_call_;
- // For intercepting send_initial_metadata on_complete.
- gpr_atm* peer_string_ = nullptr;
- grpc_closure send_initial_metadata_on_complete_;
- grpc_closure* original_send_initial_metadata_on_complete_ = nullptr;
-
// For intercepting recv_initial_metadata_ready.
grpc_metadata_batch* recv_initial_metadata_ = nullptr;
grpc_closure recv_initial_metadata_ready_;
grpc_closure* original_recv_initial_metadata_ready_ = nullptr;
- // For intercepting recv_message_ready.
- y_absl::optional<SliceBuffer>* recv_message_ = nullptr;
- grpc_closure recv_message_ready_;
- grpc_closure* original_recv_message_ready_ = nullptr;
-
// For intercepting recv_trailing_metadata_ready.
grpc_metadata_batch* recv_trailing_metadata_ = nullptr;
grpc_transport_stream_stats* transport_stream_stats_ = nullptr;
@@ -560,69 +583,6 @@ class ClientChannel::LoadBalancedCall
grpc_transport_stream_op_batch* pending_batches_[MAX_PENDING_BATCHES] = {};
};
-// A sub-class of ServiceConfigCallData used to access the
-// CallDispatchController. Allocated on the arena, stored in the call
-// context, and destroyed when the call is destroyed.
-class ClientChannelServiceConfigCallData : public ServiceConfigCallData {
- public:
- ClientChannelServiceConfigCallData(
- RefCountedPtr<ServiceConfig> service_config,
- const ServiceConfigParser::ParsedConfigVector* method_configs,
- ServiceConfigCallData::CallAttributes call_attributes,
- ConfigSelector::CallDispatchController* call_dispatch_controller,
- grpc_call_context_element* call_context)
- : ServiceConfigCallData(std::move(service_config), method_configs,
- std::move(call_attributes)),
- call_dispatch_controller_(call_dispatch_controller) {
- call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = this;
- call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].destroy = Destroy;
- }
-
- ConfigSelector::CallDispatchController* call_dispatch_controller() {
- return &call_dispatch_controller_;
- }
-
- private:
- // A wrapper for the CallDispatchController returned by the ConfigSelector.
- // Handles the case where the ConfigSelector doees not return any
- // CallDispatchController.
- // Also ensures that we call Commit() at most once, which allows the
- // client channel code to call Commit() when the call is complete in case
- // it wasn't called earlier, without needing to know whether or not it was.
- class CallDispatchControllerWrapper
- : public ConfigSelector::CallDispatchController {
- public:
- explicit CallDispatchControllerWrapper(
- ConfigSelector::CallDispatchController* call_dispatch_controller)
- : call_dispatch_controller_(call_dispatch_controller) {}
-
- bool ShouldRetry() override {
- if (call_dispatch_controller_ != nullptr) {
- return call_dispatch_controller_->ShouldRetry();
- }
- return true;
- }
-
- void Commit() override {
- if (call_dispatch_controller_ != nullptr && !commit_called_) {
- call_dispatch_controller_->Commit();
- commit_called_ = true;
- }
- }
-
- private:
- ConfigSelector::CallDispatchController* call_dispatch_controller_;
- bool commit_called_ = false;
- };
-
- static void Destroy(void* ptr) {
- auto* self = static_cast<ClientChannelServiceConfigCallData*>(ptr);
- self->~ClientChannelServiceConfigCallData();
- }
-
- CallDispatchControllerWrapper call_dispatch_controller_;
-};
-
} // namespace grpc_core
#endif // GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel_internal.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel_internal.h
new file mode 100644
index 0000000000..44006242b3
--- /dev/null
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel_internal.h
@@ -0,0 +1,114 @@
+//
+// Copyright 2015 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_INTERNAL_H
+#define GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_INTERNAL_H
+
+#include <grpc/support/port_platform.h>
+
+#include <utility>
+
+#include "y_absl/strings/string_view.h"
+
+#include "src/core/ext/filters/client_channel/config_selector.h"
+#include "src/core/lib/channel/context.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/gprpp/unique_type_name.h"
+#include "src/core/lib/load_balancing/lb_policy.h"
+#include "src/core/lib/service_config/service_config.h"
+#include "src/core/lib/service_config/service_config_call_data.h"
+#include "src/core/lib/service_config/service_config_parser.h"
+
+//
+// This file contains internal interfaces used to allow various plugins
+// (filters, LB policies, etc) to access internal data provided by the
+// ClientChannel that is not normally accessible via external APIs.
+//
+
+namespace grpc_core {
+
+// Internal type for LB call state interface. Provides an interface for
+// LB policies to access internal call attributes.
+class ClientChannelLbCallState : public LoadBalancingPolicy::CallState {
+ public:
+ virtual y_absl::string_view GetCallAttribute(UniqueTypeName type) = 0;
+};
+
+// Internal type for ServiceConfigCallData. Provides access to the
+// CallDispatchController.
+class ClientChannelServiceConfigCallData : public ServiceConfigCallData {
+ public:
+ ClientChannelServiceConfigCallData(
+ RefCountedPtr<ServiceConfig> service_config,
+ const ServiceConfigParser::ParsedConfigVector* method_configs,
+ ServiceConfigCallData::CallAttributes call_attributes,
+ ConfigSelector::CallDispatchController* call_dispatch_controller,
+ grpc_call_context_element* call_context)
+ : ServiceConfigCallData(std::move(service_config), method_configs,
+ std::move(call_attributes)),
+ call_dispatch_controller_(call_dispatch_controller) {
+ call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = this;
+ call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].destroy = Destroy;
+ }
+
+ ConfigSelector::CallDispatchController* call_dispatch_controller() {
+ return &call_dispatch_controller_;
+ }
+
+ private:
+ // A wrapper for the CallDispatchController returned by the ConfigSelector.
+ // Handles the case where the ConfigSelector doees not return any
+ // CallDispatchController.
+ // Also ensures that we call Commit() at most once, which allows the
+ // client channel code to call Commit() when the call is complete in case
+ // it wasn't called earlier, without needing to know whether or not it was.
+ class CallDispatchControllerWrapper
+ : public ConfigSelector::CallDispatchController {
+ public:
+ explicit CallDispatchControllerWrapper(
+ ConfigSelector::CallDispatchController* call_dispatch_controller)
+ : call_dispatch_controller_(call_dispatch_controller) {}
+
+ bool ShouldRetry() override {
+ if (call_dispatch_controller_ != nullptr) {
+ return call_dispatch_controller_->ShouldRetry();
+ }
+ return true;
+ }
+
+ void Commit() override {
+ if (call_dispatch_controller_ != nullptr && !commit_called_) {
+ call_dispatch_controller_->Commit();
+ commit_called_ = true;
+ }
+ }
+
+ private:
+ ConfigSelector::CallDispatchController* call_dispatch_controller_;
+ bool commit_called_ = false;
+ };
+
+ static void Destroy(void* ptr) {
+ auto* self = static_cast<ClientChannelServiceConfigCallData*>(ptr);
+ self->~ClientChannelServiceConfigCallData();
+ }
+
+ CallDispatchControllerWrapper call_dispatch_controller_;
+};
+
+} // namespace grpc_core
+
+#endif // GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_INTERNAL_H
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/config_selector.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/config_selector.h
index 4c440ee8ba..f3d093a99c 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/config_selector.h
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/config_selector.h
@@ -28,7 +28,6 @@
#include "y_absl/strings/string_view.h"
#include <grpc/grpc.h>
-#include <grpc/slice.h>
#include <grpc/support/log.h>
#include "src/core/lib/channel/channel_fwd.h"
@@ -39,6 +38,7 @@
#include "src/core/lib/service_config/service_config.h"
#include "src/core/lib/service_config/service_config_call_data.h"
#include "src/core/lib/service_config/service_config_parser.h"
+#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/metadata_batch.h"
// Channel arg key for ConfigSelector.
@@ -65,7 +65,6 @@ class ConfigSelector : public RefCounted<ConfigSelector> {
};
struct GetCallConfigArgs {
- grpc_slice* path;
grpc_metadata_batch* initial_metadata;
Arena* arena;
};
@@ -132,8 +131,10 @@ class DefaultConfigSelector : public ConfigSelector {
y_absl::StatusOr<CallConfig> GetCallConfig(GetCallConfigArgs args) override {
CallConfig call_config;
+ Slice* path = args.initial_metadata->get_pointer(HttpPathMetadata());
+ GPR_ASSERT(path != nullptr);
call_config.method_configs =
- service_config_->GetMethodParsedConfigVector(*args.path);
+ service_config_->GetMethodParsedConfigVector(path->c_slice());
call_config.service_config = service_config_;
return call_config;
}
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_call_state_internal.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_call_state_internal.h
deleted file mode 100644
index b9539aa248..0000000000
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_call_state_internal.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright 2015 gRPC authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#ifndef GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_CALL_STATE_INTERNAL_H
-#define GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_CALL_STATE_INTERNAL_H
-
-#include <grpc/support/port_platform.h>
-
-#include "y_absl/strings/string_view.h"
-
-#include "src/core/lib/gprpp/unique_type_name.h"
-#include "src/core/lib/load_balancing/lb_policy.h"
-
-namespace grpc_core {
-
-//
-// LbCallStateInternal
-//
-class LbCallStateInternal : public LoadBalancingPolicy::CallState {
- public:
- virtual y_absl::string_view GetCallAttribute(UniqueTypeName type) = 0;
-};
-
-} // namespace grpc_core
-
-#endif // GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_CALL_STATE_INTERNAL_H
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/backend_metric_data.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/backend_metric_data.h
index e7c7429853..056b55721e 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/backend_metric_data.h
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/backend_metric_data.h
@@ -32,8 +32,10 @@ struct BackendMetricData {
/// Memory utilization expressed as a fraction of available memory
/// resources.
double mem_utilization = -1;
- /// Total QPS being served by the backend across all services.
+ /// Total queries per second being served by the backend across all services.
double qps = -1;
+ /// Total errors per second reported by the backend across all services.
+ double eps = -1;
/// Application-specific requests cost metrics. Metric names are
/// determined by the application. Each value is an absolute cost
/// (e.g. 3487 bytes of storage) associated with the request.
@@ -42,6 +44,9 @@ struct BackendMetricData {
/// are determined by the application. Each value is expressed as a
/// fraction of total resources available.
std::map<y_absl::string_view, double> utilization;
+ /// Application-specific opaque metrics. Metric names are determined by the
+ /// the application. Each value is an opaque measurement.
+ std::map<y_absl::string_view, double> named_metrics;
};
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
index 46a200c772..e28a3943a0 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
@@ -61,6 +61,7 @@
#include <string.h>
#include <algorithm>
+#include <atomic>
#include <initializer_list>
#include <map>
#include <memory>
@@ -390,19 +391,15 @@ class GrpcLb : public LoadBalancingPolicy {
// Returns the LB token to use for a drop, or null if the call
// should not be dropped.
//
- // Note: This is called from the picker, so it will be invoked in
- // the channel's data plane mutex, NOT the control plane
- // work_serializer. It should not be accessed by any other part of the LB
- // policy.
+ // Note: This is called from the picker, NOT from inside the control
+ // plane work_serializer.
const char* ShouldDrop();
private:
std::vector<GrpcLbServer> serverlist_;
- // Guarded by the channel's data plane mutex, NOT the control
- // plane work_serializer. It should not be accessed by anything but the
- // picker via the ShouldDrop() method.
- size_t drop_index_ = 0;
+ // Accessed from the picker, so needs synchronization.
+ std::atomic<size_t> drop_index_{0};
};
class Picker : public SubchannelPicker {
@@ -718,8 +715,8 @@ bool GrpcLb::Serverlist::ContainsAllDropEntries() const {
const char* GrpcLb::Serverlist::ShouldDrop() {
if (serverlist_.empty()) return nullptr;
- GrpcLbServer& server = serverlist_[drop_index_];
- drop_index_ = (drop_index_ + 1) % serverlist_.size();
+ size_t index = drop_index_.fetch_add(1, std::memory_order_relaxed);
+ GrpcLbServer& server = serverlist_[index % serverlist_.size()];
return server.drop ? server.load_balance_token : nullptr;
}
@@ -1166,13 +1163,15 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked() {
upb::Arena arena;
if (!GrpcLbResponseParse(response_slice, arena.ptr(), &response) ||
(response.type == response.INITIAL && seen_initial_response_)) {
- char* response_slice_str =
- grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX);
- gpr_log(GPR_ERROR,
- "[grpclb %p] lb_calld=%p: Invalid LB response received: '%s'. "
- "Ignoring.",
- grpclb_policy(), this, response_slice_str);
- gpr_free(response_slice_str);
+ if (gpr_should_log(GPR_LOG_SEVERITY_ERROR)) {
+ char* response_slice_str =
+ grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX);
+ gpr_log(GPR_ERROR,
+ "[grpclb %p] lb_calld=%p: Invalid LB response received: '%s'. "
+ "Ignoring.",
+ grpclb_policy(), this, response_slice_str);
+ gpr_free(response_slice_str);
+ }
} else {
switch (response.type) {
case response.INITIAL: {
@@ -1533,7 +1532,7 @@ void GrpcLb::ShutdownLocked() {
GPR_ASSERT(child_channelz_node != nullptr);
parent_channelz_node_->RemoveChildChannel(child_channelz_node->uuid());
}
- grpc_channel_destroy(lb_channel_);
+ grpc_channel_destroy_internal(lb_channel_);
lb_channel_ = nullptr;
}
}
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc
index d619b5d1cf..22eae0a8e7 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc
@@ -22,7 +22,6 @@
#include <stdlib.h>
#include <algorithm>
-#include <atomic>
#include <cmath>
#include <memory>
#include <util/generic/string.h>
@@ -31,7 +30,6 @@
#include <vector>
#include "y_absl/base/attributes.h"
-#include "y_absl/base/thread_annotations.h"
#include "y_absl/container/inlined_vector.h"
#include "y_absl/status/status.h"
#include "y_absl/status/statusor.h"
@@ -40,15 +38,14 @@
#include "y_absl/strings/string_view.h"
#include "y_absl/types/optional.h"
-#include <grpc/grpc.h>
-
#define XXH_INLINE_ALL
#include "xxhash.h"
+#include <grpc/grpc.h>
#include <grpc/impl/connectivity_state.h>
#include <grpc/support/log.h>
-#include "src/core/ext/filters/client_channel/client_channel.h"
+#include "src/core/ext/filters/client_channel/client_channel_internal.h"
#include "src/core/ext/filters/client_channel/lb_policy/subchannel_list.h"
#include "src/core/lib/address_utils/sockaddr_utils.h"
#include "src/core/lib/channel/channel_args.h"
@@ -56,8 +53,8 @@
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/orphanable.h"
+#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/gprpp/unique_type_name.h"
#include "src/core/lib/gprpp/work_serializer.h"
#include "src/core/lib/iomgr/closure.h"
@@ -144,8 +141,6 @@ class RingHash : public LoadBalancingPolicy {
void ResetBackoffLocked() override;
private:
- ~RingHash() override;
-
// Forward declaration.
class RingHashSubchannelList;
@@ -166,13 +161,11 @@ class RingHash : public LoadBalancingPolicy {
const ServerAddress& address() const { return address_; }
- grpc_connectivity_state GetConnectivityState() const {
- return connectivity_state_.load(std::memory_order_relaxed);
+ grpc_connectivity_state logical_connectivity_state() const {
+ return logical_connectivity_state_;
}
-
- y_absl::Status GetConnectivityStatus() const {
- MutexLock lock(&mu_);
- return connectivity_status_;
+ const y_absl::Status& logical_connectivity_status() const {
+ return logical_connectivity_status_;
}
private:
@@ -189,20 +182,28 @@ class RingHash : public LoadBalancingPolicy {
// subchannel in some cases; for example, once this is set to
// TRANSIENT_FAILURE, we do not change it again until we get READY,
// so we skip any interim stops in CONNECTING.
- // Uses an atomic so that it can be accessed outside of the WorkSerializer.
- std::atomic<grpc_connectivity_state> connectivity_state_{GRPC_CHANNEL_IDLE};
-
- mutable Mutex mu_;
- y_absl::Status connectivity_status_ Y_ABSL_GUARDED_BY(&mu_);
+ grpc_connectivity_state logical_connectivity_state_ = GRPC_CHANNEL_IDLE;
+ y_absl::Status logical_connectivity_status_;
};
// A list of subchannels and the ring containing those subchannels.
class RingHashSubchannelList
: public SubchannelList<RingHashSubchannelList, RingHashSubchannelData> {
public:
- struct RingEntry {
- uint64_t hash;
- RingHashSubchannelData* subchannel;
+ class Ring : public RefCounted<Ring> {
+ public:
+ struct RingEntry {
+ uint64_t hash;
+ size_t subchannel_index;
+ };
+
+ Ring(RingHashLbConfig* config, RingHashSubchannelList* subchannel_list,
+ const ChannelArgs& args);
+
+ const std::vector<RingEntry>& ring() const { return ring_; }
+
+ private:
+ std::vector<RingEntry> ring_;
};
RingHashSubchannelList(RingHash* policy, ServerAddressList addresses,
@@ -213,7 +214,7 @@ class RingHash : public LoadBalancingPolicy {
p->Unref(DEBUG_LOCATION, "subchannel_list");
}
- const std::vector<RingEntry>& ring() const { return ring_; }
+ RefCountedPtr<Ring> ring() { return ring_; }
// Updates the counters of subchannels in each state when a
// subchannel transitions from old_state to new_state.
@@ -237,7 +238,7 @@ class RingHash : public LoadBalancingPolicy {
size_t num_connecting_ = 0;
size_t num_transient_failure_ = 0;
- std::vector<RingEntry> ring_;
+ RefCountedPtr<Ring> ring_;
// The index of the subchannel currently doing an internally
// triggered connection attempt, if any.
@@ -252,24 +253,31 @@ class RingHash : public LoadBalancingPolicy {
class Picker : public SubchannelPicker {
public:
- explicit Picker(RefCountedPtr<RingHashSubchannelList> subchannel_list)
- : subchannel_list_(std::move(subchannel_list)) {}
-
- ~Picker() override {
- // Hop into WorkSerializer to unref the subchannel list, since that may
- // trigger the unreffing of the underlying subchannels.
- MakeOrphanable<WorkSerializerRunner>(std::move(subchannel_list_));
+ Picker(RefCountedPtr<RingHash> ring_hash_lb,
+ RingHashSubchannelList* subchannel_list)
+ : ring_hash_lb_(std::move(ring_hash_lb)),
+ ring_(subchannel_list->ring()) {
+ subchannels_.reserve(subchannel_list->num_subchannels());
+ for (size_t i = 0; i < subchannel_list->num_subchannels(); ++i) {
+ RingHashSubchannelData* subchannel_data =
+ subchannel_list->subchannel(i);
+ subchannels_.emplace_back(
+ SubchannelInfo{subchannel_data->subchannel()->Ref(),
+ subchannel_data->logical_connectivity_state(),
+ subchannel_data->logical_connectivity_status()});
+ }
}
PickResult Pick(PickArgs args) override;
private:
- // An interface for running a callback in the control plane WorkSerializer.
- class WorkSerializerRunner : public Orphanable {
+ // A fire-and-forget class that schedules subchannel connection attempts
+ // on the control plane WorkSerializer.
+ class SubchannelConnectionAttempter : public Orphanable {
public:
- explicit WorkSerializerRunner(
- RefCountedPtr<RingHashSubchannelList> subchannel_list)
- : subchannel_list_(std::move(subchannel_list)) {
+ explicit SubchannelConnectionAttempter(
+ RefCountedPtr<RingHash> ring_hash_lb)
+ : ring_hash_lb_(std::move(ring_hash_lb)) {
GRPC_CLOSURE_INIT(&closure_, RunInExecCtx, this, nullptr);
}
@@ -279,56 +287,43 @@ class RingHash : public LoadBalancingPolicy {
ExecCtx::Run(DEBUG_LOCATION, &closure_, y_absl::OkStatus());
}
- // Will be invoked inside of the WorkSerializer.
- virtual void Run() {}
-
- protected:
- RingHash* ring_hash_lb() const {
- return static_cast<RingHash*>(subchannel_list_->policy());
+ void AddSubchannel(RefCountedPtr<SubchannelInterface> subchannel) {
+ subchannels_.push_back(std::move(subchannel));
}
private:
static void RunInExecCtx(void* arg, grpc_error_handle /*error*/) {
- auto* self = static_cast<WorkSerializerRunner*>(arg);
- self->ring_hash_lb()->work_serializer()->Run(
+ auto* self = static_cast<SubchannelConnectionAttempter*>(arg);
+ self->ring_hash_lb_->work_serializer()->Run(
[self]() {
- self->Run();
+ if (!self->ring_hash_lb_->shutdown_) {
+ for (auto& subchannel : self->subchannels_) {
+ subchannel->RequestConnection();
+ }
+ }
delete self;
},
DEBUG_LOCATION);
}
- RefCountedPtr<RingHashSubchannelList> subchannel_list_;
+ RefCountedPtr<RingHash> ring_hash_lb_;
grpc_closure closure_;
+ std::vector<RefCountedPtr<SubchannelInterface>> subchannels_;
};
- // A fire-and-forget class that schedules subchannel connection attempts
- // on the control plane WorkSerializer.
- class SubchannelConnectionAttempter : public WorkSerializerRunner {
- public:
- explicit SubchannelConnectionAttempter(
- RefCountedPtr<RingHashSubchannelList> subchannel_list)
- : WorkSerializerRunner(std::move(subchannel_list)) {}
-
- void AddSubchannel(RefCountedPtr<SubchannelInterface> subchannel) {
- subchannels_.push_back(std::move(subchannel));
- }
-
- void Run() override {
- if (!ring_hash_lb()->shutdown_) {
- for (auto& subchannel : subchannels_) {
- subchannel->RequestConnection();
- }
- }
- }
-
- private:
- std::vector<RefCountedPtr<SubchannelInterface>> subchannels_;
+ struct SubchannelInfo {
+ RefCountedPtr<SubchannelInterface> subchannel;
+ grpc_connectivity_state state;
+ y_absl::Status status;
};
- RefCountedPtr<RingHashSubchannelList> subchannel_list_;
+ RefCountedPtr<RingHash> ring_hash_lb_;
+ RefCountedPtr<RingHashSubchannelList::Ring> ring_;
+ std::vector<SubchannelInfo> subchannels_;
};
+ ~RingHash() override;
+
void ShutdownLocked() override;
// Current config from resolver.
@@ -346,15 +341,14 @@ class RingHash : public LoadBalancingPolicy {
//
RingHash::PickResult RingHash::Picker::Pick(PickArgs args) {
- auto* call_state = static_cast<ClientChannel::LoadBalancedCall::LbCallState*>(
- args.call_state);
+ auto* call_state = static_cast<ClientChannelLbCallState*>(args.call_state);
auto hash = call_state->GetCallAttribute(RequestHashAttributeName());
uint64_t h;
if (!y_absl::SimpleAtoi(hash, &h)) {
return PickResult::Fail(
y_absl::InternalError("ring hash value is not a number"));
}
- const auto& ring = subchannel_list_->ring();
+ const auto& ring = ring_->ring();
// Ported from https://github.com/RJ/ketama/blob/master/libketama/ketama.c
// (ketama_get_server) NOTE: The algorithm depends on using signed integers
// for lowp, highp, and first_index. Do not change them!
@@ -387,27 +381,25 @@ RingHash::PickResult RingHash::Picker::Pick(PickArgs args) {
[&](RefCountedPtr<SubchannelInterface> subchannel) {
if (subchannel_connection_attempter == nullptr) {
subchannel_connection_attempter =
- MakeOrphanable<SubchannelConnectionAttempter>(
- subchannel_list_->Ref(DEBUG_LOCATION,
- "SubchannelConnectionAttempter"));
+ MakeOrphanable<SubchannelConnectionAttempter>(ring_hash_lb_->Ref(
+ DEBUG_LOCATION, "SubchannelConnectionAttempter"));
}
subchannel_connection_attempter->AddSubchannel(std::move(subchannel));
};
- switch (ring[first_index].subchannel->GetConnectivityState()) {
+ SubchannelInfo& first_subchannel =
+ subchannels_[ring[first_index].subchannel_index];
+ switch (first_subchannel.state) {
case GRPC_CHANNEL_READY:
- return PickResult::Complete(
- ring[first_index].subchannel->subchannel()->Ref());
+ return PickResult::Complete(first_subchannel.subchannel);
case GRPC_CHANNEL_IDLE:
- ScheduleSubchannelConnectionAttempt(
- ring[first_index].subchannel->subchannel()->Ref());
+ ScheduleSubchannelConnectionAttempt(first_subchannel.subchannel);
Y_ABSL_FALLTHROUGH_INTENDED;
case GRPC_CHANNEL_CONNECTING:
return PickResult::Queue();
default: // GRPC_CHANNEL_TRANSIENT_FAILURE
break;
}
- ScheduleSubchannelConnectionAttempt(
- ring[first_index].subchannel->subchannel()->Ref());
+ ScheduleSubchannelConnectionAttempt(first_subchannel.subchannel);
// Loop through remaining subchannels to find one in READY.
// On the way, we make sure the right set of connection attempts
// will happen.
@@ -415,19 +407,17 @@ RingHash::PickResult RingHash::Picker::Pick(PickArgs args) {
bool found_first_non_failed = false;
for (size_t i = 1; i < ring.size(); ++i) {
const auto& entry = ring[(first_index + i) % ring.size()];
- if (entry.subchannel == ring[first_index].subchannel) {
+ if (entry.subchannel_index == ring[first_index].subchannel_index) {
continue;
}
- grpc_connectivity_state connectivity_state =
- entry.subchannel->GetConnectivityState();
- if (connectivity_state == GRPC_CHANNEL_READY) {
- return PickResult::Complete(entry.subchannel->subchannel()->Ref());
+ SubchannelInfo& subchannel_info = subchannels_[entry.subchannel_index];
+ if (subchannel_info.state == GRPC_CHANNEL_READY) {
+ return PickResult::Complete(subchannel_info.subchannel);
}
if (!found_second_subchannel) {
- switch (connectivity_state) {
+ switch (subchannel_info.state) {
case GRPC_CHANNEL_IDLE:
- ScheduleSubchannelConnectionAttempt(
- entry.subchannel->subchannel()->Ref());
+ ScheduleSubchannelConnectionAttempt(subchannel_info.subchannel);
Y_ABSL_FALLTHROUGH_INTENDED;
case GRPC_CHANNEL_CONNECTING:
return PickResult::Queue();
@@ -437,13 +427,11 @@ RingHash::PickResult RingHash::Picker::Pick(PickArgs args) {
found_second_subchannel = true;
}
if (!found_first_non_failed) {
- if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
- ScheduleSubchannelConnectionAttempt(
- entry.subchannel->subchannel()->Ref());
+ if (subchannel_info.state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+ ScheduleSubchannelConnectionAttempt(subchannel_info.subchannel);
} else {
- if (connectivity_state == GRPC_CHANNEL_IDLE) {
- ScheduleSubchannelConnectionAttempt(
- entry.subchannel->subchannel()->Ref());
+ if (subchannel_info.state == GRPC_CHANNEL_IDLE) {
+ ScheduleSubchannelConnectionAttempt(subchannel_info.subchannel);
}
found_first_non_failed = true;
}
@@ -451,27 +439,16 @@ RingHash::PickResult RingHash::Picker::Pick(PickArgs args) {
}
return PickResult::Fail(y_absl::UnavailableError(y_absl::StrCat(
"ring hash cannot find a connected subchannel; first failure: ",
- ring[first_index].subchannel->GetConnectivityStatus().ToString())));
+ first_subchannel.status.ToString())));
}
//
-// RingHash::RingHashSubchannelList
+// RingHash::RingHashSubchannelList::Ring
//
-RingHash::RingHashSubchannelList::RingHashSubchannelList(
- RingHash* policy, ServerAddressList addresses, const ChannelArgs& args)
- : SubchannelList(policy,
- (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)
- ? "RingHashSubchannelList"
- : nullptr),
- std::move(addresses), policy->channel_control_helper(),
- args),
- num_idle_(num_subchannels()) {
- // Need to maintain a ref to the LB policy as long as we maintain
- // any references to subchannels, since the subchannels'
- // pollset_sets will include the LB policy's pollset_set.
- policy->Ref(DEBUG_LOCATION, "subchannel_list").release();
- // Construct the ring.
+RingHash::RingHashSubchannelList::Ring::Ring(
+ RingHashLbConfig* config, RingHashSubchannelList* subchannel_list,
+ const ChannelArgs& args) {
// Store the weights while finding the sum.
struct AddressWeight {
TString address;
@@ -482,9 +459,9 @@ RingHash::RingHashSubchannelList::RingHashSubchannelList(
};
std::vector<AddressWeight> address_weights;
size_t sum = 0;
- address_weights.reserve(num_subchannels());
- for (size_t i = 0; i < num_subchannels(); ++i) {
- RingHashSubchannelData* sd = subchannel(i);
+ address_weights.reserve(subchannel_list->num_subchannels());
+ for (size_t i = 0; i < subchannel_list->num_subchannels(); ++i) {
+ RingHashSubchannelData* sd = subchannel_list->subchannel(i);
const ServerAddressWeightAttribute* weight_attribute = static_cast<
const ServerAddressWeightAttribute*>(sd->address().GetAttribute(
ServerAddressWeightAttribute::kServerAddressWeightAttributeKey));
@@ -518,10 +495,8 @@ RingHash::RingHashSubchannelList::RingHashSubchannelList(
// to fit.
const size_t ring_size_cap = args.GetInt(GRPC_ARG_RING_HASH_LB_RING_SIZE_CAP)
.value_or(kRingSizeCapDefault);
- const size_t min_ring_size =
- std::min(policy->config_->min_ring_size(), ring_size_cap);
- const size_t max_ring_size =
- std::min(policy->config_->max_ring_size(), ring_size_cap);
+ const size_t min_ring_size = std::min(config->min_ring_size(), ring_size_cap);
+ const size_t max_ring_size = std::min(config->max_ring_size(), ring_size_cap);
const double scale = std::min(
std::ceil(min_normalized_weight * min_ring_size) / min_normalized_weight,
static_cast<double>(max_ring_size));
@@ -538,7 +513,7 @@ RingHash::RingHashSubchannelList::RingHashSubchannelList(
double target_hashes = 0.0;
uint64_t min_hashes_per_host = ring_size;
uint64_t max_hashes_per_host = 0;
- for (size_t i = 0; i < num_subchannels(); ++i) {
+ for (size_t i = 0; i < subchannel_list->num_subchannels(); ++i) {
const TString& address_string = address_weights[i].address;
hash_key_buffer.assign(address_string.begin(), address_string.end());
hash_key_buffer.emplace_back('_');
@@ -551,7 +526,7 @@ RingHash::RingHashSubchannelList::RingHashSubchannelList(
y_absl::string_view hash_key(hash_key_buffer.data(),
hash_key_buffer.size());
const uint64_t hash = XXH64(hash_key.data(), hash_key.size(), 0);
- ring_.push_back({hash, subchannel(i)});
+ ring_.push_back({hash, i});
++count;
++current_hashes;
hash_key_buffer.erase(offset_start, hash_key_buffer.end());
@@ -562,14 +537,34 @@ RingHash::RingHashSubchannelList::RingHashSubchannelList(
std::max(static_cast<uint64_t>(i), max_hashes_per_host);
}
std::sort(ring_.begin(), ring_.end(),
- [](const RingHashSubchannelList::RingEntry& lhs,
- const RingHashSubchannelList::RingEntry& rhs) -> bool {
+ [](const RingEntry& lhs, const RingEntry& rhs) -> bool {
return lhs.hash < rhs.hash;
});
+}
+
+//
+// RingHash::RingHashSubchannelList
+//
+
+RingHash::RingHashSubchannelList::RingHashSubchannelList(
+ RingHash* policy, ServerAddressList addresses, const ChannelArgs& args)
+ : SubchannelList(policy,
+ (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)
+ ? "RingHashSubchannelList"
+ : nullptr),
+ std::move(addresses), policy->channel_control_helper(),
+ args),
+ num_idle_(num_subchannels()) {
+ // Need to maintain a ref to the LB policy as long as we maintain
+ // any references to subchannels, since the subchannels'
+ // pollset_sets will include the LB policy's pollset_set.
+ policy->Ref(DEBUG_LOCATION, "subchannel_list").release();
+ // Construct the ring.
+ ring_ = MakeRefCounted<Ring>(policy->config_.get(), this, args);
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
gpr_log(GPR_INFO,
"[RH %p] created subchannel list %p with %" PRIuPTR " ring entries",
- policy, this, ring_.size());
+ policy, this, ring_->ring().size());
}
}
@@ -661,7 +656,7 @@ void RingHash::RingHashSubchannelList::UpdateRingHashConnectivityStateLocked(
// Note that we use our own picker regardless of connectivity state.
p->channel_control_helper()->UpdateState(
state, status,
- MakeRefCounted<Picker>(Ref(DEBUG_LOCATION, "RingHashPicker")));
+ MakeRefCounted<Picker>(p->Ref(DEBUG_LOCATION, "RingHashPicker"), this));
// While the ring_hash policy is reporting TRANSIENT_FAILURE, it will
// not be getting any pick requests from the priority policy.
// However, because the ring_hash policy does not attempt to
@@ -708,7 +703,6 @@ void RingHash::RingHashSubchannelData::ProcessConnectivityChangeLocked(
y_absl::optional<grpc_connectivity_state> old_state,
grpc_connectivity_state new_state) {
RingHash* p = static_cast<RingHash*>(subchannel_list()->policy());
- grpc_connectivity_state last_connectivity_state = GetConnectivityState();
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) {
gpr_log(
GPR_INFO,
@@ -716,7 +710,7 @@ void RingHash::RingHashSubchannelData::ProcessConnectivityChangeLocked(
"(index %" PRIuPTR " of %" PRIuPTR "): prev_state=%s new_state=%s",
p, subchannel(), subchannel_list(), Index(),
subchannel_list()->num_subchannels(),
- ConnectivityStateName(last_connectivity_state),
+ ConnectivityStateName(logical_connectivity_state_),
ConnectivityStateName(new_state));
}
GPR_ASSERT(subchannel() != nullptr);
@@ -736,34 +730,23 @@ void RingHash::RingHashSubchannelData::ProcessConnectivityChangeLocked(
const bool connection_attempt_complete = new_state != GRPC_CHANNEL_CONNECTING;
// Decide what state to report for the purposes of aggregation and
// picker behavior.
- // If the last recorded state was TRANSIENT_FAILURE, ignore the update
- // unless the new state is READY.
- bool update_status = true;
- y_absl::Status status = connectivity_status();
- if (last_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE &&
- new_state != GRPC_CHANNEL_READY &&
- new_state != GRPC_CHANNEL_TRANSIENT_FAILURE) {
- new_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
- {
- MutexLock lock(&mu_);
- status = connectivity_status_;
- }
- update_status = false;
- }
- // Update state counters used for aggregation.
- subchannel_list()->UpdateStateCountersLocked(last_connectivity_state,
- new_state);
- // Update status seen by picker if needed.
- if (update_status) {
- MutexLock lock(&mu_);
- connectivity_status_ = connectivity_status();
+ // If the last recorded state was TRANSIENT_FAILURE, ignore the change
+ // unless the new state is READY (or TF again, in which case we need
+ // to update the status).
+ if (logical_connectivity_state_ != GRPC_CHANNEL_TRANSIENT_FAILURE ||
+ new_state == GRPC_CHANNEL_READY ||
+ new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+ // Update state counters used for aggregation.
+ subchannel_list()->UpdateStateCountersLocked(logical_connectivity_state_,
+ new_state);
+ // Update logical state.
+ logical_connectivity_state_ = new_state;
+ logical_connectivity_status_ = connectivity_status();
}
- // Update last seen state, also used by picker.
- connectivity_state_.store(new_state, std::memory_order_relaxed);
// Update the RH policy's connectivity state, creating new picker and new
// ring.
subchannel_list()->UpdateRingHashConnectivityStateLocked(
- Index(), connection_attempt_complete, status);
+ Index(), connection_attempt_complete, logical_connectivity_status_);
}
//
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc
index e5ed7c5507..c65a215fa5 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc
@@ -366,7 +366,6 @@ class RlsLb : public LoadBalancingPolicy {
class Picker : public LoadBalancingPolicy::SubchannelPicker {
public:
explicit Picker(RefCountedPtr<RlsLb> lb_policy);
- ~Picker() override;
PickResult Pick(PickArgs args) override;
@@ -1009,19 +1008,6 @@ RlsLb::Picker::Picker(RefCountedPtr<RlsLb> lb_policy)
}
}
-RlsLb::Picker::~Picker() {
- // It's not safe to unref the default child policy in the picker,
- // since that needs to be done in the WorkSerializer.
- if (default_child_policy_ != nullptr) {
- auto* default_child_policy = default_child_policy_.release();
- lb_policy_->work_serializer()->Run(
- [default_child_policy]() {
- default_child_policy->Unref(DEBUG_LOCATION, "Picker");
- },
- DEBUG_LOCATION);
- }
-}
-
LoadBalancingPolicy::PickResult RlsLb::Picker::Pick(PickArgs args) {
// Construct key for request.
RequestKey key = {BuildKeyMap(config_->key_builder_map(), args.path,
@@ -1646,7 +1632,7 @@ void RlsLb::RlsChannel::Orphan() {
client_channel->RemoveConnectivityWatcher(watcher_);
watcher_ = nullptr;
}
- grpc_channel_destroy(channel_);
+ grpc_channel_destroy_internal(channel_);
}
Unref(DEBUG_LOCATION, "Orphan");
}
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
index b7fe7e793d..bae6478a2e 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
@@ -18,14 +18,17 @@
#include <inttypes.h>
#include <stdlib.h>
+#include <string.h>
#include <algorithm>
+#include <atomic>
#include <memory>
#include <util/generic/string.h>
#include <util/string/cast.h>
#include <utility>
#include <vector>
+#include "y_absl/random/random.h"
#include "y_absl/status/status.h"
#include "y_absl/status/statusor.h"
#include "y_absl/strings/str_cat.h"
@@ -175,7 +178,7 @@ class RoundRobin : public LoadBalancingPolicy {
// Using pointer value only, no ref held -- do not dereference!
RoundRobin* parent_;
- size_t last_picked_index_;
+ std::atomic<size_t> last_picked_index_;
std::vector<RefCountedPtr<SubchannelInterface>> subchannels_;
};
@@ -190,6 +193,8 @@ class RoundRobin : public LoadBalancingPolicy {
RefCountedPtr<RoundRobinSubchannelList> latest_pending_subchannel_list_;
bool shutdown_ = false;
+
+ y_absl::BitGen bit_gen_;
};
//
@@ -208,27 +213,26 @@ RoundRobin::Picker::Picker(RoundRobin* parent,
}
// For discussion on why we generate a random starting index for
// the picker, see https://github.com/grpc/grpc-go/issues/2580.
- // TODO(roth): rand(3) is not thread-safe. This should be replaced with
- // something better as part of https://github.com/grpc/grpc/issues/17891.
- last_picked_index_ = rand() % subchannels_.size();
+ size_t index =
+ y_absl::Uniform<size_t>(parent->bit_gen_, 0, subchannels_.size());
+ last_picked_index_.store(index, std::memory_order_relaxed);
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) {
gpr_log(GPR_INFO,
"[RR %p picker %p] created picker from subchannel_list=%p "
"with %" PRIuPTR " READY subchannels; last_picked_index_=%" PRIuPTR,
- parent_, this, subchannel_list, subchannels_.size(),
- last_picked_index_);
+ parent_, this, subchannel_list, subchannels_.size(), index);
}
}
RoundRobin::PickResult RoundRobin::Picker::Pick(PickArgs /*args*/) {
- last_picked_index_ = (last_picked_index_ + 1) % subchannels_.size();
+ size_t index = last_picked_index_.fetch_add(1, std::memory_order_relaxed) %
+ subchannels_.size();
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) {
gpr_log(GPR_INFO,
"[RR %p picker %p] returning index %" PRIuPTR ", subchannel=%p",
- parent_, this, last_picked_index_,
- subchannels_[last_picked_index_].get());
+ parent_, this, index, subchannels_[index].get());
}
- return PickResult::Complete(subchannels_[last_picked_index_]);
+ return PickResult::Complete(subchannels_[index]);
}
//
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_round_robin/weighted_round_robin.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_round_robin/weighted_round_robin.cc
index b91d333d15..9096768478 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_round_robin/weighted_round_robin.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_round_robin/weighted_round_robin.cc
@@ -100,6 +100,7 @@ class WeightedRoundRobinConfig : public LoadBalancingPolicy::Config {
Duration weight_expiration_period() const {
return weight_expiration_period_;
}
+ float error_utilization_penalty() const { return error_utilization_penalty_; }
static const JsonLoaderInterface* JsonLoader(const JsonArgs&) {
static const auto* loader =
@@ -114,14 +115,21 @@ class WeightedRoundRobinConfig : public LoadBalancingPolicy::Config {
&WeightedRoundRobinConfig::weight_update_period_)
.OptionalField("weightExpirationPeriod",
&WeightedRoundRobinConfig::weight_expiration_period_)
+ .OptionalField(
+ "errorUtilizationPenalty",
+ &WeightedRoundRobinConfig::error_utilization_penalty_)
.Finish();
return loader;
}
- void JsonPostLoad(const Json&, const JsonArgs&, ValidationErrors*) {
+ void JsonPostLoad(const Json&, const JsonArgs&, ValidationErrors* errors) {
// Impose lower bound of 100ms on weightUpdatePeriod.
weight_update_period_ =
std::max(weight_update_period_, Duration::Milliseconds(100));
+ if (error_utilization_penalty_ < 0) {
+ ValidationErrors::ScopedField field(errors, ".errorUtilizationPenalty");
+ errors->AddError("must be non-negative");
+ }
}
private:
@@ -130,6 +138,7 @@ class WeightedRoundRobinConfig : public LoadBalancingPolicy::Config {
Duration blackout_period_ = Duration::Seconds(10);
Duration weight_update_period_ = Duration::Seconds(1);
Duration weight_expiration_period_ = Duration::Minutes(3);
+ float error_utilization_penalty_ = 1.0;
};
// WRR LB policy.
@@ -150,7 +159,8 @@ class WeightedRoundRobin : public LoadBalancingPolicy {
: wrr_(std::move(wrr)), key_(std::move(key)) {}
~AddressWeight() override;
- void MaybeUpdateWeight(double qps, double cpu_utilization);
+ void MaybeUpdateWeight(double qps, double eps, double cpu_utilization,
+ float error_utilization_penalty);
float GetWeight(Timestamp now, Duration weight_expiration_period,
Duration blackout_period);
@@ -192,14 +202,17 @@ class WeightedRoundRobin : public LoadBalancingPolicy {
private:
class OobWatcher : public OobBackendMetricWatcher {
public:
- explicit OobWatcher(RefCountedPtr<AddressWeight> weight)
- : weight_(std::move(weight)) {}
+ OobWatcher(RefCountedPtr<AddressWeight> weight,
+ float error_utilization_penalty)
+ : weight_(std::move(weight)),
+ error_utilization_penalty_(error_utilization_penalty) {}
void OnBackendMetricReport(
const BackendMetricData& backend_metric_data) override;
private:
RefCountedPtr<AddressWeight> weight_;
+ const float error_utilization_penalty_;
};
// Performs connectivity state updates that need to be done only
@@ -291,8 +304,10 @@ class WeightedRoundRobin : public LoadBalancingPolicy {
// A call tracker that collects per-call endpoint utilization reports.
class SubchannelCallTracker : public SubchannelCallTrackerInterface {
public:
- explicit SubchannelCallTracker(RefCountedPtr<AddressWeight> weight)
- : weight_(std::move(weight)) {}
+ SubchannelCallTracker(RefCountedPtr<AddressWeight> weight,
+ float error_utilization_penalty)
+ : weight_(std::move(weight)),
+ error_utilization_penalty_(error_utilization_penalty) {}
void Start() override {}
@@ -300,6 +315,7 @@ class WeightedRoundRobin : public LoadBalancingPolicy {
private:
RefCountedPtr<AddressWeight> weight_;
+ const float error_utilization_penalty_;
};
// Info stored about each subchannel.
@@ -325,6 +341,7 @@ class WeightedRoundRobin : public LoadBalancingPolicy {
const Duration weight_update_period_;
const Duration weight_expiration_period_;
const Duration blackout_period_;
+ const float error_utilization_penalty_;
std::vector<SubchannelInfo> subchannels_;
Mutex scheduler_mu_;
@@ -382,16 +399,24 @@ WeightedRoundRobin::AddressWeight::~AddressWeight() {
}
void WeightedRoundRobin::AddressWeight::MaybeUpdateWeight(
- double qps, double cpu_utilization) {
+ double qps, double eps, double cpu_utilization,
+ float error_utilization_penalty) {
// Compute weight.
float weight = 0;
- if (qps > 0 && cpu_utilization > 0) weight = qps / cpu_utilization;
+ if (qps > 0 && cpu_utilization > 0) {
+ double penalty = 0.0;
+ if (eps > 0 && error_utilization_penalty > 0) {
+ penalty = eps / qps * error_utilization_penalty;
+ }
+ weight = qps / (cpu_utilization + penalty);
+ }
if (weight == 0) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) {
gpr_log(GPR_INFO,
- "[WRR %p] subchannel %s: qps=%f, cpu_utilization=%f: weight=%f "
- "(not updating)",
- wrr_.get(), key_.c_str(), qps, cpu_utilization, weight);
+ "[WRR %p] subchannel %s: qps=%f, eps=%f, cpu_utilization=%f: "
+ "error_util_penalty=%f, weight=%f (not updating)",
+ wrr_.get(), key_.c_str(), qps, eps, cpu_utilization,
+ error_utilization_penalty, weight);
}
return;
}
@@ -400,11 +425,12 @@ void WeightedRoundRobin::AddressWeight::MaybeUpdateWeight(
MutexLock lock(&mu_);
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) {
gpr_log(GPR_INFO,
- "[WRR %p] subchannel %s: qps=%f, cpu_utilization=%f: setting "
- "weight=%f weight_=%f now=%s last_update_time_=%s "
- "non_empty_since_=%s",
- wrr_.get(), key_.c_str(), qps, cpu_utilization, weight, weight_,
- now.ToString().c_str(), last_update_time_.ToString().c_str(),
+ "[WRR %p] subchannel %s: qps=%f, eps=%f, cpu_utilization=%f "
+ "error_util_penalty=%f : setting weight=%f weight_=%f now=%s "
+ "last_update_time_=%s non_empty_since_=%s",
+ wrr_.get(), key_.c_str(), qps, eps, cpu_utilization,
+ error_utilization_penalty, weight, weight_, now.ToString().c_str(),
+ last_update_time_.ToString().c_str(),
non_empty_since_.ToString().c_str());
}
if (non_empty_since_ == Timestamp::InfFuture()) non_empty_since_ = now;
@@ -457,12 +483,15 @@ void WeightedRoundRobin::Picker::SubchannelCallTracker::Finish(
auto* backend_metric_data =
args.backend_metric_accessor->GetBackendMetricData();
double qps = 0;
+ double eps = 0;
double cpu_utilization = 0;
if (backend_metric_data != nullptr) {
qps = backend_metric_data->qps;
+ eps = backend_metric_data->eps;
cpu_utilization = backend_metric_data->cpu_utilization;
}
- weight_->MaybeUpdateWeight(qps, cpu_utilization);
+ weight_->MaybeUpdateWeight(qps, eps, cpu_utilization,
+ error_utilization_penalty_);
}
//
@@ -477,6 +506,7 @@ WeightedRoundRobin::Picker::Picker(
weight_update_period_(wrr_->config_->weight_update_period()),
weight_expiration_period_(wrr_->config_->weight_expiration_period()),
blackout_period_(wrr_->config_->blackout_period()),
+ error_utilization_penalty_(wrr_->config_->error_utilization_penalty()),
last_picked_index_(y_absl::Uniform<size_t>(wrr_->bit_gen_)) {
for (size_t i = 0; i < subchannel_list->num_subchannels(); ++i) {
WeightedRoundRobinSubchannelData* sd = subchannel_list->subchannel(i);
@@ -516,8 +546,8 @@ WeightedRoundRobin::PickResult WeightedRoundRobin::Picker::Pick(
// Collect per-call utilization data if needed.
std::unique_ptr<SubchannelCallTrackerInterface> subchannel_call_tracker;
if (use_per_rpc_utilization_) {
- subchannel_call_tracker =
- std::make_unique<SubchannelCallTracker>(subchannel_info.weight);
+ subchannel_call_tracker = std::make_unique<SubchannelCallTracker>(
+ subchannel_info.weight, error_utilization_penalty_);
}
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) {
gpr_log(GPR_INFO,
@@ -561,6 +591,13 @@ void WeightedRoundRobin::Picker::BuildSchedulerAndStartTimerLocked() {
if (scheduler_or.has_value()) {
scheduler =
std::make_shared<StaticStrideScheduler>(std::move(*scheduler_or));
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) {
+ gpr_log(GPR_INFO, "[WRR %p picker %p] new scheduler: %p", wrr_.get(),
+ this, scheduler.get());
+ }
+ } else if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_wrr_trace)) {
+ gpr_log(GPR_INFO, "[WRR %p picker %p] no scheduler, falling back to RR",
+ wrr_.get(), this);
}
{
MutexLock lock(&scheduler_mu_);
@@ -818,8 +855,9 @@ void WeightedRoundRobin::WeightedRoundRobinSubchannelList::
void WeightedRoundRobin::WeightedRoundRobinSubchannelData::OobWatcher::
OnBackendMetricReport(const BackendMetricData& backend_metric_data) {
- weight_->MaybeUpdateWeight(backend_metric_data.qps,
- backend_metric_data.cpu_utilization);
+ weight_->MaybeUpdateWeight(backend_metric_data.qps, backend_metric_data.eps,
+ backend_metric_data.cpu_utilization,
+ error_utilization_penalty_);
}
//
@@ -838,9 +876,10 @@ WeightedRoundRobin::WeightedRoundRobinSubchannelData::
WeightedRoundRobin* p =
static_cast<WeightedRoundRobin*>(subchannel_list->policy());
if (p->config_->enable_oob_load_report()) {
- subchannel()->AddDataWatcher(
- MakeOobBackendMetricWatcher(p->config_->oob_reporting_period(),
- std::make_unique<OobWatcher>(weight_)));
+ subchannel()->AddDataWatcher(MakeOobBackendMetricWatcher(
+ p->config_->oob_reporting_period(),
+ std::make_unique<OobWatcher>(weight_,
+ p->config_->error_utilization_penalty())));
}
}
@@ -951,15 +990,14 @@ class WeightedRoundRobinFactory : public LoadBalancingPolicyFactory {
y_absl::StatusOr<RefCountedPtr<LoadBalancingPolicy::Config>>
ParseLoadBalancingConfig(const Json& json) const override {
if (json.type() == Json::Type::JSON_NULL) {
- // priority was mentioned as a policy in the deprecated
- // loadBalancingPolicy field or in the client API.
return y_absl::InvalidArgumentError(
- "field:loadBalancingPolicy error:priority policy requires "
- "configuration. Please use loadBalancingConfig field of service "
- "config instead.");
+ "field:loadBalancingPolicy error:weighted_round_robin policy "
+ "requires configuration. Please use loadBalancingConfig field of "
+ "service config instead.");
}
return LoadRefCountedFromJson<WeightedRoundRobinConfig>(
- json, JsonArgs(), "errors validating priority LB policy config");
+ json, JsonArgs(),
+ "errors validating weighted_round_robin LB policy config");
}
};
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
index 0ca4a7307b..a6ef311b93 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
@@ -27,6 +27,7 @@
#include <utility>
#include <vector>
+#include "y_absl/base/thread_annotations.h"
#include "y_absl/random/random.h"
#include "y_absl/status/status.h"
#include "y_absl/status/statusor.h"
@@ -47,6 +48,7 @@
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/gprpp/validation_errors.h"
#include "src/core/lib/gprpp/work_serializer.h"
@@ -139,7 +141,11 @@ class WeightedTargetLb : public LoadBalancingPolicy {
private:
PickerList pickers_;
- y_absl::BitGen bit_gen_;
+
+ // TODO(roth): Consider using a separate thread-local BitGen for each CPU
+ // to avoid the need for this mutex.
+ Mutex mu_;
+ y_absl::BitGen bit_gen_ Y_ABSL_GUARDED_BY(&mu_);
};
// Each WeightedChild holds a ref to its parent WeightedTargetLb.
@@ -248,8 +254,10 @@ class WeightedTargetLb : public LoadBalancingPolicy {
WeightedTargetLb::PickResult WeightedTargetLb::WeightedPicker::Pick(
PickArgs args) {
// Generate a random number in [0, total weight).
- const uint64_t key =
- y_absl::Uniform<uint64_t>(bit_gen_, 0, pickers_.back().first);
+ const uint64_t key = [&]() {
+ MutexLock lock(&mu_);
+ return y_absl::Uniform<uint64_t>(bit_gen_, 0, pickers_.back().first);
+ }();
// Find the index in pickers_ corresponding to key.
size_t mid = 0;
size_t start_index = 0;
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc
index a956460356..0bf74a5069 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc
@@ -39,6 +39,7 @@
#include <grpc/impl/connectivity_state.h>
#include <grpc/support/log.h>
+#include "src/core/ext/filters/client_channel/lb_policy/backend_metric_data.h"
#include "src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h"
#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_attributes.h"
#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h"
@@ -333,7 +334,13 @@ class XdsClusterImplLb::Picker::SubchannelCallTracker
}
// Record call completion for load reporting.
if (locality_stats_ != nullptr) {
- locality_stats_->AddCallFinished(!args.status.ok());
+ auto* backend_metric_data =
+ args.backend_metric_accessor->GetBackendMetricData();
+ const std::map<y_absl::string_view, double>* named_metrics = nullptr;
+ if (backend_metric_data != nullptr) {
+ named_metrics = &backend_metric_data->named_metrics;
+ }
+ locality_stats_->AddCallFinished(named_metrics, !args.status.ok());
}
// Decrement number of calls in flight.
call_counter_->Decrement();
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc
index 78a28d4fd5..7df2ba57ce 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc
@@ -38,7 +38,7 @@
#include <grpc/impl/connectivity_state.h>
#include <grpc/support/log.h>
-#include "src/core/ext/filters/client_channel/client_channel.h"
+#include "src/core/ext/filters/client_channel/client_channel_internal.h"
#include "src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h"
#include "src/core/ext/filters/client_channel/resolver/xds/xds_resolver.h"
#include "src/core/lib/channel/channel_args.h"
@@ -230,8 +230,7 @@ class XdsClusterManagerLb : public LoadBalancingPolicy {
XdsClusterManagerLb::PickResult XdsClusterManagerLb::ClusterPicker::Pick(
PickArgs args) {
- auto* call_state = static_cast<ClientChannel::LoadBalancedCall::LbCallState*>(
- args.call_state);
+ auto* call_state = static_cast<ClientChannelLbCallState*>(args.call_state);
auto cluster_name =
call_state->GetCallAttribute(XdsClusterAttributeTypeName());
auto it = cluster_map_.find(TString(cluster_name));
@@ -329,7 +328,6 @@ void XdsClusterManagerLb::UpdateStateLocked() {
size_t num_ready = 0;
size_t num_connecting = 0;
size_t num_idle = 0;
- size_t num_transient_failures = 0;
for (const auto& p : children_) {
const auto& child_name = p.first;
const ClusterChild* child = p.second.get();
@@ -352,7 +350,6 @@ void XdsClusterManagerLb::UpdateStateLocked() {
break;
}
case GRPC_CHANNEL_TRANSIENT_FAILURE: {
- ++num_transient_failures;
break;
}
default:
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.cc
index f9d07ccdeb..8b6367e637 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_override_host.cc
@@ -44,7 +44,7 @@
#include <grpc/impl/connectivity_state.h>
#include <grpc/support/log.h>
-#include "src/core/ext/filters/client_channel/lb_call_state_internal.h"
+#include "src/core/ext/filters/client_channel/client_channel_internal.h"
#include "src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h"
#include "src/core/ext/filters/stateful_session/stateful_session_filter.h"
#include "src/core/ext/xds/xds_health_status.h"
@@ -370,7 +370,7 @@ XdsOverrideHostLb::Picker::PickOverridenHost(y_absl::string_view override_host)
LoadBalancingPolicy::PickResult XdsOverrideHostLb::Picker::Pick(
LoadBalancingPolicy::PickArgs args) {
- auto* call_state = static_cast<LbCallStateInternal*>(args.call_state);
+ auto* call_state = static_cast<ClientChannelLbCallState*>(args.call_state);
auto override_host = call_state->GetCallAttribute(XdsOverrideHostTypeName());
auto overridden_host_pick = PickOverridenHost(override_host);
if (overridden_host_pick.has_value()) {
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
index 237bb94b16..0ae8c1ad40 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
@@ -31,10 +31,12 @@
#include "y_absl/base/thread_annotations.h"
#include "y_absl/status/status.h"
#include "y_absl/status/statusor.h"
+#include "y_absl/strings/match.h"
#include "y_absl/strings/string_view.h"
#include "y_absl/strings/strip.h"
#include "y_absl/types/optional.h"
+#include <grpc/event_engine/event_engine.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@@ -42,8 +44,6 @@
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/debug_location.h"
-#include "src/core/lib/gprpp/global_config_generic.h"
-#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/status_helper.h"
@@ -62,7 +62,6 @@
#if GRPC_ARES == 1
#include <stdio.h>
-#include <string.h>
#include <address_sorting/address_sorting.h>
@@ -71,12 +70,11 @@
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h"
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
-#include "src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h"
#include "src/core/ext/filters/client_channel/resolver/polling_resolver.h"
#include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/config/config_vars.h"
#include "src/core/lib/event_engine/handle_containers.h"
-#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/gethostname.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/json/json.h"
@@ -96,7 +94,7 @@ namespace {
class AresClientChannelDNSResolver : public PollingResolver {
public:
AresClientChannelDNSResolver(ResolverArgs args,
- const ChannelArgs& channel_args);
+ Duration min_time_between_resolutions);
OrphanablePtr<Orphanable> StartRequest() override;
@@ -206,29 +204,26 @@ class AresClientChannelDNSResolver : public PollingResolver {
};
AresClientChannelDNSResolver::AresClientChannelDNSResolver(
- ResolverArgs args, const ChannelArgs& channel_args)
- : PollingResolver(
- std::move(args), channel_args,
- std::max(Duration::Zero(),
- channel_args
- .GetDurationFromIntMillis(
- GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS)
- .value_or(Duration::Seconds(30))),
- BackOff::Options()
- .set_initial_backoff(Duration::Milliseconds(
- GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS * 1000))
- .set_multiplier(GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER)
- .set_jitter(GRPC_DNS_RECONNECT_JITTER)
- .set_max_backoff(Duration::Milliseconds(
- GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS * 1000)),
- &grpc_trace_cares_resolver),
+ ResolverArgs args, Duration min_time_between_resolutions)
+ : PollingResolver(std::move(args), min_time_between_resolutions,
+ BackOff::Options()
+ .set_initial_backoff(Duration::Milliseconds(
+ GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS * 1000))
+ .set_multiplier(GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER)
+ .set_jitter(GRPC_DNS_RECONNECT_JITTER)
+ .set_max_backoff(Duration::Milliseconds(
+ GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS * 1000)),
+ &grpc_trace_cares_resolver),
request_service_config_(
- !channel_args.GetBool(GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION)
+ !channel_args()
+ .GetBool(GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION)
.value_or(true)),
- enable_srv_queries_(channel_args.GetBool(GRPC_ARG_DNS_ENABLE_SRV_QUERIES)
+ enable_srv_queries_(channel_args()
+ .GetBool(GRPC_ARG_DNS_ENABLE_SRV_QUERIES)
.value_or(false)),
query_timeout_ms_(
- std::max(0, channel_args.GetInt(GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS)
+ std::max(0, channel_args()
+ .GetInt(GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS)
.value_or(GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS))) {}
AresClientChannelDNSResolver::~AresClientChannelDNSResolver() {
@@ -461,9 +456,13 @@ class AresClientChannelDNSResolverFactory : public ResolverFactory {
}
OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
- ChannelArgs channel_args = args.args;
- return MakeOrphanable<AresClientChannelDNSResolver>(std::move(args),
- channel_args);
+ Duration min_time_between_resolutions = std::max(
+ Duration::Zero(), args.args
+ .GetDurationFromIntMillis(
+ GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS)
+ .value_or(Duration::Seconds(30)));
+ return MakeOrphanable<AresClientChannelDNSResolver>(
+ std::move(args), min_time_between_resolutions);
}
};
@@ -811,18 +810,12 @@ class AresDNSResolver : public DNSResolver {
intptr_t aba_token_ Y_ABSL_GUARDED_BY(mu_) = 0;
};
-bool ShouldUseAres(const char* resolver_env) {
- return resolver_env != nullptr && gpr_stricmp(resolver_env, "ares") == 0;
+bool ShouldUseAres(y_absl::string_view resolver_env) {
+ return !resolver_env.empty() && y_absl::EqualsIgnoreCase(resolver_env, "ares");
}
bool UseAresDnsResolver() {
- static const bool result = []() {
- UniquePtr<char> resolver = GPR_GLOBAL_CONFIG_GET(grpc_dns_resolver);
- bool result = ShouldUseAres(resolver.get());
- if (result) gpr_log(GPR_DEBUG, "Using ares dns resolver");
- return result;
- }();
- return result;
+ return ShouldUseAres(ConfigVars::Get().DnsResolver());
}
} // namespace
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc
index 7c0efe1627..594876b280 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc
@@ -252,7 +252,7 @@ class GrpcPolledFdWindows {
bool IsFdStillReadableLocked() { return read_buf_has_data_; }
- void ShutdownLocked(grpc_error_handle error) {
+ void ShutdownLocked(grpc_error_handle /* error */) {
grpc_winsocket_shutdown(winsocket_);
}
@@ -263,7 +263,7 @@ class GrpcPolledFdWindows {
const char* GetName() const { return name_.c_str(); }
ares_ssize_t RecvFrom(WSAErrorContext* wsa_error_ctx, void* data,
- ares_socket_t data_len, int flags,
+ ares_socket_t data_len, int /* flags */,
struct sockaddr* from, ares_socklen_t* from_len) {
GRPC_CARES_TRACE_LOG(
"fd:|%s| RecvFrom called read_buf_has_data:%d Current read buf "
@@ -301,7 +301,7 @@ class GrpcPolledFdWindows {
grpc_slice out = GRPC_SLICE_MALLOC(total);
size_t cur = 0;
for (int i = 0; i < iov_count; i++) {
- for (int k = 0; k < iov[i].iov_len; k++) {
+ for (size_t k = 0; k < iov[i].iov_len; k++) {
GRPC_SLICE_START_PTR(out)[cur++] = ((char*)iov[i].iov_base)[k];
}
}
@@ -862,7 +862,7 @@ class GrpcPolledFdFactoryWindows : public GrpcPolledFdFactory {
explicit GrpcPolledFdFactoryWindows(Mutex* mu) : sock_to_polled_fd_map_(mu) {}
GrpcPolledFd* NewGrpcPolledFdLocked(
- ares_socket_t as, grpc_pollset_set* driver_pollset_set) override {
+ ares_socket_t as, grpc_pollset_set* /* driver_pollset_set */) override {
GrpcPolledFdWindows* polled_fd = sock_to_polled_fd_map_.LookupPolledFd(as);
// Set a flag so that the virtual socket "close" method knows it
// doesn't need to call ShutdownLocked, since now the driver will.
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc
deleted file mode 100644
index 97920b9ba1..0000000000
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// Copyright 2019 gRPC authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-// This is similar to the sockaddr resolver, except that it supports a
-// bunch of query args that are useful for dependency injection in tests.
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h"
-
-#include "src/core/lib/gprpp/global_config.h"
-
-GPR_GLOBAL_CONFIG_DEFINE_STRING(
- grpc_dns_resolver, "",
- "Declares which DNS resolver to use. The default is ares if gRPC is built "
- "with c-ares support. Otherwise, the value of this environment variable is "
- "ignored.")
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h
deleted file mode 100644
index ae7afa7272..0000000000
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-//
-// Copyright 2019 gRPC authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//
-
-#ifndef GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_DNS_RESOLVER_SELECTION_H
-#define GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_DNS_RESOLVER_SELECTION_H
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/lib/gprpp/global_config_generic.h"
-#include "src/core/lib/gprpp/memory.h"
-
-GPR_GLOBAL_CONFIG_DECLARE_STRING(grpc_dns_resolver);
-
-#endif // GRPC_SRC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_DNS_RESOLVER_SELECTION_H
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
index 243b7dcf0a..074f858a71 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
@@ -26,6 +26,7 @@
#include "y_absl/functional/bind_front.h"
#include "y_absl/status/status.h"
#include "y_absl/status/statusor.h"
+#include "y_absl/strings/match.h"
#include "y_absl/strings/str_cat.h"
#include "y_absl/strings/string_view.h"
#include "y_absl/strings/strip.h"
@@ -34,16 +35,13 @@
#include <grpc/grpc.h>
#include <grpc/support/log.h>
-#include "src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h"
#include "src/core/ext/filters/client_channel/resolver/polling_resolver.h"
#include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/config/config_vars.h"
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/debug/trace.h"
-#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/debug_location.h"
-#include "src/core/lib/gprpp/global_config_generic.h"
-#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/time.h"
@@ -68,7 +66,7 @@ TraceFlag grpc_trace_dns_resolver(false, "dns_resolver");
class NativeClientChannelDNSResolver : public PollingResolver {
public:
NativeClientChannelDNSResolver(ResolverArgs args,
- const ChannelArgs& channel_args);
+ Duration min_time_between_resolutions);
~NativeClientChannelDNSResolver() override;
OrphanablePtr<Orphanable> StartRequest() override;
@@ -89,22 +87,16 @@ class NativeClientChannelDNSResolver : public PollingResolver {
};
NativeClientChannelDNSResolver::NativeClientChannelDNSResolver(
- ResolverArgs args, const ChannelArgs& channel_args)
- : PollingResolver(
- std::move(args), channel_args,
- std::max(Duration::Zero(),
- channel_args
- .GetDurationFromIntMillis(
- GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS)
- .value_or(Duration::Seconds(30))),
- BackOff::Options()
- .set_initial_backoff(Duration::Milliseconds(
- GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS * 1000))
- .set_multiplier(GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER)
- .set_jitter(GRPC_DNS_RECONNECT_JITTER)
- .set_max_backoff(Duration::Milliseconds(
- GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS * 1000)),
- &grpc_trace_dns_resolver) {
+ ResolverArgs args, Duration min_time_between_resolutions)
+ : PollingResolver(std::move(args), min_time_between_resolutions,
+ BackOff::Options()
+ .set_initial_backoff(Duration::Milliseconds(
+ GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS * 1000))
+ .set_multiplier(GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER)
+ .set_jitter(GRPC_DNS_RECONNECT_JITTER)
+ .set_max_backoff(Duration::Milliseconds(
+ GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS * 1000)),
+ &grpc_trace_dns_resolver) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_dns_resolver)) {
gpr_log(GPR_DEBUG, "[dns_resolver=%p] created", this);
}
@@ -175,18 +167,20 @@ class NativeClientChannelDNSResolverFactory : public ResolverFactory {
OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
if (!IsValidUri(args.uri)) return nullptr;
- auto channel_args = args.args;
+ Duration min_time_between_resolutions = std::max(
+ Duration::Zero(), args.args
+ .GetDurationFromIntMillis(
+ GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS)
+ .value_or(Duration::Seconds(30)));
return MakeOrphanable<NativeClientChannelDNSResolver>(
- std::move(args), std::move(channel_args));
+ std::move(args), min_time_between_resolutions);
}
};
} // namespace
void RegisterNativeDnsResolver(CoreConfiguration::Builder* builder) {
- static const char* const resolver =
- GPR_GLOBAL_CONFIG_GET(grpc_dns_resolver).release();
- if (gpr_stricmp(resolver, "native") == 0) {
+ if (y_absl::EqualsIgnoreCase(ConfigVars::Get().DnsResolver(), "native")) {
gpr_log(GPR_DEBUG, "Using native dns resolver");
builder->resolver_registry()->RegisterResolverFactory(
std::make_unique<NativeClientChannelDNSResolverFactory>());
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc
index b9bcb2cb20..e004ce738f 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc
@@ -16,28 +16,23 @@
#include <grpc/support/port_platform.h>
-#include <string.h>
-
#include <cstdint>
-#include <initializer_list>
#include <memory>
#include <random>
#include <util/generic/string.h>
#include <util/string/cast.h>
+#include <type_traits>
#include <utility>
-#include "y_absl/status/status.h"
#include "y_absl/status/statusor.h"
#include "y_absl/strings/str_cat.h"
-#include "y_absl/strings/str_format.h"
#include "y_absl/strings/string_view.h"
#include "y_absl/strings/strip.h"
#include "y_absl/types/optional.h"
-#include <grpc/grpc.h>
-#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
+#include "src/core/ext/gcp/metadata_query.h"
#include "src/core/ext/xds/xds_bootstrap.h"
#include "src/core/ext/xds/xds_client_grpc.h"
#include "src/core/lib/channel/channel_args.h"
@@ -46,13 +41,8 @@
#include "src/core/lib/gprpp/env.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/gprpp/work_serializer.h"
-#include "src/core/lib/http/httpcli.h"
-#include "src/core/lib/http/parser.h"
-#include "src/core/lib/iomgr/closure.h"
-#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/json/json.h"
#include "src/core/lib/resolver/resolver.h"
@@ -60,7 +50,6 @@
#include "src/core/lib/resolver/resolver_registry.h"
#include "src/core/lib/resource_quota/resource_quota.h"
#include "src/core/lib/security/credentials/alts/check_gcp_environment.h"
-#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/uri/uri_parser.h"
namespace grpc_core {
@@ -79,53 +68,6 @@ class GoogleCloud2ProdResolver : public Resolver {
void ShutdownLocked() override;
private:
- // Represents an HTTP request to the metadata server.
- class MetadataQuery : public InternallyRefCounted<MetadataQuery> {
- public:
- MetadataQuery(RefCountedPtr<GoogleCloud2ProdResolver> resolver,
- const char* path, grpc_polling_entity* pollent);
- ~MetadataQuery() override;
-
- void Orphan() override;
-
- private:
- static void OnHttpRequestDone(void* arg, grpc_error_handle error);
-
- // If error is not y_absl::OkStatus(), then it's not safe to look at response.
- virtual void OnDone(GoogleCloud2ProdResolver* resolver,
- const grpc_http_response* response,
- grpc_error_handle error) = 0;
-
- RefCountedPtr<GoogleCloud2ProdResolver> resolver_;
- OrphanablePtr<HttpRequest> http_request_;
- grpc_http_response response_;
- grpc_closure on_done_;
- };
-
- // A metadata server query to get the zone.
- class ZoneQuery : public MetadataQuery {
- public:
- ZoneQuery(RefCountedPtr<GoogleCloud2ProdResolver> resolver,
- grpc_polling_entity* pollent);
-
- private:
- void OnDone(GoogleCloud2ProdResolver* resolver,
- const grpc_http_response* response,
- grpc_error_handle error) override;
- };
-
- // A metadata server query to get the IPv6 address.
- class IPv6Query : public MetadataQuery {
- public:
- IPv6Query(RefCountedPtr<GoogleCloud2ProdResolver> resolver,
- grpc_polling_entity* pollent);
-
- private:
- void OnDone(GoogleCloud2ProdResolver* resolver,
- const grpc_http_response* response,
- grpc_error_handle error) override;
- };
-
void ZoneQueryDone(TString zone);
void IPv6QueryDone(bool ipv6_supported);
void StartXdsResolver();
@@ -138,129 +80,14 @@ class GoogleCloud2ProdResolver : public Resolver {
TString metadata_server_name_ = "metadata.google.internal.";
bool shutdown_ = false;
- OrphanablePtr<ZoneQuery> zone_query_;
+ OrphanablePtr<MetadataQuery> zone_query_;
y_absl::optional<TString> zone_;
- OrphanablePtr<IPv6Query> ipv6_query_;
+ OrphanablePtr<MetadataQuery> ipv6_query_;
y_absl::optional<bool> supports_ipv6_;
};
//
-// GoogleCloud2ProdResolver::MetadataQuery
-//
-
-GoogleCloud2ProdResolver::MetadataQuery::MetadataQuery(
- RefCountedPtr<GoogleCloud2ProdResolver> resolver, const char* path,
- grpc_polling_entity* pollent)
- : resolver_(std::move(resolver)) {
- // Start HTTP request.
- GRPC_CLOSURE_INIT(&on_done_, OnHttpRequestDone, this, nullptr);
- Ref().release(); // Ref held by callback.
- grpc_http_request request;
- memset(&request, 0, sizeof(grpc_http_request));
- grpc_http_header header = {const_cast<char*>("Metadata-Flavor"),
- const_cast<char*>("Google")};
- request.hdr_count = 1;
- request.hdrs = &header;
- auto uri = URI::Create("http", resolver_->metadata_server_name_, path,
- {} /* query params */, "" /* fragment */);
- GPR_ASSERT(uri.ok()); // params are hardcoded
- grpc_arg resource_quota_arg = grpc_channel_arg_pointer_create(
- const_cast<char*>(GRPC_ARG_RESOURCE_QUOTA),
- resolver_->resource_quota_.get(), grpc_resource_quota_arg_vtable());
- grpc_channel_args args = {1, &resource_quota_arg};
- http_request_ =
- HttpRequest::Get(std::move(*uri), &args, pollent, &request,
- Timestamp::Now() + Duration::Seconds(10), // 10s timeout
- &on_done_, &response_,
- RefCountedPtr<grpc_channel_credentials>(
- grpc_insecure_credentials_create()));
- http_request_->Start();
-}
-
-GoogleCloud2ProdResolver::MetadataQuery::~MetadataQuery() {
- grpc_http_response_destroy(&response_);
-}
-
-void GoogleCloud2ProdResolver::MetadataQuery::Orphan() {
- http_request_.reset();
- Unref();
-}
-
-void GoogleCloud2ProdResolver::MetadataQuery::OnHttpRequestDone(
- void* arg, grpc_error_handle error) {
- auto* self = static_cast<MetadataQuery*>(arg);
- // Hop back into WorkSerializer to call OnDone().
- // Note: We implicitly pass our ref to the callback here.
- self->resolver_->work_serializer_->Run(
- [self, error]() {
- self->OnDone(self->resolver_.get(), &self->response_, error);
- self->Unref();
- },
- DEBUG_LOCATION);
-}
-
-//
-// GoogleCloud2ProdResolver::ZoneQuery
-//
-
-GoogleCloud2ProdResolver::ZoneQuery::ZoneQuery(
- RefCountedPtr<GoogleCloud2ProdResolver> resolver,
- grpc_polling_entity* pollent)
- : MetadataQuery(std::move(resolver), "/computeMetadata/v1/instance/zone",
- pollent) {}
-
-void GoogleCloud2ProdResolver::ZoneQuery::OnDone(
- GoogleCloud2ProdResolver* resolver, const grpc_http_response* response,
- grpc_error_handle error) {
- y_absl::StatusOr<TString> zone;
- if (!error.ok()) {
- zone = y_absl::UnknownError(y_absl::StrCat(
- "error fetching zone from metadata server: ", StatusToString(error)));
- } else if (response->status != 200) {
- zone = y_absl::UnknownError(y_absl::StrFormat(
- "zone query received non-200 status: %d", response->status));
- } else {
- y_absl::string_view body(response->body, response->body_length);
- size_t i = body.find_last_of('/');
- if (i == body.npos) {
- zone = y_absl::UnknownError(
- y_absl::StrCat("could not parse zone from metadata server: ", body));
- } else {
- zone = TString(body.substr(i + 1));
- }
- }
- if (!zone.ok()) {
- gpr_log(GPR_ERROR, "zone query failed: %s",
- zone.status().ToString().c_str());
- resolver->ZoneQueryDone("");
- } else {
- resolver->ZoneQueryDone(std::move(*zone));
- }
-}
-
-//
-// GoogleCloud2ProdResolver::IPv6Query
-//
-
-GoogleCloud2ProdResolver::IPv6Query::IPv6Query(
- RefCountedPtr<GoogleCloud2ProdResolver> resolver,
- grpc_polling_entity* pollent)
- : MetadataQuery(std::move(resolver),
- "/computeMetadata/v1/instance/network-interfaces/0/ipv6s",
- pollent) {}
-
-void GoogleCloud2ProdResolver::IPv6Query::OnDone(
- GoogleCloud2ProdResolver* resolver, const grpc_http_response* response,
- grpc_error_handle error) {
- if (!error.ok()) {
- gpr_log(GPR_ERROR, "error fetching IPv6 address from metadata server: %s",
- StatusToString(error).c_str());
- }
- resolver->IPv6QueryDone(error.ok() && response->status == 200);
-}
-
-//
// GoogleCloud2ProdResolver
//
@@ -323,8 +150,33 @@ void GoogleCloud2ProdResolver::StartLocked() {
return;
}
// Using xDS. Start metadata server queries.
- zone_query_ = MakeOrphanable<ZoneQuery>(Ref(), &pollent_);
- ipv6_query_ = MakeOrphanable<IPv6Query>(Ref(), &pollent_);
+ zone_query_ = MakeOrphanable<MetadataQuery>(
+ metadata_server_name_, TString(MetadataQuery::kZoneAttribute),
+ &pollent_,
+ [resolver = static_cast<RefCountedPtr<GoogleCloud2ProdResolver>>(Ref())](
+ TString /* attribute */,
+ y_absl::StatusOr<TString> result) mutable {
+ resolver->work_serializer_->Run(
+ [resolver, result = std::move(result)]() mutable {
+ resolver->ZoneQueryDone(result.ok() ? std::move(result).value()
+ : "");
+ },
+ DEBUG_LOCATION);
+ },
+ Duration::Seconds(10));
+ ipv6_query_ = MakeOrphanable<MetadataQuery>(
+ metadata_server_name_, TString(MetadataQuery::kIPv6Attribute),
+ &pollent_,
+ [resolver = static_cast<RefCountedPtr<GoogleCloud2ProdResolver>>(Ref())](
+ TString /* attribute */,
+ y_absl::StatusOr<TString> result) mutable {
+ resolver->work_serializer_->Run(
+ [resolver, result = std::move(result)]() {
+ resolver->IPv6QueryDone(result.ok());
+ },
+ DEBUG_LOCATION);
+ },
+ Duration::Seconds(10));
}
void GoogleCloud2ProdResolver::RequestReresolutionLocked() {
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/polling_resolver.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/polling_resolver.cc
index 97085b5622..b43fa989c7 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/polling_resolver.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/polling_resolver.cc
@@ -47,13 +47,12 @@ namespace grpc_core {
using ::grpc_event_engine::experimental::EventEngine;
PollingResolver::PollingResolver(ResolverArgs args,
- const ChannelArgs& channel_args,
Duration min_time_between_resolutions,
BackOff::Options backoff_options,
TraceFlag* tracer)
: authority_(args.uri.authority()),
name_to_resolve_(y_absl::StripPrefix(args.uri.path(), "/")),
- channel_args_(channel_args),
+ channel_args_(std::move(args.args)),
work_serializer_(std::move(args.work_serializer)),
result_handler_(std::move(args.result_handler)),
tracer_(tracer),
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/polling_resolver.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/polling_resolver.h
index 970abd4dc2..ff918f969d 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/polling_resolver.h
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/polling_resolver.h
@@ -45,8 +45,7 @@ namespace grpc_core {
// Implementations need only to implement StartRequest().
class PollingResolver : public Resolver {
public:
- PollingResolver(ResolverArgs args, const ChannelArgs& channel_args,
- Duration min_time_between_resolutions,
+ PollingResolver(ResolverArgs args, Duration min_time_between_resolutions,
BackOff::Options backoff_options, TraceFlag* tracer);
~PollingResolver() override;
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
index b922a0ee15..2bf3d86a0a 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
@@ -48,6 +48,7 @@
#include <grpc/grpc.h>
#include "src/core/lib/gprpp/unique_type_name.h"
+#include "src/core/lib/slice/slice.h"
#define XXH_INLINE_ALL
#include "xxhash.h"
@@ -85,7 +86,6 @@
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/service_config/service_config.h"
#include "src/core/lib/service_config/service_config_impl.h"
-#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/uri/uri_parser.h"
@@ -659,8 +659,10 @@ y_absl::optional<uint64_t> HeaderHashHelper(
y_absl::StatusOr<ConfigSelector::CallConfig>
XdsResolver::XdsConfigSelector::GetCallConfig(GetCallConfigArgs args) {
+ Slice* path = args.initial_metadata->get_pointer(HttpPathMetadata());
+ GPR_ASSERT(path != nullptr);
auto route_index = XdsRouting::GetRouteForRequest(
- RouteListIterator(&route_table_), StringViewFromSlice(*args.path),
+ RouteListIterator(&route_table_), path->as_string_view(),
args.initial_metadata);
if (!route_index.has_value()) {
return y_absl::UnavailableError(
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_filter.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_filter.cc
index 10b3205552..7ec4d5389c 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_filter.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_filter.cc
@@ -36,13 +36,14 @@
#include "y_absl/strings/strip.h"
#include "y_absl/types/optional.h"
+#include <grpc/event_engine/event_engine.h>
#include <grpc/grpc.h>
#include <grpc/slice.h>
#include <grpc/status.h>
-#include <grpc/support/atm.h>
#include <grpc/support/log.h>
#include "src/core/ext/filters/client_channel/client_channel.h"
+#include "src/core/ext/filters/client_channel/client_channel_internal.h"
#include "src/core/ext/filters/client_channel/config_selector.h"
#include "src/core/ext/filters/client_channel/retry_service_config.h"
#include "src/core/ext/filters/client_channel/retry_throttle.h"
@@ -65,7 +66,6 @@
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/polling_entity.h"
-#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/service_config/service_config.h"
#include "src/core/lib/service_config/service_config_call_data.h"
@@ -133,6 +133,7 @@ namespace grpc_core {
namespace {
+using grpc_event_engine::experimental::EventEngine;
using internal::RetryGlobalConfig;
using internal::RetryMethodConfig;
using internal::RetryServiceConfigParser;
@@ -177,6 +178,7 @@ class RetryFilter {
RetryFilter(const ChannelArgs& args, grpc_error_handle* error)
: client_channel_(args.GetObject<ClientChannel>()),
+ event_engine_(args.GetObject<EventEngine>()),
per_rpc_retry_buffer_size_(GetMaxPerRpcRetryBufferSize(args)),
service_config_parser_index_(
internal::RetryServiceConfigParser::ParserIndex()) {
@@ -213,6 +215,7 @@ class RetryFilter {
const grpc_call_context_element* context);
ClientChannel* client_channel_;
+ EventEngine* const event_engine_;
size_t per_rpc_retry_buffer_size_;
RefCountedPtr<ServerRetryThrottleData> retry_throttle_data_;
const size_t service_config_parser_index_;
@@ -270,7 +273,7 @@ class RetryFilter::CallData {
// We allocate one struct on the arena for each attempt at starting a
// batch on a given LB call.
class BatchData
- : public RefCounted<BatchData, PolymorphicRefCount, kUnrefCallDtor> {
+ : public RefCounted<BatchData, PolymorphicRefCount, UnrefCallDtor> {
public:
BatchData(RefCountedPtr<CallAttempt> call_attempt, int refcount,
bool set_on_complete);
@@ -443,18 +446,17 @@ class RetryFilter::CallData {
// Abandons the call attempt. Unrefs any deferred batches.
void Abandon();
- static void OnPerAttemptRecvTimer(void* arg, grpc_error_handle error);
+ void OnPerAttemptRecvTimer();
static void OnPerAttemptRecvTimerLocked(void* arg, grpc_error_handle error);
void MaybeCancelPerAttemptRecvTimer();
CallData* calld_;
AttemptDispatchController attempt_dispatch_controller_;
- OrphanablePtr<ClientChannel::LoadBalancedCall> lb_call_;
+ OrphanablePtr<ClientChannel::FilterBasedLoadBalancedCall> lb_call_;
bool lb_call_committed_ = false;
- grpc_timer per_attempt_recv_timer_;
grpc_closure on_per_attempt_recv_timer_;
- bool per_attempt_recv_timer_pending_ = false;
+ y_absl::optional<EventEngine::TaskHandle> per_attempt_recv_timer_handle_;
// BatchData.batch.payload points to this.
grpc_transport_stream_op_batch_payload batch_payload_;
@@ -549,14 +551,15 @@ class RetryFilter::CallData {
// If server_pushback is nullopt, retry_backoff_ is used.
void StartRetryTimer(y_absl::optional<Duration> server_pushback);
- static void OnRetryTimer(void* arg, grpc_error_handle error);
- static void OnRetryTimerLocked(void* arg, grpc_error_handle error);
+ void OnRetryTimer();
+ static void OnRetryTimerLocked(void* arg, grpc_error_handle /*error*/);
// Adds a closure to closures to start a transparent retry.
void AddClosureToStartTransparentRetry(CallCombinerClosureList* closures);
static void StartTransparentRetry(void* arg, grpc_error_handle error);
- OrphanablePtr<ClientChannel::LoadBalancedCall> CreateLoadBalancedCall(
+ OrphanablePtr<ClientChannel::FilterBasedLoadBalancedCall>
+ CreateLoadBalancedCall(
ConfigSelector::CallDispatchController* call_dispatch_controller,
bool is_transparent_retry);
@@ -587,7 +590,7 @@ class RetryFilter::CallData {
// LB call used when we've committed to a call attempt and the retry
// state for that attempt is no longer needed. This provides a fast
// path for long-running streaming calls that minimizes overhead.
- OrphanablePtr<ClientChannel::LoadBalancedCall> committed_call_;
+ OrphanablePtr<ClientChannel::FilterBasedLoadBalancedCall> committed_call_;
// When are are not yet fully committed to a particular call (i.e.,
// either we might still retry or we have committed to the call but
@@ -602,26 +605,16 @@ class RetryFilter::CallData {
// Retry state.
bool retry_committed_ : 1;
- bool retry_timer_pending_ : 1;
bool retry_codepath_started_ : 1;
bool sent_transparent_retry_not_seen_by_server_ : 1;
int num_attempts_completed_ = 0;
- grpc_timer retry_timer_;
+ y_absl::optional<EventEngine::TaskHandle> retry_timer_handle_;
grpc_closure retry_closure_;
// Cached data for retrying send ops.
// send_initial_metadata
bool seen_send_initial_metadata_ = false;
grpc_metadata_batch send_initial_metadata_{arena_};
- // TODO(roth): As part of implementing hedging, we'll probably need to
- // have the LB call set a value in CallAttempt and then propagate it
- // from CallAttempt to the parent call when we commit. Otherwise, we
- // may leave this with a value for a peer other than the one we
- // actually commit to. Alternatively, maybe see if there's a way to
- // change the surface API such that the peer isn't available until
- // after initial metadata is received? (Could even change the
- // transport API to return this with the recv_initial_metadata op.)
- gpr_atm* peer_string_;
// send_message
// When we get a send_message op, we replace the original byte stream
// with a CachingByteStream that caches the slices to a local buffer for
@@ -657,7 +650,7 @@ class RetryFilter::CallData {
// on_call_stack_destruction closure from the surface.
class RetryFilter::CallData::CallStackDestructionBarrier
: public RefCounted<CallStackDestructionBarrier, PolymorphicRefCount,
- kUnrefCallDtor> {
+ UnrefCallDtor> {
public:
CallStackDestructionBarrier() {}
@@ -724,23 +717,23 @@ RetryFilter::CallData::CallAttempt::CallAttempt(CallData* calld,
// If per_attempt_recv_timeout is set, start a timer.
if (calld->retry_policy_ != nullptr &&
calld->retry_policy_->per_attempt_recv_timeout().has_value()) {
- Timestamp per_attempt_recv_deadline =
- Timestamp::Now() + *calld->retry_policy_->per_attempt_recv_timeout();
+ const Duration per_attempt_recv_timeout =
+ *calld->retry_policy_->per_attempt_recv_timeout();
if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) {
gpr_log(GPR_INFO,
"chand=%p calld=%p attempt=%p: per-attempt timeout in %" PRId64
" ms",
- calld->chand_, calld, this,
- calld->retry_policy_->per_attempt_recv_timeout()->millis());
+ calld->chand_, calld, this, per_attempt_recv_timeout.millis());
}
// Schedule retry after computed delay.
- GRPC_CLOSURE_INIT(&on_per_attempt_recv_timer_, OnPerAttemptRecvTimer, this,
- nullptr);
GRPC_CALL_STACK_REF(calld->owning_call_, "OnPerAttemptRecvTimer");
Ref(DEBUG_LOCATION, "OnPerAttemptRecvTimer").release();
- per_attempt_recv_timer_pending_ = true;
- grpc_timer_init(&per_attempt_recv_timer_, per_attempt_recv_deadline,
- &on_per_attempt_recv_timer_);
+ per_attempt_recv_timer_handle_ = calld_->chand_->event_engine_->RunAfter(
+ per_attempt_recv_timeout, [this] {
+ ApplicationCallbackExecCtx callback_exec_ctx;
+ ExecCtx exec_ctx;
+ OnPerAttemptRecvTimer();
+ });
}
}
@@ -804,7 +797,7 @@ void RetryFilter::CallData::CallAttempt::MaybeSwitchToFastPath() {
// If we've already switched to fast path, there's nothing to do here.
if (calld_->committed_call_ != nullptr) return;
// If the perAttemptRecvTimeout timer is pending, we can't switch yet.
- if (per_attempt_recv_timer_pending_) return;
+ if (per_attempt_recv_timer_handle_.has_value()) return;
// If there are still send ops to replay, we can't switch yet.
if (HaveSendOpsToReplay()) return;
// If we started an internal batch for recv_trailing_metadata but have not
@@ -882,7 +875,7 @@ namespace {
void StartBatchInCallCombiner(void* arg, grpc_error_handle /*ignored*/) {
grpc_transport_stream_op_batch* batch =
static_cast<grpc_transport_stream_op_batch*>(arg);
- auto* lb_call = static_cast<ClientChannel::LoadBalancedCall*>(
+ auto* lb_call = static_cast<ClientChannel::FilterBasedLoadBalancedCall*>(
batch->handler_private.extra_arg);
// Note: This will release the call combiner.
lb_call->StartTransportStreamOpBatch(batch);
@@ -896,7 +889,7 @@ void RetryFilter::CallData::CallAttempt::AddClosureForBatch(
if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) {
gpr_log(GPR_INFO, "chand=%p calld=%p attempt=%p: adding batch (%s): %s",
calld_->chand_, calld_, this, reason,
- grpc_transport_stream_op_batch_string(batch).c_str());
+ grpc_transport_stream_op_batch_string(batch, false).c_str());
}
batch->handler_private.extra_arg = lb_call_.get();
GRPC_CLOSURE_INIT(&batch->handler_private.closure, StartBatchInCallCombiner,
@@ -1250,14 +1243,11 @@ void RetryFilter::CallData::CallAttempt::Abandon() {
on_complete_deferred_batches_.clear();
}
-void RetryFilter::CallData::CallAttempt::OnPerAttemptRecvTimer(
- void* arg, grpc_error_handle error) {
- auto* call_attempt = static_cast<CallAttempt*>(arg);
- GRPC_CLOSURE_INIT(&call_attempt->on_per_attempt_recv_timer_,
- OnPerAttemptRecvTimerLocked, call_attempt, nullptr);
- GRPC_CALL_COMBINER_START(call_attempt->calld_->call_combiner_,
- &call_attempt->on_per_attempt_recv_timer_, error,
- "per-attempt timer fired");
+void RetryFilter::CallData::CallAttempt::OnPerAttemptRecvTimer() {
+ GRPC_CLOSURE_INIT(&on_per_attempt_recv_timer_, OnPerAttemptRecvTimerLocked,
+ this, nullptr);
+ GRPC_CALL_COMBINER_START(calld_->call_combiner_, &on_per_attempt_recv_timer_,
+ y_absl::OkStatus(), "per-attempt timer fired");
}
void RetryFilter::CallData::CallAttempt::OnPerAttemptRecvTimerLocked(
@@ -1267,35 +1257,33 @@ void RetryFilter::CallData::CallAttempt::OnPerAttemptRecvTimerLocked(
if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) {
gpr_log(GPR_INFO,
"chand=%p calld=%p attempt=%p: perAttemptRecvTimeout timer fired: "
- "error=%s, per_attempt_recv_timer_pending_=%d",
+ "error=%s, per_attempt_recv_timer_handle_.has_value()=%d",
calld->chand_, calld, call_attempt, StatusToString(error).c_str(),
- call_attempt->per_attempt_recv_timer_pending_);
+ call_attempt->per_attempt_recv_timer_handle_.has_value());
}
CallCombinerClosureList closures;
- if (error.ok() && call_attempt->per_attempt_recv_timer_pending_) {
- call_attempt->per_attempt_recv_timer_pending_ = false;
- // Cancel this attempt.
- // TODO(roth): When implementing hedging, we should not cancel the
- // current attempt.
- call_attempt->MaybeAddBatchForCancelOp(
- grpc_error_set_int(
- GRPC_ERROR_CREATE("retry perAttemptRecvTimeout exceeded"),
- StatusIntProperty::kRpcStatus, GRPC_STATUS_CANCELLED),
- &closures);
- // Check whether we should retry.
- if (call_attempt->ShouldRetry(/*status=*/y_absl::nullopt,
- /*server_pushback_ms=*/y_absl::nullopt)) {
- // Mark current attempt as abandoned.
- call_attempt->Abandon();
- // We are retrying. Start backoff timer.
- calld->StartRetryTimer(/*server_pushback=*/y_absl::nullopt);
- } else {
- // Not retrying, so commit the call.
- calld->RetryCommit(call_attempt);
- // If retry state is no longer needed, switch to fast path for
- // subsequent batches.
- call_attempt->MaybeSwitchToFastPath();
- }
+ call_attempt->per_attempt_recv_timer_handle_.reset();
+ // Cancel this attempt.
+ // TODO(roth): When implementing hedging, we should not cancel the
+ // current attempt.
+ call_attempt->MaybeAddBatchForCancelOp(
+ grpc_error_set_int(
+ GRPC_ERROR_CREATE("retry perAttemptRecvTimeout exceeded"),
+ StatusIntProperty::kRpcStatus, GRPC_STATUS_CANCELLED),
+ &closures);
+ // Check whether we should retry.
+ if (call_attempt->ShouldRetry(/*status=*/y_absl::nullopt,
+ /*server_pushback_ms=*/y_absl::nullopt)) {
+ // Mark current attempt as abandoned.
+ call_attempt->Abandon();
+ // We are retrying. Start backoff timer.
+ calld->StartRetryTimer(/*server_pushback=*/y_absl::nullopt);
+ } else {
+ // Not retrying, so commit the call.
+ calld->RetryCommit(call_attempt);
+ // If retry state is no longer needed, switch to fast path for
+ // subsequent batches.
+ call_attempt->MaybeSwitchToFastPath();
}
closures.RunClosures(calld->call_combiner_);
call_attempt->Unref(DEBUG_LOCATION, "OnPerAttemptRecvTimer");
@@ -1303,15 +1291,19 @@ void RetryFilter::CallData::CallAttempt::OnPerAttemptRecvTimerLocked(
}
void RetryFilter::CallData::CallAttempt::MaybeCancelPerAttemptRecvTimer() {
- if (per_attempt_recv_timer_pending_) {
+ if (per_attempt_recv_timer_handle_.has_value()) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) {
gpr_log(GPR_INFO,
"chand=%p calld=%p attempt=%p: cancelling "
"perAttemptRecvTimeout timer",
calld_->chand_, calld_, this);
}
- per_attempt_recv_timer_pending_ = false;
- grpc_timer_cancel(&per_attempt_recv_timer_);
+ if (calld_->chand_->event_engine_->Cancel(
+ *per_attempt_recv_timer_handle_)) {
+ Unref(DEBUG_LOCATION, "OnPerAttemptRecvTimer");
+ GRPC_CALL_STACK_UNREF(calld_->owning_call_, "OnPerAttemptRecvTimer");
+ }
+ per_attempt_recv_timer_handle_.reset();
}
}
@@ -1352,8 +1344,9 @@ RetryFilter::CallData::CallAttempt::BatchData::~BatchData() {
this);
}
CallAttempt* call_attempt = std::exchange(call_attempt_, nullptr);
- GRPC_CALL_STACK_UNREF(call_attempt->calld_->owning_call_, "Retry BatchData");
+ grpc_call_stack* owning_call = call_attempt->calld_->owning_call_;
call_attempt->Unref(DEBUG_LOCATION, "~BatchData");
+ GRPC_CALL_STACK_UNREF(owning_call, "Retry BatchData");
}
void RetryFilter::CallData::CallAttempt::BatchData::
@@ -1880,7 +1873,8 @@ void RetryFilter::CallData::CallAttempt::BatchData::OnComplete(
"got on_complete, error=%s, batch=%s",
calld->chand_, calld, call_attempt, batch_data.get(),
StatusToString(error).c_str(),
- grpc_transport_stream_op_batch_string(&batch_data->batch_).c_str());
+ grpc_transport_stream_op_batch_string(&batch_data->batch_, false)
+ .c_str());
}
// If this attempt has been abandoned, then we're not going to propagate
// the completion of this batch, so do nothing.
@@ -1955,7 +1949,8 @@ void RetryFilter::CallData::CallAttempt::BatchData::OnCompleteForCancelOp(
"got on_complete for cancel_stream batch, error=%s, batch=%s",
calld->chand_, calld, call_attempt, batch_data.get(),
StatusToString(error).c_str(),
- grpc_transport_stream_op_batch_string(&batch_data->batch_).c_str());
+ grpc_transport_stream_op_batch_string(&batch_data->batch_, false)
+ .c_str());
}
GRPC_CALL_COMBINER_STOP(
calld->call_combiner_,
@@ -1987,7 +1982,6 @@ void RetryFilter::CallData::CallAttempt::BatchData::
batch_.send_initial_metadata = true;
batch_.payload->send_initial_metadata.send_initial_metadata =
&call_attempt_->send_initial_metadata_;
- batch_.payload->send_initial_metadata.peer_string = calld->peer_string_;
}
void RetryFilter::CallData::CallAttempt::BatchData::
@@ -2161,7 +2155,6 @@ RetryFilter::CallData::CallData(RetryFilter* chand,
pending_send_message_(false),
pending_send_trailing_metadata_(false),
retry_committed_(false),
- retry_timer_pending_(false),
retry_codepath_started_(false),
sent_transparent_retry_not_seen_by_server_(false) {}
@@ -2179,7 +2172,8 @@ void RetryFilter::CallData::StartTransportStreamOpBatch(
if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace) &&
!GRPC_TRACE_FLAG_ENABLED(grpc_trace_channel)) {
gpr_log(GPR_INFO, "chand=%p calld=%p: batch started from surface: %s",
- chand_, this, grpc_transport_stream_op_batch_string(batch).c_str());
+ chand_, this,
+ grpc_transport_stream_op_batch_string(batch, false).c_str());
}
// If we have an LB call, delegate to the LB call.
if (committed_call_ != nullptr) {
@@ -2221,13 +2215,15 @@ void RetryFilter::CallData::StartTransportStreamOpBatch(
return;
}
// Cancel retry timer if needed.
- if (retry_timer_pending_) {
+ if (retry_timer_handle_.has_value()) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) {
gpr_log(GPR_INFO, "chand=%p calld=%p: cancelling retry timer", chand_,
this);
}
- retry_timer_pending_ = false; // Lame timer callback.
- grpc_timer_cancel(&retry_timer_);
+ if (chand_->event_engine_->Cancel(*retry_timer_handle_)) {
+ GRPC_CALL_STACK_UNREF(owning_call_, "OnRetryTimer");
+ }
+ retry_timer_handle_.reset();
FreeAllCachedSendOpData();
}
// We have no call attempt, so there's nowhere to send the cancellation
@@ -2241,7 +2237,7 @@ void RetryFilter::CallData::StartTransportStreamOpBatch(
PendingBatch* pending = PendingBatchesAdd(batch);
// If the timer is pending, yield the call combiner and wait for it to
// run, since we don't want to start another call attempt until it does.
- if (retry_timer_pending_) {
+ if (retry_timer_handle_.has_value()) {
GRPC_CALL_COMBINER_STOP(call_combiner_,
"added pending batch while retry timer pending");
return;
@@ -2301,7 +2297,7 @@ void RetryFilter::CallData::StartTransportStreamOpBatch(
call_attempt_->StartRetriableBatches();
}
-OrphanablePtr<ClientChannel::LoadBalancedCall>
+OrphanablePtr<ClientChannel::FilterBasedLoadBalancedCall>
RetryFilter::CallData::CreateLoadBalancedCall(
ConfigSelector::CallDispatchController* call_dispatch_controller,
bool is_transparent_retry) {
@@ -2335,7 +2331,6 @@ void RetryFilter::CallData::MaybeCacheSendOpsForBatch(PendingBatch* pending) {
grpc_metadata_batch* send_initial_metadata =
batch->payload->send_initial_metadata.send_initial_metadata;
send_initial_metadata_ = send_initial_metadata->Copy();
- peer_string_ = batch->payload->send_initial_metadata.peer_string;
}
// Set up cache for send_message ops.
if (batch->send_message) {
@@ -2576,42 +2571,40 @@ void RetryFilter::CallData::StartRetryTimer(
// Reset call attempt.
call_attempt_.reset(DEBUG_LOCATION, "StartRetryTimer");
// Compute backoff delay.
- Timestamp next_attempt_time;
+ Duration next_attempt_timeout;
if (server_pushback.has_value()) {
GPR_ASSERT(*server_pushback >= Duration::Zero());
- next_attempt_time = Timestamp::Now() + *server_pushback;
+ next_attempt_timeout = *server_pushback;
retry_backoff_.Reset();
} else {
- next_attempt_time = retry_backoff_.NextAttemptTime();
+ next_attempt_timeout = retry_backoff_.NextAttemptTime() - Timestamp::Now();
}
if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: retrying failed call in %" PRId64 " ms", chand_,
- this, (next_attempt_time - Timestamp::Now()).millis());
+ this, next_attempt_timeout.millis());
}
// Schedule retry after computed delay.
- GRPC_CLOSURE_INIT(&retry_closure_, OnRetryTimer, this, nullptr);
GRPC_CALL_STACK_REF(owning_call_, "OnRetryTimer");
- retry_timer_pending_ = true;
- grpc_timer_init(&retry_timer_, next_attempt_time, &retry_closure_);
+ retry_timer_handle_ =
+ chand_->event_engine_->RunAfter(next_attempt_timeout, [this] {
+ ApplicationCallbackExecCtx callback_exec_ctx;
+ ExecCtx exec_ctx;
+ OnRetryTimer();
+ });
}
-void RetryFilter::CallData::OnRetryTimer(void* arg, grpc_error_handle error) {
- auto* calld = static_cast<CallData*>(arg);
- GRPC_CLOSURE_INIT(&calld->retry_closure_, OnRetryTimerLocked, calld, nullptr);
- GRPC_CALL_COMBINER_START(calld->call_combiner_, &calld->retry_closure_, error,
+void RetryFilter::CallData::OnRetryTimer() {
+ GRPC_CLOSURE_INIT(&retry_closure_, OnRetryTimerLocked, this, nullptr);
+ GRPC_CALL_COMBINER_START(call_combiner_, &retry_closure_, y_absl::OkStatus(),
"retry timer fired");
}
void RetryFilter::CallData::OnRetryTimerLocked(void* arg,
- grpc_error_handle error) {
+ grpc_error_handle /*error*/) {
auto* calld = static_cast<CallData*>(arg);
- if (error.ok() && calld->retry_timer_pending_) {
- calld->retry_timer_pending_ = false;
- calld->CreateCallAttempt(/*is_transparent_retry=*/false);
- } else {
- GRPC_CALL_COMBINER_STOP(calld->call_combiner_, "retry timer cancelled");
- }
+ calld->retry_timer_handle_.reset();
+ calld->CreateCallAttempt(/*is_transparent_retry=*/false);
GRPC_CALL_STACK_UNREF(calld->owning_call_, "OnRetryTimer");
}
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.cc
index 2fd4f7d79d..5feedef993 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.cc
@@ -920,7 +920,8 @@ bool Subchannel::PublishTransportLocked() {
// Construct channel stack.
ChannelStackBuilderImpl builder("subchannel", GRPC_CLIENT_SUBCHANNEL,
connecting_result_.channel_args);
- builder.SetTransport(connecting_result_.transport);
+ // Builder takes ownership of transport.
+ builder.SetTransport(std::exchange(connecting_result_.transport, nullptr));
if (!CoreConfiguration::Get().channel_init().CreateStack(&builder)) {
return false;
}
@@ -933,9 +934,6 @@ bool Subchannel::PublishTransportLocked() {
key_.ToString().c_str(), StatusToString(error).c_str());
return false;
}
- // Release the ownership since it is now owned by the connected filter in the
- // channel stack (published).
- connecting_result_.transport = nullptr;
RefCountedPtr<channelz::SocketNode> socket =
std::move(connecting_result_.socket_node);
connecting_result_.Reset();
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel_stream_client.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel_stream_client.cc
index 1b1bfcd95a..109e9b6974 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel_stream_client.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel_stream_client.cc
@@ -34,6 +34,7 @@
#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/gprpp/time.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/resource_quota/resource_quota.h"
#include "src/core/lib/transport/error_utils.h"
@@ -44,6 +45,8 @@
namespace grpc_core {
+using ::grpc_event_engine::experimental::EventEngine;
+
//
// SubchannelStreamClient
//
@@ -70,12 +73,11 @@ SubchannelStreamClient::SubchannelStreamClient(
.set_multiplier(SUBCHANNEL_STREAM_RECONNECT_BACKOFF_MULTIPLIER)
.set_jitter(SUBCHANNEL_STREAM_RECONNECT_JITTER)
.set_max_backoff(Duration::Seconds(
- SUBCHANNEL_STREAM_RECONNECT_MAX_BACKOFF_SECONDS))) {
+ SUBCHANNEL_STREAM_RECONNECT_MAX_BACKOFF_SECONDS))),
+ event_engine_(connected_subchannel_->args().GetObject<EventEngine>()) {
if (GPR_UNLIKELY(tracer_ != nullptr)) {
gpr_log(GPR_INFO, "%s %p: created SubchannelStreamClient", tracer_, this);
}
- GRPC_CLOSURE_INIT(&retry_timer_callback_, OnRetryTimer, this,
- grpc_schedule_on_exec_ctx);
StartCall();
}
@@ -95,8 +97,9 @@ void SubchannelStreamClient::Orphan() {
MutexLock lock(&mu_);
event_handler_.reset();
call_state_.reset();
- if (retry_timer_callback_pending_) {
- grpc_timer_cancel(&retry_timer_);
+ if (retry_timer_handle_.has_value()) {
+ event_engine_->Cancel(*retry_timer_handle_);
+ retry_timer_handle_.reset();
}
}
Unref(DEBUG_LOCATION, "orphan");
@@ -125,11 +128,10 @@ void SubchannelStreamClient::StartRetryTimerLocked() {
if (event_handler_ != nullptr) {
event_handler_->OnRetryTimerStartLocked(this);
}
- Timestamp next_try = retry_backoff_.NextAttemptTime();
+ const Duration timeout = retry_backoff_.NextAttemptTime() - Timestamp::Now();
if (GPR_UNLIKELY(tracer_ != nullptr)) {
gpr_log(GPR_INFO, "%s %p: SubchannelStreamClient health check call lost...",
tracer_, this);
- Duration timeout = next_try - Timestamp::Now();
if (timeout > Duration::Zero()) {
gpr_log(GPR_INFO, "%s %p: ... will retry in %" PRId64 "ms.", tracer_,
this, timeout.millis());
@@ -137,28 +139,27 @@ void SubchannelStreamClient::StartRetryTimerLocked() {
gpr_log(GPR_INFO, "%s %p: ... retrying immediately.", tracer_, this);
}
}
- // Ref for callback, tracked manually.
- Ref(DEBUG_LOCATION, "health_retry_timer").release();
- retry_timer_callback_pending_ = true;
- grpc_timer_init(&retry_timer_, next_try, &retry_timer_callback_);
+ retry_timer_handle_ = event_engine_->RunAfter(
+ timeout, [self = Ref(DEBUG_LOCATION, "health_retry_timer")]() mutable {
+ ApplicationCallbackExecCtx callback_exec_ctx;
+ ExecCtx exec_ctx;
+ self->OnRetryTimer();
+ self.reset(DEBUG_LOCATION, "health_retry_timer");
+ });
}
-void SubchannelStreamClient::OnRetryTimer(void* arg, grpc_error_handle error) {
- auto* self = static_cast<SubchannelStreamClient*>(arg);
- {
- MutexLock lock(&self->mu_);
- self->retry_timer_callback_pending_ = false;
- if (self->event_handler_ != nullptr && error.ok() &&
- self->call_state_ == nullptr) {
- if (GPR_UNLIKELY(self->tracer_ != nullptr)) {
- gpr_log(GPR_INFO,
- "%s %p: SubchannelStreamClient restarting health check call",
- self->tracer_, self);
- }
- self->StartCallLocked();
+void SubchannelStreamClient::OnRetryTimer() {
+ MutexLock lock(&mu_);
+ if (event_handler_ != nullptr && retry_timer_handle_.has_value() &&
+ call_state_ == nullptr) {
+ if (GPR_UNLIKELY(tracer_ != nullptr)) {
+ gpr_log(GPR_INFO,
+ "%s %p: SubchannelStreamClient restarting health check call",
+ tracer_, this);
}
+ StartCallLocked();
}
- self->Unref(DEBUG_LOCATION, "health_retry_timer");
+ retry_timer_handle_.reset();
}
//
@@ -243,7 +244,6 @@ void SubchannelStreamClient::CallState::StartCallLocked() {
GPR_ASSERT(error.ok());
payload_.send_initial_metadata.send_initial_metadata =
&send_initial_metadata_;
- payload_.send_initial_metadata.peer_string = nullptr;
batch_.send_initial_metadata = true;
// Add send_message op.
send_message_.Append(Slice(
@@ -258,7 +258,6 @@ void SubchannelStreamClient::CallState::StartCallLocked() {
payload_.recv_initial_metadata.recv_initial_metadata =
&recv_initial_metadata_;
payload_.recv_initial_metadata.trailing_metadata_available = nullptr;
- payload_.recv_initial_metadata.peer_string = nullptr;
// recv_initial_metadata_ready callback takes ref, handled manually.
call_->Ref(DEBUG_LOCATION, "recv_initial_metadata_ready").release();
payload_.recv_initial_metadata.recv_initial_metadata_ready =
diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel_stream_client.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel_stream_client.h
index 088ef29869..96a42914a8 100644
--- a/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel_stream_client.h
+++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel_stream_client.h
@@ -27,6 +27,7 @@
#include "y_absl/strings/string_view.h"
#include "y_absl/types/optional.h"
+#include <grpc/event_engine/event_engine.h>
#include <grpc/event_engine/memory_allocator.h>
#include <grpc/slice.h>
#include <grpc/status.h>
@@ -42,7 +43,6 @@
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/iomgr_fwd.h"
#include "src/core/lib/iomgr/polling_entity.h"
-#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/resource_quota/memory_quota.h"
#include "src/core/lib/slice/slice.h"
@@ -196,7 +196,7 @@ class SubchannelStreamClient
void StartCallLocked() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&mu_);
void StartRetryTimerLocked() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&mu_);
- static void OnRetryTimer(void* arg, grpc_error_handle error);
+ void OnRetryTimer() Y_ABSL_LOCKS_EXCLUDED(mu_);
RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
grpc_pollset_set* interested_parties_; // Do not own.
@@ -212,9 +212,12 @@ class SubchannelStreamClient
// Call retry state.
BackOff retry_backoff_ Y_ABSL_GUARDED_BY(mu_);
- grpc_timer retry_timer_ Y_ABSL_GUARDED_BY(mu_);
- grpc_closure retry_timer_callback_ Y_ABSL_GUARDED_BY(mu_);
- bool retry_timer_callback_pending_ Y_ABSL_GUARDED_BY(mu_) = false;
+ y_absl::optional<grpc_event_engine::experimental::EventEngine::TaskHandle>
+ retry_timer_handle_ Y_ABSL_GUARDED_BY(mu_);
+ // A raw pointer will suffice since connected_subchannel_ holds a copy of the
+ // ChannelArgs which holds an std::shared_ptr of the EventEngine.
+ grpc_event_engine::experimental::EventEngine* event_engine_
+ Y_ABSL_GUARDED_BY(mu_);
};
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/ext/filters/http/client/http_client_filter.cc b/contrib/libs/grpc/src/core/ext/filters/http/client/http_client_filter.cc
index 3973cb35bd..ad884d9142 100644
--- a/contrib/libs/grpc/src/core/ext/filters/http/client/http_client_filter.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/http/client/http_client_filter.cc
@@ -134,13 +134,13 @@ ArenaPromise<ServerMetadataHandle> HttpClientFilter::MakeCallPromise(
return std::move(md);
});
- return Race(Map(next_promise_factory(std::move(call_args)),
+ return Race(initial_metadata_err->Wait(),
+ Map(next_promise_factory(std::move(call_args)),
[](ServerMetadataHandle md) -> ServerMetadataHandle {
auto r = CheckServerMetadata(md.get());
if (!r.ok()) return ServerMetadataFromStatus(r);
return md;
- }),
- initial_metadata_err->Wait());
+ }));
}
HttpClientFilter::HttpClientFilter(HttpSchemeMetadata::ValueType scheme,
diff --git a/contrib/libs/grpc/src/core/ext/filters/http/http_filters_plugin.cc b/contrib/libs/grpc/src/core/ext/filters/http/http_filters_plugin.cc
index 77a41142c7..3a4b6ab9f7 100644
--- a/contrib/libs/grpc/src/core/ext/filters/http/http_filters_plugin.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/http/http_filters_plugin.cc
@@ -20,14 +20,9 @@
#include <string.h>
-#include "y_absl/types/optional.h"
-
-#include <grpc/grpc.h>
-
#include "src/core/ext/filters/http/client/http_client_filter.h"
#include "src/core/ext/filters/http/message_compress/compression_filter.h"
#include "src/core/ext/filters/http/server/http_server_filter.h"
-#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_fwd.h"
#include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/config/core_configuration.h"
@@ -50,13 +45,7 @@ void RegisterHttpFilters(CoreConfiguration::Builder* builder) {
channel_type, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
[filter](ChannelStackBuilder* builder) {
if (!is_building_http_like_transport(builder)) return true;
- auto args = builder->channel_args();
- const bool enable =
- args.GetBool(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION)
- .value_or(true) ||
- args.GetBool(GRPC_ARG_ENABLE_PER_MESSAGE_COMPRESSION)
- .value_or(true);
- if (enable) builder->PrependFilter(filter);
+ builder->PrependFilter(filter);
return true;
});
};
diff --git a/contrib/libs/grpc/src/core/ext/filters/http/message_compress/compression_filter.cc b/contrib/libs/grpc/src/core/ext/filters/http/message_compress/compression_filter.cc
index 81ff6244f9..80afb64d89 100644
--- a/contrib/libs/grpc/src/core/ext/filters/http/message_compress/compression_filter.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/http/message_compress/compression_filter.cc
@@ -37,6 +37,7 @@
#include <grpc/support/log.h>
#include "src/core/ext/filters/message_size/message_size_filter.h"
+#include "src/core/lib/channel/call_tracer.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/context.h"
@@ -114,6 +115,12 @@ MessageHandle CompressionFilter::CompressMessage(
gpr_log(GPR_ERROR, "CompressMessage: len=%" PRIdPTR " alg=%d flags=%d",
message->payload()->Length(), algorithm, message->flags());
}
+ auto* call_context = GetContext<grpc_call_context_element>();
+ auto* call_tracer = static_cast<CallTracerInterface*>(
+ call_context[GRPC_CONTEXT_CALL_TRACER].value);
+ if (call_tracer != nullptr) {
+ call_tracer->RecordSendMessage(*message->payload());
+ }
// Check if we're allowed to compress this message
// (apps might want to disable compression for certain messages to avoid
// crime/beast like vulns).
@@ -144,6 +151,9 @@ MessageHandle CompressionFilter::CompressMessage(
}
tmp.Swap(payload);
flags |= GRPC_WRITE_INTERNAL_COMPRESS;
+ if (call_tracer != nullptr) {
+ call_tracer->RecordSendCompressedMessage(*message->payload());
+ }
} else {
if (GRPC_TRACE_FLAG_ENABLED(grpc_compression_trace)) {
const char* algo_name;
@@ -164,6 +174,12 @@ y_absl::StatusOr<MessageHandle> CompressionFilter::DecompressMessage(
message->payload()->Length(),
args.max_recv_message_length.value_or(-1), args.algorithm);
}
+ auto* call_context = GetContext<grpc_call_context_element>();
+ auto* call_tracer = static_cast<CallTracerInterface*>(
+ call_context[GRPC_CONTEXT_CALL_TRACER].value);
+ if (call_tracer != nullptr) {
+ call_tracer->RecordReceivedMessage(*message->payload());
+ }
// Check max message length.
if (args.max_recv_message_length.has_value() &&
message->payload()->Length() >
@@ -190,6 +206,9 @@ y_absl::StatusOr<MessageHandle> CompressionFilter::DecompressMessage(
message->payload()->Swap(&decompressed_slices);
message->mutable_flags() &= ~GRPC_WRITE_INTERNAL_COMPRESS;
message->mutable_flags() |= GRPC_WRITE_INTERNAL_TEST_ONLY_WAS_COMPRESSED;
+ if (call_tracer != nullptr) {
+ call_tracer->RecordReceivedDecompressedMessage(*message->payload());
+ }
return std::move(message);
}
@@ -234,7 +253,7 @@ ArenaPromise<ServerMetadataHandle> ClientCompressionFilter::MakeCallPromise(
return CompressMessage(std::move(message), compression_algorithm);
});
auto* decompress_args = GetContext<Arena>()->New<DecompressArgs>(
- DecompressArgs{GRPC_COMPRESS_NONE, y_absl::nullopt});
+ DecompressArgs{GRPC_COMPRESS_ALGORITHMS_COUNT, y_absl::nullopt});
auto* decompress_err =
GetContext<Arena>()->New<Latch<ServerMetadataHandle>>();
call_args.server_initial_metadata->InterceptAndMap(
@@ -255,8 +274,8 @@ ArenaPromise<ServerMetadataHandle> ClientCompressionFilter::MakeCallPromise(
return std::move(*r);
});
// Run the next filter, and race it with getting an error from decompression.
- return Race(next_promise_factory(std::move(call_args)),
- decompress_err->Wait());
+ return Race(decompress_err->Wait(),
+ next_promise_factory(std::move(call_args)));
}
ArenaPromise<ServerMetadataHandle> ServerCompressionFilter::MakeCallPromise(
@@ -270,7 +289,8 @@ ArenaPromise<ServerMetadataHandle> ServerCompressionFilter::MakeCallPromise(
this](MessageHandle message) -> y_absl::optional<MessageHandle> {
auto r = DecompressMessage(std::move(message), decompress_args);
if (grpc_call_trace.enabled()) {
- gpr_log(GPR_DEBUG, "DecompressMessage returned %s",
+ gpr_log(GPR_DEBUG, "%s[compression] DecompressMessage returned %s",
+ Activity::current()->DebugTag().c_str(),
r.status().ToString().c_str());
}
if (!r.ok()) {
@@ -296,13 +316,9 @@ ArenaPromise<ServerMetadataHandle> ServerCompressionFilter::MakeCallPromise(
this](MessageHandle message) -> y_absl::optional<MessageHandle> {
return CompressMessage(std::move(message), *compression_algorithm);
});
- // Concurrently:
- // - call the next filter
- // - decompress incoming messages
- // - wait for initial metadata to be sent, and then commence compression of
- // outgoing messages
- return Race(next_promise_factory(std::move(call_args)),
- decompress_err->Wait());
+ // Run the next filter, and race it with getting an error from decompression.
+ return Race(decompress_err->Wait(),
+ next_promise_factory(std::move(call_args)));
}
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.cc b/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.cc
index b522041518..d7039713a7 100644
--- a/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.cc
@@ -18,10 +18,14 @@
#include "src/core/ext/filters/message_size/message_size_filter.h"
+#include <inttypes.h>
+
+#include <functional>
#include <initializer_list>
-#include <new>
+#include <util/generic/string.h>
+#include <util/string/cast.h>
+#include <utility>
-#include "y_absl/status/status.h"
#include "y_absl/strings/str_format.h"
#include <grpc/grpc.h>
@@ -32,21 +36,22 @@
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/config/core_configuration.h"
-#include "src/core/lib/gprpp/debug_location.h"
-#include "src/core/lib/gprpp/status_helper.h"
-#include "src/core/lib/iomgr/call_combiner.h"
-#include "src/core/lib/iomgr/closure.h"
-#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/promise/activity.h"
+#include "src/core/lib/promise/context.h"
+#include "src/core/lib/promise/latch.h"
+#include "src/core/lib/promise/poll.h"
+#include "src/core/lib/promise/race.h"
+#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/service_config/service_config_call_data.h"
+#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_buffer.h"
+#include "src/core/lib/surface/call_trace.h"
#include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/surface/channel_stack_type.h"
+#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
-static void recv_message_ready(void* user_data, grpc_error_handle error);
-static void recv_trailing_metadata_ready(void* user_data,
- grpc_error_handle error);
-
namespace grpc_core {
//
@@ -124,251 +129,164 @@ size_t MessageSizeParser::ParserIndex() {
parser_name());
}
-} // namespace grpc_core
-
-namespace {
-struct channel_data {
- grpc_core::MessageSizeParsedConfig limits;
- const size_t service_config_parser_index{
- grpc_core::MessageSizeParser::ParserIndex()};
-};
+//
+// MessageSizeFilter
+//
-struct call_data {
- call_data(grpc_call_element* elem, const channel_data& chand,
- const grpc_call_element_args& args)
- : call_combiner(args.call_combiner), limits(chand.limits) {
- GRPC_CLOSURE_INIT(&recv_message_ready, ::recv_message_ready, elem,
- grpc_schedule_on_exec_ctx);
- GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready,
- ::recv_trailing_metadata_ready, elem,
- grpc_schedule_on_exec_ctx);
- // Get max sizes from channel data, then merge in per-method config values.
- // Note: Per-method config is only available on the client, so we
- // apply the max request size to the send limit and the max response
- // size to the receive limit.
- const grpc_core::MessageSizeParsedConfig* config_from_call_context =
- grpc_core::MessageSizeParsedConfig::GetFromCallContext(
- args.context, chand.service_config_parser_index);
- if (config_from_call_context != nullptr) {
- y_absl::optional<uint32_t> max_send_size = limits.max_send_size();
- y_absl::optional<uint32_t> max_recv_size = limits.max_recv_size();
- if (config_from_call_context->max_send_size().has_value() &&
- (!max_send_size.has_value() ||
- *config_from_call_context->max_send_size() < *max_send_size)) {
- max_send_size = *config_from_call_context->max_send_size();
+const grpc_channel_filter ClientMessageSizeFilter::kFilter =
+ MakePromiseBasedFilter<ClientMessageSizeFilter, FilterEndpoint::kClient,
+ kFilterExaminesOutboundMessages |
+ kFilterExaminesInboundMessages>("message_size");
+const grpc_channel_filter ServerMessageSizeFilter::kFilter =
+ MakePromiseBasedFilter<ServerMessageSizeFilter, FilterEndpoint::kServer,
+ kFilterExaminesOutboundMessages |
+ kFilterExaminesInboundMessages>("message_size");
+
+class MessageSizeFilter::CallBuilder {
+ private:
+ auto Interceptor(uint32_t max_length, bool is_send) {
+ return [max_length, is_send,
+ err = err_](MessageHandle msg) -> y_absl::optional<MessageHandle> {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_INFO, "%s[message_size] %s len:%" PRIdPTR " max:%d",
+ Activity::current()->DebugTag().c_str(),
+ is_send ? "send" : "recv", msg->payload()->Length(),
+ max_length);
}
- if (config_from_call_context->max_recv_size().has_value() &&
- (!max_recv_size.has_value() ||
- *config_from_call_context->max_recv_size() < *max_recv_size)) {
- max_recv_size = *config_from_call_context->max_recv_size();
+ if (msg->payload()->Length() > max_length) {
+ if (err->is_set()) return std::move(msg);
+ auto r = GetContext<Arena>()->MakePooled<ServerMetadata>(
+ GetContext<Arena>());
+ r->Set(GrpcStatusMetadata(), GRPC_STATUS_RESOURCE_EXHAUSTED);
+ r->Set(GrpcMessageMetadata(),
+ Slice::FromCopiedString(
+ y_absl::StrFormat("%s message larger than max (%u vs. %d)",
+ is_send ? "Sent" : "Received",
+ msg->payload()->Length(), max_length)));
+ err->Set(std::move(r));
+ return y_absl::nullopt;
}
- limits = grpc_core::MessageSizeParsedConfig(max_send_size, max_recv_size);
- }
+ return std::move(msg);
+ };
}
- ~call_data() {}
-
- grpc_core::CallCombiner* call_combiner;
- grpc_core::MessageSizeParsedConfig limits;
- // Receive closures are chained: we inject this closure as the
- // recv_message_ready up-call on transport_stream_op, and remember to
- // call our next_recv_message_ready member after handling it.
- grpc_closure recv_message_ready;
- grpc_closure recv_trailing_metadata_ready;
- // The error caused by a message that is too large, or y_absl::OkStatus()
- grpc_error_handle error;
- // Used by recv_message_ready.
- y_absl::optional<grpc_core::SliceBuffer>* recv_message = nullptr;
- // Original recv_message_ready callback, invoked after our own.
- grpc_closure* next_recv_message_ready = nullptr;
- // Original recv_trailing_metadata callback, invoked after our own.
- grpc_closure* original_recv_trailing_metadata_ready;
- bool seen_recv_trailing_metadata = false;
- grpc_error_handle recv_trailing_metadata_error;
-};
-
-} // namespace
+ public:
+ explicit CallBuilder(const MessageSizeParsedConfig& limits)
+ : limits_(limits) {}
-// Callback invoked when we receive a message. Here we check the max
-// receive message size.
-static void recv_message_ready(void* user_data, grpc_error_handle error) {
- grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
- call_data* calld = static_cast<call_data*>(elem->call_data);
- if (calld->recv_message->has_value() &&
- calld->limits.max_recv_size().has_value() &&
- (*calld->recv_message)->Length() >
- static_cast<size_t>(*calld->limits.max_recv_size())) {
- grpc_error_handle new_error = grpc_error_set_int(
- GRPC_ERROR_CREATE(y_absl::StrFormat(
- "Received message larger than max (%u vs. %d)",
- (*calld->recv_message)->Length(), *calld->limits.max_recv_size())),
- grpc_core::StatusIntProperty::kRpcStatus,
- GRPC_STATUS_RESOURCE_EXHAUSTED);
- error = grpc_error_add_child(error, new_error);
- calld->error = error;
+ template <typename T>
+ void AddSend(T* pipe_end) {
+ if (!limits_.max_send_size().has_value()) return;
+ pipe_end->InterceptAndMap(Interceptor(*limits_.max_send_size(), true));
}
- // Invoke the next callback.
- grpc_closure* closure = calld->next_recv_message_ready;
- calld->next_recv_message_ready = nullptr;
- if (calld->seen_recv_trailing_metadata) {
- // We might potentially see another RECV_MESSAGE op. In that case, we do not
- // want to run the recv_trailing_metadata_ready closure again. The newer
- // RECV_MESSAGE op cannot cause any errors since the transport has already
- // invoked the recv_trailing_metadata_ready closure and all further
- // RECV_MESSAGE ops will get null payloads.
- calld->seen_recv_trailing_metadata = false;
- GRPC_CALL_COMBINER_START(calld->call_combiner,
- &calld->recv_trailing_metadata_ready,
- calld->recv_trailing_metadata_error,
- "continue recv_trailing_metadata_ready");
+ template <typename T>
+ void AddRecv(T* pipe_end) {
+ if (!limits_.max_recv_size().has_value()) return;
+ pipe_end->InterceptAndMap(Interceptor(*limits_.max_recv_size(), false));
}
- grpc_core::Closure::Run(DEBUG_LOCATION, closure, error);
-}
-// Callback invoked on completion of recv_trailing_metadata
-// Notifies the recv_trailing_metadata batch of any message size failures
-static void recv_trailing_metadata_ready(void* user_data,
- grpc_error_handle error) {
- grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
- call_data* calld = static_cast<call_data*>(elem->call_data);
- if (calld->next_recv_message_ready != nullptr) {
- calld->seen_recv_trailing_metadata = true;
- calld->recv_trailing_metadata_error = error;
- GRPC_CALL_COMBINER_STOP(calld->call_combiner,
- "deferring recv_trailing_metadata_ready until "
- "after recv_message_ready");
- return;
+ ArenaPromise<ServerMetadataHandle> Run(
+ CallArgs call_args, NextPromiseFactory next_promise_factory) {
+ return Race(err_->Wait(), next_promise_factory(std::move(call_args)));
}
- error = grpc_error_add_child(error, calld->error);
- // Invoke the next callback.
- grpc_core::Closure::Run(DEBUG_LOCATION,
- calld->original_recv_trailing_metadata_ready, error);
-}
-// Start transport stream op.
-static void message_size_start_transport_stream_op_batch(
- grpc_call_element* elem, grpc_transport_stream_op_batch* op) {
- call_data* calld = static_cast<call_data*>(elem->call_data);
- // Check max send message size.
- if (op->send_message && calld->limits.max_send_size().has_value() &&
- op->payload->send_message.send_message->Length() >
- static_cast<size_t>(*calld->limits.max_send_size())) {
- grpc_transport_stream_op_batch_finish_with_failure(
- op,
- grpc_error_set_int(GRPC_ERROR_CREATE(y_absl::StrFormat(
- "Sent message larger than max (%u vs. %d)",
- op->payload->send_message.send_message->Length(),
- *calld->limits.max_send_size())),
- grpc_core::StatusIntProperty::kRpcStatus,
- GRPC_STATUS_RESOURCE_EXHAUSTED),
- calld->call_combiner);
- return;
- }
- // Inject callback for receiving a message.
- if (op->recv_message) {
- calld->next_recv_message_ready =
- op->payload->recv_message.recv_message_ready;
- calld->recv_message = op->payload->recv_message.recv_message;
- op->payload->recv_message.recv_message_ready = &calld->recv_message_ready;
- }
- // Inject callback for receiving trailing metadata.
- if (op->recv_trailing_metadata) {
- calld->original_recv_trailing_metadata_ready =
- op->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
- op->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
- &calld->recv_trailing_metadata_ready;
- }
- // Chain to the next filter.
- grpc_call_next_op(elem, op);
-}
+ private:
+ Latch<ServerMetadataHandle>* const err_ =
+ GetContext<Arena>()->ManagedNew<Latch<ServerMetadataHandle>>();
+ MessageSizeParsedConfig limits_;
+};
-// Constructor for call_data.
-static grpc_error_handle message_size_init_call_elem(
- grpc_call_element* elem, const grpc_call_element_args* args) {
- channel_data* chand = static_cast<channel_data*>(elem->channel_data);
- new (elem->call_data) call_data(elem, *chand, *args);
- return y_absl::OkStatus();
+y_absl::StatusOr<ClientMessageSizeFilter> ClientMessageSizeFilter::Create(
+ const ChannelArgs& args, ChannelFilter::Args) {
+ return ClientMessageSizeFilter(args);
}
-// Destructor for call_data.
-static void message_size_destroy_call_elem(
- grpc_call_element* elem, const grpc_call_final_info* /*final_info*/,
- grpc_closure* /*ignored*/) {
- call_data* calld = static_cast<call_data*>(elem->call_data);
- calld->~call_data();
+y_absl::StatusOr<ServerMessageSizeFilter> ServerMessageSizeFilter::Create(
+ const ChannelArgs& args, ChannelFilter::Args) {
+ return ServerMessageSizeFilter(args);
}
-// Constructor for channel_data.
-static grpc_error_handle message_size_init_channel_elem(
- grpc_channel_element* elem, grpc_channel_element_args* args) {
- GPR_ASSERT(!args->is_last);
- channel_data* chand = static_cast<channel_data*>(elem->channel_data);
- new (chand) channel_data();
- chand->limits = grpc_core::MessageSizeParsedConfig::GetFromChannelArgs(
- args->channel_args);
- return y_absl::OkStatus();
-}
+ArenaPromise<ServerMetadataHandle> ClientMessageSizeFilter::MakeCallPromise(
+ CallArgs call_args, NextPromiseFactory next_promise_factory) {
+ // Get max sizes from channel data, then merge in per-method config values.
+ // Note: Per-method config is only available on the client, so we
+ // apply the max request size to the send limit and the max response
+ // size to the receive limit.
+ MessageSizeParsedConfig limits = this->limits();
+ const MessageSizeParsedConfig* config_from_call_context =
+ MessageSizeParsedConfig::GetFromCallContext(
+ GetContext<grpc_call_context_element>(),
+ service_config_parser_index_);
+ if (config_from_call_context != nullptr) {
+ y_absl::optional<uint32_t> max_send_size = limits.max_send_size();
+ y_absl::optional<uint32_t> max_recv_size = limits.max_recv_size();
+ if (config_from_call_context->max_send_size().has_value() &&
+ (!max_send_size.has_value() ||
+ *config_from_call_context->max_send_size() < *max_send_size)) {
+ max_send_size = *config_from_call_context->max_send_size();
+ }
+ if (config_from_call_context->max_recv_size().has_value() &&
+ (!max_recv_size.has_value() ||
+ *config_from_call_context->max_recv_size() < *max_recv_size)) {
+ max_recv_size = *config_from_call_context->max_recv_size();
+ }
+ limits = MessageSizeParsedConfig(max_send_size, max_recv_size);
+ }
-// Destructor for channel_data.
-static void message_size_destroy_channel_elem(grpc_channel_element* elem) {
- channel_data* chand = static_cast<channel_data*>(elem->channel_data);
- chand->~channel_data();
+ CallBuilder b(limits);
+ b.AddSend(call_args.client_to_server_messages);
+ b.AddRecv(call_args.server_to_client_messages);
+ return b.Run(std::move(call_args), std::move(next_promise_factory));
}
-const grpc_channel_filter grpc_message_size_filter = {
- message_size_start_transport_stream_op_batch,
- nullptr,
- grpc_channel_next_op,
- sizeof(call_data),
- message_size_init_call_elem,
- grpc_call_stack_ignore_set_pollset_or_pollset_set,
- message_size_destroy_call_elem,
- sizeof(channel_data),
- message_size_init_channel_elem,
- grpc_channel_stack_no_post_init,
- message_size_destroy_channel_elem,
- grpc_channel_next_get_info,
- "message_size"};
+ArenaPromise<ServerMetadataHandle> ServerMessageSizeFilter::MakeCallPromise(
+ CallArgs call_args, NextPromiseFactory next_promise_factory) {
+ CallBuilder b(limits());
+ b.AddSend(call_args.server_to_client_messages);
+ b.AddRecv(call_args.client_to_server_messages);
+ return b.Run(std::move(call_args), std::move(next_promise_factory));
+}
+namespace {
// Used for GRPC_CLIENT_SUBCHANNEL
-static bool maybe_add_message_size_filter_subchannel(
- grpc_core::ChannelStackBuilder* builder) {
+bool MaybeAddMessageSizeFilterToSubchannel(ChannelStackBuilder* builder) {
if (builder->channel_args().WantMinimalStack()) {
return true;
}
- builder->PrependFilter(&grpc_message_size_filter);
+ builder->PrependFilter(&ClientMessageSizeFilter::kFilter);
return true;
}
-// Used for GRPC_CLIENT_DIRECT_CHANNEL and GRPC_SERVER_CHANNEL. Adds the filter
-// only if message size limits or service config is specified.
-static bool maybe_add_message_size_filter(
- grpc_core::ChannelStackBuilder* builder) {
- auto channel_args = builder->channel_args();
- if (channel_args.WantMinimalStack()) {
+// Used for GRPC_CLIENT_DIRECT_CHANNEL and GRPC_SERVER_CHANNEL. Adds the
+// filter only if message size limits or service config is specified.
+auto MaybeAddMessageSizeFilter(const grpc_channel_filter* filter) {
+ return [filter](ChannelStackBuilder* builder) {
+ auto channel_args = builder->channel_args();
+ if (channel_args.WantMinimalStack()) {
+ return true;
+ }
+ MessageSizeParsedConfig limits =
+ MessageSizeParsedConfig::GetFromChannelArgs(channel_args);
+ const bool enable =
+ limits.max_send_size().has_value() ||
+ limits.max_recv_size().has_value() ||
+ channel_args.GetString(GRPC_ARG_SERVICE_CONFIG).has_value();
+ if (enable) builder->PrependFilter(filter);
return true;
- }
- grpc_core::MessageSizeParsedConfig limits =
- grpc_core::MessageSizeParsedConfig::GetFromChannelArgs(channel_args);
- const bool enable =
- limits.max_send_size().has_value() ||
- limits.max_recv_size().has_value() ||
- channel_args.GetString(GRPC_ARG_SERVICE_CONFIG).has_value();
- if (enable) builder->PrependFilter(&grpc_message_size_filter);
- return true;
+ };
}
-namespace grpc_core {
+} // namespace
void RegisterMessageSizeFilter(CoreConfiguration::Builder* builder) {
MessageSizeParser::Register(builder);
- builder->channel_init()->RegisterStage(
- GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
- maybe_add_message_size_filter_subchannel);
- builder->channel_init()->RegisterStage(GRPC_CLIENT_DIRECT_CHANNEL,
- GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
- maybe_add_message_size_filter);
- builder->channel_init()->RegisterStage(GRPC_SERVER_CHANNEL,
+ builder->channel_init()->RegisterStage(GRPC_CLIENT_SUBCHANNEL,
GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
- maybe_add_message_size_filter);
+ MaybeAddMessageSizeFilterToSubchannel);
+ builder->channel_init()->RegisterStage(
+ GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ MaybeAddMessageSizeFilter(&ClientMessageSizeFilter::kFilter));
+ builder->channel_init()->RegisterStage(
+ GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ MaybeAddMessageSizeFilter(&ServerMessageSizeFilter::kFilter));
}
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.h b/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.h
index 70201da402..0b8390fbc1 100644
--- a/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.h
+++ b/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.h
@@ -24,21 +24,22 @@
#include <memory>
+#include "y_absl/status/statusor.h"
#include "y_absl/strings/string_view.h"
#include "y_absl/types/optional.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_fwd.h"
-#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/context.h"
+#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/gprpp/validation_errors.h"
#include "src/core/lib/json/json.h"
#include "src/core/lib/json/json_args.h"
#include "src/core/lib/json/json_object_loader.h"
+#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/service_config/service_config_parser.h"
-
-extern const grpc_channel_filter grpc_message_size_filter;
+#include "src/core/lib/transport/transport.h"
namespace grpc_core {
@@ -85,6 +86,50 @@ class MessageSizeParser : public ServiceConfigParser::Parser {
y_absl::optional<uint32_t> GetMaxRecvSizeFromChannelArgs(const ChannelArgs& args);
y_absl::optional<uint32_t> GetMaxSendSizeFromChannelArgs(const ChannelArgs& args);
+class MessageSizeFilter : public ChannelFilter {
+ protected:
+ explicit MessageSizeFilter(const ChannelArgs& args)
+ : limits_(MessageSizeParsedConfig::GetFromChannelArgs(args)) {}
+
+ class CallBuilder;
+
+ const MessageSizeParsedConfig& limits() const { return limits_; }
+
+ private:
+ MessageSizeParsedConfig limits_;
+};
+
+class ServerMessageSizeFilter final : public MessageSizeFilter {
+ public:
+ static const grpc_channel_filter kFilter;
+
+ static y_absl::StatusOr<ServerMessageSizeFilter> Create(
+ const ChannelArgs& args, ChannelFilter::Args filter_args);
+
+ // Construct a promise for one call.
+ ArenaPromise<ServerMetadataHandle> MakeCallPromise(
+ CallArgs call_args, NextPromiseFactory next_promise_factory) override;
+
+ private:
+ using MessageSizeFilter::MessageSizeFilter;
+};
+
+class ClientMessageSizeFilter final : public MessageSizeFilter {
+ public:
+ static const grpc_channel_filter kFilter;
+
+ static y_absl::StatusOr<ClientMessageSizeFilter> Create(
+ const ChannelArgs& args, ChannelFilter::Args filter_args);
+
+ // Construct a promise for one call.
+ ArenaPromise<ServerMetadataHandle> MakeCallPromise(
+ CallArgs call_args, NextPromiseFactory next_promise_factory) override;
+
+ private:
+ const size_t service_config_parser_index_{MessageSizeParser::ParserIndex()};
+ using MessageSizeFilter::MessageSizeFilter;
+};
+
} // namespace grpc_core
#endif // GRPC_SRC_CORE_EXT_FILTERS_MESSAGE_SIZE_MESSAGE_SIZE_FILTER_H
diff --git a/contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_filter.cc b/contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_filter.cc
index 8ba2d8e3ef..b8fb277d73 100644
--- a/contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_filter.cc
+++ b/contrib/libs/grpc/src/core/ext/filters/stateful_session/stateful_session_filter.cc
@@ -90,13 +90,14 @@ void MaybeUpdateServerInitialMetadata(
y_absl::optional<y_absl::string_view> cookie_value,
ServerMetadata* server_initial_metadata) {
// Get peer string.
- auto peer_string = server_initial_metadata->get(PeerString());
- if (!peer_string.has_value()) return; // Nothing we can do.
+ Slice* peer_string = server_initial_metadata->get_pointer(PeerString());
+ if (peer_string == nullptr) return; // Nothing we can do.
// If there was no cookie or if the address changed, set the cookie.
- if (!cookie_value.has_value() || *peer_string != *cookie_value) {
- std::vector<TString> parts = {
- y_absl::StrCat(*cookie_config->name, "=",
- y_absl::Base64Escape(*peer_string), "; HttpOnly")};
+ if (!cookie_value.has_value() ||
+ peer_string->as_string_view() != *cookie_value) {
+ std::vector<TString> parts = {y_absl::StrCat(
+ *cookie_config->name, "=",
+ y_absl::Base64Escape(peer_string->as_string_view()), "; HttpOnly")};
if (!cookie_config->path.empty()) {
parts.emplace_back(y_absl::StrCat("Path=", cookie_config->path));
}
diff --git a/contrib/libs/grpc/src/core/ext/gcp/metadata_query.cc b/contrib/libs/grpc/src/core/ext/gcp/metadata_query.cc
new file mode 100644
index 0000000000..e1d739db68
--- /dev/null
+++ b/contrib/libs/grpc/src/core/ext/gcp/metadata_query.cc
@@ -0,0 +1,137 @@
+//
+//
+// Copyright 2023 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/ext/gcp/metadata_query.h"
+
+#include <string.h>
+
+#include <initializer_list>
+#include <memory>
+#include <utility>
+
+#include "y_absl/status/status.h"
+#include "y_absl/status/statusor.h"
+#include "y_absl/strings/str_format.h"
+#include "y_absl/strings/string_view.h"
+
+#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/gprpp/status_helper.h"
+#include "src/core/lib/gprpp/time.h"
+#include "src/core/lib/security/credentials/credentials.h"
+#include "src/core/lib/uri/uri_parser.h"
+
+namespace grpc_core {
+
+TraceFlag grpc_metadata_query_trace(false, "metadata_query");
+
+constexpr const char MetadataQuery::kZoneAttribute[];
+constexpr const char MetadataQuery::kClusterNameAttribute[];
+constexpr const char MetadataQuery::kRegionAttribute[];
+constexpr const char MetadataQuery::kInstanceIdAttribute[];
+constexpr const char MetadataQuery::kIPv6Attribute[];
+
+MetadataQuery::MetadataQuery(
+ TString attribute, grpc_polling_entity* pollent,
+ y_absl::AnyInvocable<void(TString /* attribute */,
+ y_absl::StatusOr<TString> /* result */)>
+ callback,
+ Duration timeout)
+ : MetadataQuery("metadata.google.internal.", std::move(attribute), pollent,
+ std::move(callback), timeout) {}
+
+MetadataQuery::MetadataQuery(
+ TString metadata_server_name, TString attribute,
+ grpc_polling_entity* pollent,
+ y_absl::AnyInvocable<void(TString /* attribute */,
+ y_absl::StatusOr<TString> /* result */)>
+ callback,
+ Duration timeout)
+ : InternallyRefCounted<MetadataQuery>(nullptr, 2),
+ attribute_(std::move(attribute)),
+ callback_(std::move(callback)) {
+ GRPC_CLOSURE_INIT(&on_done_, OnDone, this, nullptr);
+ auto uri = URI::Create("http", std::move(metadata_server_name), attribute_,
+ {} /* query params */, "" /* fragment */);
+ GPR_ASSERT(uri.ok()); // params are hardcoded
+ grpc_http_request request;
+ memset(&request, 0, sizeof(grpc_http_request));
+ grpc_http_header header = {const_cast<char*>("Metadata-Flavor"),
+ const_cast<char*>("Google")};
+ request.hdr_count = 1;
+ request.hdrs = &header;
+ http_request_ = HttpRequest::Get(
+ std::move(*uri), nullptr /* channel args */, pollent, &request,
+ Timestamp::Now() + timeout, &on_done_, &response_,
+ RefCountedPtr<grpc_channel_credentials>(
+ grpc_insecure_credentials_create()));
+ http_request_->Start();
+}
+
+MetadataQuery::~MetadataQuery() { grpc_http_response_destroy(&response_); }
+
+void MetadataQuery::Orphan() {
+ http_request_.reset();
+ Unref();
+}
+
+void MetadataQuery::OnDone(void* arg, grpc_error_handle error) {
+ auto* self = static_cast<MetadataQuery*>(arg);
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_metadata_query_trace)) {
+ gpr_log(GPR_INFO, "MetadataServer Query for %s: HTTP status: %d, error: %s",
+ self->attribute_.c_str(), self->response_.status,
+ StatusToString(error).c_str());
+ }
+ y_absl::StatusOr<TString> result;
+ if (!error.ok()) {
+ result = y_absl::UnavailableError(y_absl::StrFormat(
+ "MetadataServer Query failed for %s: %s", self->attribute_.c_str(),
+ StatusToString(error).c_str()));
+ } else if (self->response_.status != 200) {
+ result = y_absl::UnavailableError(y_absl::StrFormat(
+ "MetadataServer Query received non-200 status for %s: %s",
+ self->attribute_.c_str(), StatusToString(error).c_str()));
+ } else if (self->attribute_ == kZoneAttribute) {
+ y_absl::string_view body(self->response_.body, self->response_.body_length);
+ size_t pos = body.find_last_of('/');
+ if (pos == body.npos) {
+ result = y_absl::UnavailableError(
+ y_absl::StrFormat("MetadataServer Could not parse zone: %s",
+ TString(body).c_str()));
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_metadata_query_trace)) {
+ gpr_log(GPR_INFO, "%s", result.status().ToString().c_str());
+ }
+ } else {
+ result = TString(body.substr(pos + 1));
+ }
+ } else {
+ result = TString(self->response_.body, self->response_.body_length);
+ }
+ auto callback = std::move(self->callback_);
+ auto attribute = std::move(self->attribute_);
+ self->Unref();
+ return callback(std::move(attribute), std::move(result));
+}
+
+} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/ext/gcp/metadata_query.h b/contrib/libs/grpc/src/core/ext/gcp/metadata_query.h
new file mode 100644
index 0000000000..85d2f8415d
--- /dev/null
+++ b/contrib/libs/grpc/src/core/ext/gcp/metadata_query.h
@@ -0,0 +1,88 @@
+//
+// Copyright 2023 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GRPC_SRC_CORE_EXT_GCP_METADATA_QUERY_H
+#define GRPC_SRC_CORE_EXT_GCP_METADATA_QUERY_H
+
+#include <grpc/support/port_platform.h>
+
+#include <util/generic/string.h>
+#include <util/string/cast.h>
+
+#include "y_absl/functional/any_invocable.h"
+#include "y_absl/status/statusor.h"
+
+#include "src/core/lib/gprpp/orphanable.h"
+#include "src/core/lib/gprpp/time.h"
+#include "src/core/lib/http/httpcli.h"
+#include "src/core/lib/http/parser.h"
+#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/iomgr/polling_entity.h"
+
+namespace grpc_core {
+
+// Fetches the value of an attribute from the MetadataServer on a GCP
+// environment.
+class MetadataQuery : public InternallyRefCounted<MetadataQuery> {
+ public:
+ static constexpr const char kZoneAttribute[] =
+ "/computeMetadata/v1/instance/zone";
+ static constexpr const char kClusterNameAttribute[] =
+ "/computeMetadata/v1/instance/attributes/cluster-name";
+ static constexpr const char kRegionAttribute[] =
+ "/computeMetadata/v1/instance/region";
+ static constexpr const char kInstanceIdAttribute[] =
+ "/computeMetadata/v1/instance/id";
+ static constexpr const char kIPv6Attribute[] =
+ "/computeMetadata/v1/instance/network-interfaces/0/ipv6s";
+
+ MetadataQuery(
+ TString attribute, grpc_polling_entity* pollent,
+ y_absl::AnyInvocable<void(TString /* attribute */,
+ y_absl::StatusOr<TString> /* result */)>
+ callback,
+ Duration timeout);
+
+ // Alternative ctor allows overriding the metadata server address, mainly
+ // to inject fakes in tests
+ MetadataQuery(
+ TString metadata_server_name, TString attribute,
+ grpc_polling_entity* pollent,
+ y_absl::AnyInvocable<void(TString /* attribute */,
+ y_absl::StatusOr<TString> /* result */)>
+ callback,
+ Duration timeout);
+
+ ~MetadataQuery() override;
+
+ void Orphan() override;
+
+ private:
+ static void OnDone(void* arg, grpc_error_handle error);
+
+ grpc_closure on_done_;
+ TString attribute_;
+ y_absl::AnyInvocable<void(TString /* attribute */,
+ y_absl::StatusOr<TString> /* result */)>
+ callback_;
+ OrphanablePtr<HttpRequest> http_request_;
+ grpc_http_response response_;
+};
+
+} // namespace grpc_core
+
+#endif // GRPC_SRC_CORE_EXT_GCP_METADATA_QUERY_H
diff --git a/contrib/libs/grpc/src/core/ext/transport/binder/transport/binder_transport.cc b/contrib/libs/grpc/src/core/ext/transport/binder/transport/binder_transport.cc
index 856e7172bb..7ae03cc981 100644
--- a/contrib/libs/grpc/src/core/ext/transport/binder/transport/binder_transport.cc
+++ b/contrib/libs/grpc/src/core/ext/transport/binder/transport/binder_transport.cc
@@ -695,6 +695,7 @@ static grpc_endpoint* get_endpoint(grpc_transport*) {
// See grpc_transport_vtable declaration for meaning of each field
static const grpc_transport_vtable vtable = {sizeof(grpc_binder_stream),
+ false,
"binder",
init_stream,
nullptr,
diff --git a/contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.cc b/contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
index 3fa43e688d..5aac42eb27 100644
--- a/contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
+++ b/contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
@@ -25,6 +25,7 @@
#include <utility>
#include <vector>
+#include "y_absl/functional/any_invocable.h"
#include "y_absl/memory/memory.h"
#include "y_absl/status/statusor.h"
@@ -249,40 +250,24 @@ y_absl::Status WireReaderImpl::ProcessStreamingTransaction(
transaction_code_t code, ReadableParcel* parcel) {
bool need_to_send_ack = false;
int64_t num_bytes = 0;
+ // Indicates which callbacks should be cancelled. It will be initialized as
+ // the flags the in-coming transaction carries, and when a particular
+ // callback is completed, the corresponding bit in cancellation_flag will be
+ // set to 0 so that we won't cancel it afterward.
+ int cancellation_flags = 0;
+ // The queue saves the actions needed to be done "WITHOUT" `mu_`.
+ // It prevents deadlock against wire writer issues.
+ std::queue<y_absl::AnyInvocable<void() &&>> deferred_func_queue;
y_absl::Status tx_process_result;
+
{
grpc_core::MutexLock lock(&mu_);
if (!connected_) {
return y_absl::InvalidArgumentError("Transports not connected yet");
}
- // Indicate which callbacks should be cancelled. It will be initialized as
- // the flags the in-coming transaction carries, and when a particular
- // callback is completed, the corresponding bit in cancellation_flag will be
- // set to 0 so that we won't cancel it afterward.
- int cancellation_flags = 0;
- tx_process_result =
- ProcessStreamingTransactionImpl(code, parcel, &cancellation_flags);
- if (!tx_process_result.ok()) {
- gpr_log(GPR_ERROR, "Failed to process streaming transaction: %s",
- tx_process_result.ToString().c_str());
- // Something went wrong when receiving transaction. Cancel failed
- // requests.
- if (cancellation_flags & kFlagPrefix) {
- gpr_log(GPR_INFO, "cancelling initial metadata");
- transport_stream_receiver_->NotifyRecvInitialMetadata(
- code, tx_process_result);
- }
- if (cancellation_flags & kFlagMessageData) {
- gpr_log(GPR_INFO, "cancelling message data");
- transport_stream_receiver_->NotifyRecvMessage(code, tx_process_result);
- }
- if (cancellation_flags & kFlagSuffix) {
- gpr_log(GPR_INFO, "cancelling trailing metadata");
- transport_stream_receiver_->NotifyRecvTrailingMetadata(
- code, tx_process_result, 0);
- }
- }
+ tx_process_result = ProcessStreamingTransactionImpl(
+ code, parcel, &cancellation_flags, deferred_func_queue);
if ((num_incoming_bytes_ - num_acknowledged_bytes_) >=
kFlowControlAckBytes) {
need_to_send_ack = true;
@@ -290,6 +275,32 @@ y_absl::Status WireReaderImpl::ProcessStreamingTransaction(
num_acknowledged_bytes_ = num_incoming_bytes_;
}
}
+ // Executes all actions in the queue.
+ while (!deferred_func_queue.empty()) {
+ std::move(deferred_func_queue.front())();
+ deferred_func_queue.pop();
+ }
+
+ if (!tx_process_result.ok()) {
+ gpr_log(GPR_ERROR, "Failed to process streaming transaction: %s",
+ tx_process_result.ToString().c_str());
+ // Something went wrong when receiving transaction. Cancel failed requests.
+ if (cancellation_flags & kFlagPrefix) {
+ gpr_log(GPR_INFO, "cancelling initial metadata");
+ transport_stream_receiver_->NotifyRecvInitialMetadata(code,
+ tx_process_result);
+ }
+ if (cancellation_flags & kFlagMessageData) {
+ gpr_log(GPR_INFO, "cancelling message data");
+ transport_stream_receiver_->NotifyRecvMessage(code, tx_process_result);
+ }
+ if (cancellation_flags & kFlagSuffix) {
+ gpr_log(GPR_INFO, "cancelling trailing metadata");
+ transport_stream_receiver_->NotifyRecvTrailingMetadata(
+ code, tx_process_result, 0);
+ }
+ }
+
if (need_to_send_ack) {
if (!wire_writer_ready_notification_.WaitForNotificationWithTimeout(
y_absl::Seconds(5))) {
@@ -311,7 +322,8 @@ y_absl::Status WireReaderImpl::ProcessStreamingTransaction(
}
y_absl::Status WireReaderImpl::ProcessStreamingTransactionImpl(
- transaction_code_t code, ReadableParcel* parcel, int* cancellation_flags) {
+ transaction_code_t code, ReadableParcel* parcel, int* cancellation_flags,
+ std::queue<y_absl::AnyInvocable<void() &&>>& deferred_func_queue) {
GPR_ASSERT(cancellation_flags);
num_incoming_bytes_ += parcel->GetDataSize();
gpr_log(GPR_INFO, "Total incoming bytes: %" PRId64, num_incoming_bytes_);
@@ -381,8 +393,12 @@ y_absl::Status WireReaderImpl::ProcessStreamingTransactionImpl(
"binder.authority");
}
}
- transport_stream_receiver_->NotifyRecvInitialMetadata(
- code, *initial_metadata_or_error);
+ deferred_func_queue.emplace([this, code,
+ initial_metadata_or_error = std::move(
+ initial_metadata_or_error)]() mutable {
+ this->transport_stream_receiver_->NotifyRecvInitialMetadata(
+ code, std::move(initial_metadata_or_error));
+ });
*cancellation_flags &= ~kFlagPrefix;
}
if (flags & kFlagMessageData) {
@@ -397,7 +413,9 @@ y_absl::Status WireReaderImpl::ProcessStreamingTransactionImpl(
if ((flags & kFlagMessageDataIsPartial) == 0) {
TString s = std::move(message_buffer_[code]);
message_buffer_.erase(code);
- transport_stream_receiver_->NotifyRecvMessage(code, std::move(s));
+ deferred_func_queue.emplace([this, code, s = std::move(s)]() mutable {
+ this->transport_stream_receiver_->NotifyRecvMessage(code, std::move(s));
+ });
}
*cancellation_flags &= ~kFlagMessageData;
}
@@ -417,8 +435,12 @@ y_absl::Status WireReaderImpl::ProcessStreamingTransactionImpl(
}
trailing_metadata = *trailing_metadata_or_error;
}
- transport_stream_receiver_->NotifyRecvTrailingMetadata(
- code, std::move(trailing_metadata), status);
+ deferred_func_queue.emplace(
+ [this, code, trailing_metadata = std::move(trailing_metadata),
+ status]() mutable {
+ this->transport_stream_receiver_->NotifyRecvTrailingMetadata(
+ code, std::move(trailing_metadata), status);
+ });
*cancellation_flags &= ~kFlagSuffix;
}
return y_absl::OkStatus();
diff --git a/contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.h b/contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.h
index 62f1fd6ebd..9116a55469 100644
--- a/contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.h
+++ b/contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.h
@@ -18,9 +18,11 @@
#include <grpc/support/port_platform.h>
#include <memory>
+#include <queue>
#include <utility>
#include "y_absl/container/flat_hash_map.h"
+#include "y_absl/functional/any_invocable.h"
#include <grpcpp/security/binder_security_policy.h>
@@ -99,9 +101,11 @@ class WireReaderImpl : public WireReader {
private:
y_absl::Status ProcessStreamingTransaction(transaction_code_t code,
ReadableParcel* parcel);
- y_absl::Status ProcessStreamingTransactionImpl(transaction_code_t code,
- ReadableParcel* parcel,
- int* cancellation_flags)
+ y_absl::Status ProcessStreamingTransactionImpl(
+ transaction_code_t code, ReadableParcel* parcel, int* cancellation_flags,
+ // The queue saves the actions needed to be done "WITHOUT" `mu_`.
+ // It prevents deadlock against wire writer issues.
+ std::queue<y_absl::AnyInvocable<void() &&>>& deferred_func_queue)
Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
std::shared_ptr<TransportStreamReceiver> transport_stream_receiver_;
diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc
index 77313f40f2..2b78e7a0a1 100644
--- a/contrib/libs/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc
+++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc
@@ -41,6 +41,7 @@
#include "y_absl/strings/strip.h"
#include "y_absl/types/optional.h"
+#include <grpc/event_engine/event_engine.h>
#include <grpc/grpc.h>
#include <grpc/grpc_posix.h>
#include <grpc/slice_buffer.h>
@@ -70,7 +71,6 @@
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/resolved_address.h"
#include "src/core/lib/iomgr/tcp_server.h"
-#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/resource_quota/memory_quota.h"
#include "src/core/lib/resource_quota/resource_quota.h"
@@ -95,6 +95,8 @@
namespace grpc_core {
namespace {
+using ::grpc_event_engine::experimental::EventEngine;
+
const char kUnixUriPrefix[] = "unix:";
const char kUnixAbstractUriPrefix[] = "unix-abstract:";
@@ -162,7 +164,7 @@ class Chttp2ServerListener : public Server::ListenerInterface {
using InternallyRefCounted<HandshakingState>::Ref;
private:
- static void OnTimeout(void* arg, grpc_error_handle error);
+ void OnTimeout() Y_ABSL_LOCKS_EXCLUDED(&connection_->mu_);
static void OnReceiveSettings(void* arg, grpc_error_handle /* error */);
static void OnHandshakeDone(void* arg, grpc_error_handle error);
RefCountedPtr<ActiveConnection> const connection_;
@@ -172,15 +174,16 @@ class Chttp2ServerListener : public Server::ListenerInterface {
Y_ABSL_GUARDED_BY(&connection_->mu_);
// State for enforcing handshake timeout on receiving HTTP/2 settings.
Timestamp const deadline_;
- grpc_timer timer_ Y_ABSL_GUARDED_BY(&connection_->mu_);
- grpc_closure on_timeout_ Y_ABSL_GUARDED_BY(&connection_->mu_);
+ y_absl::optional<EventEngine::TaskHandle> timer_handle_
+ Y_ABSL_GUARDED_BY(&connection_->mu_);
grpc_closure on_receive_settings_ Y_ABSL_GUARDED_BY(&connection_->mu_);
grpc_pollset_set* const interested_parties_;
};
ActiveConnection(grpc_pollset* accepting_pollset,
grpc_tcp_server_acceptor* acceptor,
- const ChannelArgs& args, MemoryOwner memory_owner);
+ EventEngine* event_engine, const ChannelArgs& args,
+ MemoryOwner memory_owner);
~ActiveConnection() override;
void Orphan() override;
@@ -196,7 +199,7 @@ class Chttp2ServerListener : public Server::ListenerInterface {
private:
static void OnClose(void* arg, grpc_error_handle error);
- static void OnDrainGraceTimeExpiry(void* arg, grpc_error_handle error);
+ void OnDrainGraceTimeExpiry() Y_ABSL_LOCKS_EXCLUDED(&mu_);
RefCountedPtr<Chttp2ServerListener> listener_;
Mutex mu_ Y_ABSL_ACQUIRED_AFTER(&listener_->mu_);
@@ -207,10 +210,11 @@ class Chttp2ServerListener : public Server::ListenerInterface {
// is created.
grpc_chttp2_transport* transport_ Y_ABSL_GUARDED_BY(&mu_) = nullptr;
grpc_closure on_close_;
- grpc_timer drain_grace_timer_;
- grpc_closure on_drain_grace_time_expiry_;
- bool drain_grace_timer_expiry_callback_pending_ Y_ABSL_GUARDED_BY(&mu_) =
- false;
+ y_absl::optional<EventEngine::TaskHandle> drain_grace_timer_handle_
+ Y_ABSL_GUARDED_BY(&mu_);
+ // Use a raw pointer since this event_engine_ is grabbed from the
+ // ChannelArgs of the listener_.
+ EventEngine* const event_engine_ Y_ABSL_GUARDED_BY(&mu_);
bool shutdown_ Y_ABSL_GUARDED_BY(&mu_) = false;
};
@@ -409,29 +413,33 @@ void Chttp2ServerListener::ActiveConnection::HandshakingState::Start(
OnHandshakeDone, this);
}
-void Chttp2ServerListener::ActiveConnection::HandshakingState::OnTimeout(
- void* arg, grpc_error_handle error) {
- HandshakingState* self = static_cast<HandshakingState*>(arg);
- // Note that we may be called with y_absl::OkStatus() when the timer fires
- // or with an error indicating that the timer system is being shut down.
- if (error != y_absl::CancelledError()) {
+void Chttp2ServerListener::ActiveConnection::HandshakingState::OnTimeout() {
+ grpc_chttp2_transport* transport = nullptr;
+ {
+ MutexLock lock(&connection_->mu_);
+ if (timer_handle_.has_value()) {
+ transport = connection_->transport_;
+ timer_handle_.reset();
+ }
+ }
+ if (transport != nullptr) {
grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->disconnect_with_error = GRPC_ERROR_CREATE(
"Did not receive HTTP/2 settings before handshake timeout");
- grpc_chttp2_transport* transport = nullptr;
- {
- MutexLock lock(&self->connection_->mu_);
- transport = self->connection_->transport_;
- }
grpc_transport_perform_op(&transport->base, op);
}
- self->Unref();
}
void Chttp2ServerListener::ActiveConnection::HandshakingState::
OnReceiveSettings(void* arg, grpc_error_handle /* error */) {
HandshakingState* self = static_cast<HandshakingState*>(arg);
- grpc_timer_cancel(&self->timer_);
+ {
+ MutexLock lock(&self->connection_->mu_);
+ if (self->timer_handle_.has_value()) {
+ self->connection_->event_engine_->Cancel(*self->timer_handle_);
+ self->timer_handle_.reset();
+ }
+ }
self->Unref();
}
@@ -504,10 +512,15 @@ void Chttp2ServerListener::ActiveConnection::HandshakingState::OnHandshakeDone(
grpc_chttp2_transport_start_reading(transport, args->read_buffer,
&self->on_receive_settings_,
on_close);
- self->Ref().release(); // Held by OnTimeout().
- GRPC_CLOSURE_INIT(&self->on_timeout_, OnTimeout, self,
- grpc_schedule_on_exec_ctx);
- grpc_timer_init(&self->timer_, self->deadline_, &self->on_timeout_);
+ self->timer_handle_ = self->connection_->event_engine_->RunAfter(
+ self->deadline_ - Timestamp::Now(),
+ [self = self->Ref()]() mutable {
+ ApplicationCallbackExecCtx callback_exec_ctx;
+ ExecCtx exec_ctx;
+ self->OnTimeout();
+ // HandshakingState deletion might require an active ExecCtx.
+ self.reset();
+ });
} else {
// Failed to create channel from transport. Clean up.
gpr_log(GPR_ERROR, "Failed to create channel: %s",
@@ -549,9 +562,11 @@ void Chttp2ServerListener::ActiveConnection::HandshakingState::OnHandshakeDone(
Chttp2ServerListener::ActiveConnection::ActiveConnection(
grpc_pollset* accepting_pollset, grpc_tcp_server_acceptor* acceptor,
- const ChannelArgs& args, MemoryOwner memory_owner)
+ EventEngine* event_engine, const ChannelArgs& args,
+ MemoryOwner memory_owner)
: handshaking_state_(memory_owner.MakeOrphanable<HandshakingState>(
- Ref(), accepting_pollset, acceptor, args)) {
+ Ref(), accepting_pollset, acceptor, args)),
+ event_engine_(event_engine) {
GRPC_CLOSURE_INIT(&on_close_, ActiveConnection::OnClose, this,
grpc_schedule_on_exec_ctx);
}
@@ -580,20 +595,18 @@ void Chttp2ServerListener::ActiveConnection::SendGoAway() {
MutexLock lock(&mu_);
if (transport_ != nullptr && !shutdown_) {
transport = transport_;
- Ref().release(); // Ref held by OnDrainGraceTimeExpiry
- GRPC_CLOSURE_INIT(&on_drain_grace_time_expiry_, OnDrainGraceTimeExpiry,
- this, nullptr);
- grpc_timer_init(
- &drain_grace_timer_,
- Timestamp::Now() +
- std::max(
- Duration::Zero(),
- listener_->args_
- .GetDurationFromIntMillis(
- GRPC_ARG_SERVER_CONFIG_CHANGE_DRAIN_GRACE_TIME_MS)
- .value_or(Duration::Minutes(10))),
- &on_drain_grace_time_expiry_);
- drain_grace_timer_expiry_callback_pending_ = true;
+ drain_grace_timer_handle_ = event_engine_->RunAfter(
+ std::max(Duration::Zero(),
+ listener_->args_
+ .GetDurationFromIntMillis(
+ GRPC_ARG_SERVER_CONFIG_CHANGE_DRAIN_GRACE_TIME_MS)
+ .value_or(Duration::Minutes(10))),
+ [self = Ref(DEBUG_LOCATION, "drain_grace_timer")]() mutable {
+ ApplicationCallbackExecCtx callback_exec_ctx;
+ ExecCtx exec_ctx;
+ self->OnDrainGraceTimeExpiry();
+ self.reset(DEBUG_LOCATION, "drain_grace_timer");
+ });
shutdown_ = true;
}
}
@@ -638,30 +651,31 @@ void Chttp2ServerListener::ActiveConnection::OnClose(
self->shutdown_ = true;
}
// Cancel the drain_grace_timer_ if needed.
- if (self->drain_grace_timer_expiry_callback_pending_) {
- grpc_timer_cancel(&self->drain_grace_timer_);
+ if (self->drain_grace_timer_handle_.has_value()) {
+ self->event_engine_->Cancel(*self->drain_grace_timer_handle_);
+ self->drain_grace_timer_handle_.reset();
}
}
self->Unref();
}
-void Chttp2ServerListener::ActiveConnection::OnDrainGraceTimeExpiry(
- void* arg, grpc_error_handle error) {
- ActiveConnection* self = static_cast<ActiveConnection*>(arg);
+void Chttp2ServerListener::ActiveConnection::OnDrainGraceTimeExpiry() {
+ grpc_chttp2_transport* transport = nullptr;
// If the drain_grace_timer_ was not cancelled, disconnect the transport
// immediately.
- if (error.ok()) {
- grpc_chttp2_transport* transport = nullptr;
- {
- MutexLock lock(&self->mu_);
- transport = self->transport_;
+ {
+ MutexLock lock(&mu_);
+ if (drain_grace_timer_handle_.has_value()) {
+ transport = transport_;
+ drain_grace_timer_handle_.reset();
}
+ }
+ if (transport != nullptr) {
grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->disconnect_with_error = GRPC_ERROR_CREATE(
"Drain grace time expired. Closing connection immediately.");
grpc_transport_perform_op(&transport->base, op);
}
- self->Unref();
}
//
@@ -831,8 +845,9 @@ void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp,
}
auto memory_owner = self->memory_quota_->CreateMemoryOwner(
y_absl::StrCat(grpc_endpoint_get_peer(tcp), ":server_channel"));
+ EventEngine* const event_engine = self->args_.GetObject<EventEngine>();
auto connection = memory_owner.MakeOrphanable<ActiveConnection>(
- accepting_pollset, acceptor, args, std::move(memory_owner));
+ accepting_pollset, acceptor, event_engine, args, std::move(memory_owner));
// We no longer own acceptor
acceptor = nullptr;
// Hold a ref to connection to allow starting handshake outside the
diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
index 8767c3e81c..7910d42fff 100644
--- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
+++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
@@ -45,7 +45,6 @@
#include <grpc/slice_buffer.h>
#include <grpc/status.h>
#include <grpc/support/alloc.h>
-#include <grpc/support/atm.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
@@ -61,9 +60,12 @@
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/ext/transport/chttp2/transport/stream_map.h"
#include "src/core/ext/transport/chttp2/transport/varint.h"
+#include "src/core/lib/channel/call_tracer.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/context.h"
#include "src/core/lib/debug/stats.h"
#include "src/core/lib/debug/stats_data.h"
+#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/bitset.h"
#include "src/core/lib/gprpp/crash.h"
@@ -76,6 +78,7 @@
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/iomgr_fwd.h"
+#include "src/core/lib/iomgr/port.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/resource_quota/arena.h"
@@ -94,6 +97,10 @@
#include "src/core/lib/transport/transport.h"
#include "src/core/lib/transport/transport_impl.h"
+#ifdef GRPC_POSIX_SOCKET_TCP
+#include "src/core/lib/iomgr/ev_posix.h"
+#endif
+
#define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024)
#define MAX_WINDOW 0x7fffffffu
#define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024)
@@ -199,6 +206,18 @@ static void keepalive_watchdog_fired_locked(
void* arg, GRPC_UNUSED grpc_error_handle error);
static void maybe_reset_keepalive_ping_timer_locked(grpc_chttp2_transport* t);
+namespace {
+grpc_core::CallTracerInterface* CallTracerIfEnabled(grpc_chttp2_stream* s) {
+ if (s->context == nullptr || !grpc_core::IsTraceRecordCallopsEnabled()) {
+ return nullptr;
+ }
+ return static_cast<grpc_core::CallTracerInterface*>(
+ static_cast<grpc_call_context_element*>(
+ s->context)[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE]
+ .value);
+}
+} // namespace
+
namespace grpc_core {
namespace {
@@ -344,8 +363,10 @@ static void read_channel_args(grpc_chttp2_transport* t,
.value_or(GRPC_ENABLE_CHANNELZ_DEFAULT)) {
t->channelz_socket =
grpc_core::MakeRefCounted<grpc_core::channelz::SocketNode>(
- TString(grpc_endpoint_get_local_address(t->ep)), t->peer_string,
- y_absl::StrFormat("%s %s", get_vtable()->name, t->peer_string),
+ TString(grpc_endpoint_get_local_address(t->ep)),
+ TString(t->peer_string.as_string_view()),
+ y_absl::StrCat(get_vtable()->name, " ",
+ t->peer_string.as_string_view()),
channel_args
.GetObjectRef<grpc_core::channelz::SocketNode::Security>());
}
@@ -512,7 +533,8 @@ grpc_chttp2_transport::grpc_chttp2_transport(
? "chttp2_refcount"
: nullptr),
ep(ep),
- peer_string(grpc_endpoint_get_peer(ep)),
+ peer_string(
+ grpc_core::Slice::FromCopiedString(grpc_endpoint_get_peer(ep))),
memory_owner(channel_args.GetObject<grpc_core::ResourceQuota>()
->memory_quota()
->CreateMemoryOwner(y_absl::StrCat(
@@ -525,7 +547,7 @@ grpc_chttp2_transport::grpc_chttp2_transport(
is_client(is_client),
next_stream_id(is_client ? 1 : 2),
flow_control(
- peer_string.c_str(),
+ peer_string.as_string_view(),
channel_args.GetBool(GRPC_ARG_HTTP2_BDP_PROBE).value_or(true),
&memory_owner),
deframe_state(is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0),
@@ -598,6 +620,14 @@ grpc_chttp2_transport::grpc_chttp2_transport(
if (grpc_core::test_only_init_callback != nullptr) {
grpc_core::test_only_init_callback();
}
+
+#ifdef GRPC_POSIX_SOCKET_TCP
+ closure_barrier_may_cover_write =
+ grpc_event_engine_run_in_background() &&
+ grpc_core::IsScheduleCancellationOverWriteEnabled()
+ ? 0
+ : CLOSURE_BARRIER_MAY_COVER_WRITE;
+#endif
}
static void destroy_transport_locked(void* tp, grpc_error_handle /*error*/) {
@@ -845,7 +875,8 @@ static void set_write_state(grpc_chttp2_transport* t,
grpc_chttp2_write_state st, const char* reason) {
GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_INFO, "W:%p %s [%s] state %s -> %s [%s]", t,
- t->is_client ? "CLIENT" : "SERVER", t->peer_string.c_str(),
+ t->is_client ? "CLIENT" : "SERVER",
+ TString(t->peer_string.as_string_view()).c_str(),
write_state_name(t->write_state), write_state_name(st), reason));
t->write_state = st;
// If the state is being reset back to idle, it means a write was just
@@ -1080,8 +1111,9 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
// We want to log this irrespective of whether http tracing is enabled if we
// received a GOAWAY with a non NO_ERROR code.
if (goaway_error != GRPC_HTTP2_NO_ERROR) {
- gpr_log(GPR_INFO, "%s: Got goaway [%d] err=%s", t->peer_string.c_str(),
- goaway_error, grpc_core::StatusToString(t->goaway_error).c_str());
+ gpr_log(GPR_INFO, "%s: Got goaway [%d] err=%s",
+ TString(t->peer_string.as_string_view()).c_str(), goaway_error,
+ grpc_core::StatusToString(t->goaway_error).c_str());
}
if (t->is_client) {
cancel_unstarted_streams(t, t->goaway_error);
@@ -1112,7 +1144,8 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
"%s: Received a GOAWAY with error code ENHANCE_YOUR_CALM and debug "
"data equal to \"too_many_pings\". Current keepalive time (before "
"throttling): %s",
- t->peer_string.c_str(), t->keepalive_time.ToString().c_str());
+ TString(t->peer_string.as_string_view()).c_str(),
+ t->keepalive_time.ToString().c_str());
constexpr int max_keepalive_time_millis =
INT_MAX / KEEPALIVE_TIME_BACKOFF_MULTIPLIER;
int64_t throttled_keepalive_time =
@@ -1182,14 +1215,6 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t) {
}
}
-// Flag that this closure barrier may be covering a write in a pollset, and so
-// we should not complete this closure until we can prove that the write got
-// scheduled
-#define CLOSURE_BARRIER_MAY_COVER_WRITE (1 << 0)
-// First bit of the reference count, stored in the high order bits (with the low
-// bits being used for flags defined above)
-#define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16)
-
static grpc_closure* add_closure_barrier(grpc_closure* closure) {
closure->next_data.scratch += CLOSURE_BARRIER_FIRST_REF_BIT;
return closure;
@@ -1208,10 +1233,11 @@ static void null_then_sched_closure(grpc_closure** closure) {
}
void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
- grpc_chttp2_stream* /*s*/,
+ grpc_chttp2_stream* s,
grpc_closure** pclosure,
grpc_error_handle error,
- const char* desc) {
+ const char* desc,
+ grpc_core::DebugLocation whence) {
grpc_closure* closure = *pclosure;
*pclosure = nullptr;
if (closure == nullptr) {
@@ -1222,15 +1248,23 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
gpr_log(
GPR_INFO,
"complete_closure_step: t=%p %p refs=%d flags=0x%04x desc=%s err=%s "
- "write_state=%s",
+ "write_state=%s whence=%s:%d",
t, closure,
static_cast<int>(closure->next_data.scratch /
CLOSURE_BARRIER_FIRST_REF_BIT),
static_cast<int>(closure->next_data.scratch %
CLOSURE_BARRIER_FIRST_REF_BIT),
desc, grpc_core::StatusToString(error).c_str(),
- write_state_name(t->write_state));
+ write_state_name(t->write_state), whence.file(), whence.line());
+ }
+
+ auto* tracer = CallTracerIfEnabled(s);
+ if (tracer != nullptr) {
+ tracer->RecordAnnotation(
+ y_absl::StrFormat("on_complete: s=%p %p desc=%s err=%s", s, closure, desc,
+ grpc_core::StatusToString(error).c_str()));
}
+
if (!error.ok()) {
grpc_error_handle cl_err =
grpc_core::internal::StatusMoveFromHeapPtr(closure->error_data.error);
@@ -1240,8 +1274,9 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
" write_state=", write_state_name(t->write_state), " refs=",
closure->next_data.scratch / CLOSURE_BARRIER_FIRST_REF_BIT, " flags=",
closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT));
- cl_err = grpc_error_set_str(
- cl_err, grpc_core::StatusStrProperty::kTargetAddress, t->peer_string);
+ cl_err = grpc_error_set_str(cl_err,
+ grpc_core::StatusStrProperty::kTargetAddress,
+ TString(t->peer_string.as_string_view()));
}
cl_err = grpc_error_add_child(cl_err, error);
closure->error_data.error = grpc_core::internal::StatusAllocHeapPtr(cl_err);
@@ -1290,7 +1325,7 @@ static void perform_stream_op_locked(void* stream_op,
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
gpr_log(GPR_INFO,
"perform_stream_op_locked[s=%p; op=%p]: %s; on_complete = %p", s,
- op, grpc_transport_stream_op_batch_string(op).c_str(),
+ op, grpc_transport_stream_op_batch_string(op, false).c_str(),
op->on_complete);
if (op->send_initial_metadata) {
log_metadata(op_payload->send_initial_metadata.send_initial_metadata,
@@ -1302,6 +1337,14 @@ static void perform_stream_op_locked(void* stream_op,
}
}
+ auto* tracer = CallTracerIfEnabled(s);
+ if (tracer != nullptr) {
+ tracer->RecordAnnotation(y_absl::StrFormat(
+ "perform_stream_op_locked[s=%p; op=%p]: %s; on_complete = %p", s, op,
+ grpc_transport_stream_op_batch_string(op, true).c_str(),
+ op->on_complete));
+ }
+
grpc_closure* on_complete = op->on_complete;
// on_complete will be null if and only if there are no send ops in the batch.
if (on_complete != nullptr) {
@@ -1320,7 +1363,7 @@ static void perform_stream_op_locked(void* stream_op,
t->channelz_socket->RecordStreamStartedFromLocal();
}
GPR_ASSERT(s->send_initial_metadata_finished == nullptr);
- on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
+ on_complete->next_data.scratch |= t->closure_barrier_may_cover_write;
s->send_initial_metadata_finished = add_closure_barrier(on_complete);
s->send_initial_metadata =
@@ -1370,17 +1413,13 @@ static void perform_stream_op_locked(void* stream_op,
&s->write_closed_error, 1),
"send_initial_metadata_finished");
}
- if (op_payload->send_initial_metadata.peer_string != nullptr) {
- gpr_atm_rel_store(op_payload->send_initial_metadata.peer_string,
- (gpr_atm)t->peer_string.c_str());
- }
}
if (op->send_message) {
t->num_messages_in_next_write++;
grpc_core::global_stats().IncrementHttp2SendMessageSize(
op->payload->send_message.send_message->Length());
- on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
+ on_complete->next_data.scratch |= t->closure_barrier_may_cover_write;
s->send_message_finished = add_closure_barrier(op->on_complete);
const uint32_t flags = op_payload->send_message.flags;
if (s->write_closed) {
@@ -1454,7 +1493,7 @@ static void perform_stream_op_locked(void* stream_op,
if (op->send_trailing_metadata) {
GPR_ASSERT(s->send_trailing_metadata_finished == nullptr);
- on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
+ on_complete->next_data.scratch |= t->closure_barrier_may_cover_write;
s->send_trailing_metadata_finished = add_closure_barrier(on_complete);
s->send_trailing_metadata =
op_payload->send_trailing_metadata.send_trailing_metadata;
@@ -1493,10 +1532,6 @@ static void perform_stream_op_locked(void* stream_op,
if (s->parsed_trailers_only && s->trailing_metadata_available != nullptr) {
*s->trailing_metadata_available = true;
}
- if (op_payload->recv_initial_metadata.peer_string != nullptr) {
- gpr_atm_rel_store(op_payload->recv_initial_metadata.peer_string,
- (gpr_atm)t->peer_string.c_str());
- }
grpc_chttp2_maybe_complete_recv_initial_metadata(t, s);
}
@@ -1551,7 +1586,7 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
gpr_log(GPR_INFO, "perform_stream_op[s=%p; op=%p]: %s", s, op,
- grpc_transport_stream_op_batch_string(op).c_str());
+ grpc_transport_stream_op_batch_string(op, false).c_str());
}
GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op");
@@ -1645,7 +1680,7 @@ void grpc_chttp2_ack_ping(grpc_chttp2_transport* t, uint64_t id) {
grpc_chttp2_ping_queue* pq = &t->ping_queue;
if (pq->inflight_id != id) {
gpr_log(GPR_DEBUG, "Unknown ping response from %s: %" PRIx64,
- t->peer_string.c_str(), id);
+ TString(t->peer_string.as_string_view()).c_str(), id);
return;
}
grpc_core::ExecCtx::RunList(DEBUG_LOCATION,
@@ -1692,11 +1727,12 @@ class GracefulGoaway : public grpc_core::RefCounted<GracefulGoaway> {
return;
}
if (t_->destroying || !t_->closed_with_error.ok()) {
- GRPC_CHTTP2_IF_TRACING(gpr_log(
- GPR_INFO,
- "transport:%p %s peer:%s Transport already shutting down. "
- "Graceful GOAWAY abandoned.",
- t_, t_->is_client ? "CLIENT" : "SERVER", t_->peer_string.c_str()));
+ GRPC_CHTTP2_IF_TRACING(
+ gpr_log(GPR_INFO,
+ "transport:%p %s peer:%s Transport already shutting down. "
+ "Graceful GOAWAY abandoned.",
+ t_, t_->is_client ? "CLIENT" : "SERVER",
+ TString(t_->peer_string.as_string_view()).c_str()));
return;
}
// Ping completed. Send final goaway.
@@ -1705,7 +1741,8 @@ class GracefulGoaway : public grpc_core::RefCounted<GracefulGoaway> {
"transport:%p %s peer:%s Graceful shutdown: Ping received. "
"Sending final GOAWAY with stream_id:%d",
t_, t_->is_client ? "CLIENT" : "SERVER",
- t_->peer_string.c_str(), t_->last_new_stream_id));
+ TString(t_->peer_string.as_string_view()).c_str(),
+ t_->last_new_stream_id));
t_->sent_goaway_state = GRPC_CHTTP2_FINAL_GOAWAY_SEND_SCHEDULED;
grpc_chttp2_goaway_append(t_->last_new_stream_id, 0, grpc_empty_slice(),
&t_->qbuf);
@@ -1768,7 +1805,8 @@ static void send_goaway(grpc_chttp2_transport* t, grpc_error_handle error,
} else if (t->sent_goaway_state == GRPC_CHTTP2_NO_GOAWAY_SEND ||
t->sent_goaway_state == GRPC_CHTTP2_GRACEFUL_GOAWAY) {
// We want to log this irrespective of whether http tracing is enabled
- gpr_log(GPR_DEBUG, "%s: Sending goaway err=%s", t->peer_string.c_str(),
+ gpr_log(GPR_DEBUG, "%s: Sending goaway err=%s",
+ TString(t->peer_string.as_string_view()).c_str(),
grpc_core::StatusToString(error).c_str());
t->sent_goaway_state = GRPC_CHTTP2_FINAL_GOAWAY_SEND_SCHEDULED;
grpc_chttp2_goaway_append(
@@ -1877,7 +1915,8 @@ void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_chttp2_transport* t,
grpc_slice_buffer_reset_and_unref(&s->frame_storage);
}
*s->recv_initial_metadata = std::move(s->initial_metadata_buffer);
- s->recv_initial_metadata->Set(grpc_core::PeerString(), t->peer_string);
+ s->recv_initial_metadata->Set(grpc_core::PeerString(),
+ t->peer_string.Ref());
// If we didn't receive initial metadata from the wire and instead faked a
// status (due to stream cancellations for example), let upper layers know
// that trailing metadata is immediately available.
@@ -1992,7 +2031,6 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_chttp2_transport* t,
grpc_transport_move_stats(&s->stats, s->collecting_stats);
s->collecting_stats = nullptr;
*s->recv_trailing_metadata = std::move(s->trailing_metadata_buffer);
- s->recv_trailing_metadata->Set(grpc_core::PeerString(), t->peer_string);
null_then_sched_closure(&s->recv_trailing_metadata_finished);
}
}
@@ -2578,7 +2616,8 @@ static void start_bdp_ping(void* tp, grpc_error_handle error) {
static void start_bdp_ping_locked(void* tp, grpc_error_handle error) {
grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
- gpr_log(GPR_INFO, "%s: Start BDP ping err=%s", t->peer_string.c_str(),
+ gpr_log(GPR_INFO, "%s: Start BDP ping err=%s",
+ TString(t->peer_string.as_string_view()).c_str(),
grpc_core::StatusToString(error).c_str());
}
if (!error.ok() || !t->closed_with_error.ok()) {
@@ -2602,7 +2641,8 @@ static void finish_bdp_ping(void* tp, grpc_error_handle error) {
static void finish_bdp_ping_locked(void* tp, grpc_error_handle error) {
grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
- gpr_log(GPR_INFO, "%s: Complete BDP ping err=%s", t->peer_string.c_str(),
+ gpr_log(GPR_INFO, "%s: Complete BDP ping err=%s",
+ TString(t->peer_string.as_string_view()).c_str(),
grpc_core::StatusToString(error).c_str());
}
if (!error.ok() || !t->closed_with_error.ok()) {
@@ -2764,7 +2804,8 @@ static void start_keepalive_ping_locked(void* arg, grpc_error_handle error) {
}
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace) ||
GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
- gpr_log(GPR_INFO, "%s: Start keepalive ping", t->peer_string.c_str());
+ gpr_log(GPR_INFO, "%s: Start keepalive ping",
+ TString(t->peer_string.as_string_view()).c_str());
}
GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog");
t->keepalive_watchdog_timer_handle =
@@ -2789,7 +2830,8 @@ static void finish_keepalive_ping_locked(void* arg, grpc_error_handle error) {
if (error.ok()) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace) ||
GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
- gpr_log(GPR_INFO, "%s: Finish keepalive ping", t->peer_string.c_str());
+ gpr_log(GPR_INFO, "%s: Finish keepalive ping",
+ TString(t->peer_string.as_string_view()).c_str());
}
if (!t->keepalive_ping_started) {
// start_keepalive_ping_locked has not run yet. Reschedule
@@ -2836,7 +2878,7 @@ static void keepalive_watchdog_fired_locked(
t->keepalive_watchdog_timer_handle.reset();
if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) {
gpr_log(GPR_INFO, "%s: Keepalive watchdog fired. Closing transport.",
- t->peer_string.c_str());
+ TString(t->peer_string.as_string_view()).c_str());
t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING;
close_transport_locked(
t, grpc_error_set_int(GRPC_ERROR_CREATE("keepalive watchdog timeout"),
@@ -2860,7 +2902,7 @@ static void maybe_reset_keepalive_ping_timer_locked(grpc_chttp2_transport* t) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace) ||
GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
gpr_log(GPR_INFO, "%s: Keepalive ping cancelled. Resetting timer.",
- t->peer_string.c_str());
+ TString(t->peer_string.as_string_view()).c_str());
}
t->keepalive_ping_timer_handle =
t->event_engine->RunAfter(t->keepalive_time, [t] {
@@ -2953,7 +2995,7 @@ static void benign_reclaimer_locked(void* arg, grpc_error_handle error) {
// disconnect cleanly
if (GRPC_TRACE_FLAG_ENABLED(grpc_resource_quota_trace)) {
gpr_log(GPR_INFO, "HTTP2: %s - send goaway to free memory",
- t->peer_string.c_str());
+ TString(t->peer_string.as_string_view()).c_str());
}
send_goaway(t,
grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"),
@@ -2964,7 +3006,7 @@ static void benign_reclaimer_locked(void* arg, grpc_error_handle error) {
gpr_log(GPR_INFO,
"HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR
" streams",
- t->peer_string.c_str(),
+ TString(t->peer_string.as_string_view()).c_str(),
grpc_chttp2_stream_map_size(&t->stream_map));
}
t->benign_reclaimer_registered = false;
@@ -2983,7 +3025,7 @@ static void destructive_reclaimer_locked(void* arg, grpc_error_handle error) {
grpc_chttp2_stream_map_rand(&t->stream_map));
if (GRPC_TRACE_FLAG_ENABLED(grpc_resource_quota_trace)) {
gpr_log(GPR_INFO, "HTTP2: %s - abandon stream id %d",
- t->peer_string.c_str(), s->id);
+ TString(t->peer_string.as_string_view()).c_str(), s->id);
}
grpc_chttp2_cancel_stream(
t, s,
@@ -3064,6 +3106,7 @@ static grpc_endpoint* chttp2_get_endpoint(grpc_transport* t) {
}
static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
+ false,
"chttp2",
init_stream,
nullptr,
@@ -3102,9 +3145,24 @@ void grpc_chttp2_transport_start_reading(
grpc_slice_buffer_move_into(read_buffer, &t->read_buffer);
gpr_free(read_buffer);
}
- t->notify_on_receive_settings = notify_on_receive_settings;
- t->notify_on_close = notify_on_close;
t->combiner->Run(
- GRPC_CLOSURE_INIT(&t->read_action_locked, read_action_locked, t, nullptr),
+ grpc_core::NewClosure([t, notify_on_receive_settings,
+ notify_on_close](grpc_error_handle) {
+ if (!t->closed_with_error.ok()) {
+ if (notify_on_receive_settings != nullptr) {
+ grpc_core::ExecCtx::Run(DEBUG_LOCATION, notify_on_receive_settings,
+ t->closed_with_error);
+ }
+ if (notify_on_close != nullptr) {
+ grpc_core::ExecCtx::Run(DEBUG_LOCATION, notify_on_close,
+ t->closed_with_error);
+ }
+ GRPC_CHTTP2_UNREF_TRANSPORT(t, "reading_action");
+ return;
+ }
+ t->notify_on_receive_settings = notify_on_receive_settings;
+ t->notify_on_close = notify_on_close;
+ read_action_locked(t, y_absl::OkStatus());
+ }),
y_absl::OkStatus());
}
diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/flow_control.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/flow_control.cc
index ffcfc29cc4..68ce0ed6ab 100644
--- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/flow_control.cc
+++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/flow_control.cc
@@ -102,7 +102,7 @@ std::ostream& operator<<(std::ostream& out, const FlowControlAction& action) {
return out << action.DebugString();
}
-TransportFlowControl::TransportFlowControl(const char* name,
+TransportFlowControl::TransportFlowControl(y_absl::string_view name,
bool enable_bdp_probe,
MemoryOwner* memory_owner)
: memory_owner_(memory_owner),
@@ -176,7 +176,10 @@ int64_t TransportFlowControl::target_window() const {
}
FlowControlAction TransportFlowControl::UpdateAction(FlowControlAction action) {
- if (announced_window_ < target_window() / 2) {
+ const int64_t target = target_window();
+ // round up so that one byte targets are sent.
+ const int64_t send_threshold = (target + 1) / 2;
+ if (announced_window_ < send_threshold) {
action.set_send_transport_update(
FlowControlAction::Urgency::UPDATE_IMMEDIATELY);
}
diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/flow_control.h b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/flow_control.h
index 1ba53d2eb9..4fded4013e 100644
--- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/flow_control.h
+++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/flow_control.h
@@ -31,6 +31,7 @@
#include "y_absl/functional/function_ref.h"
#include "y_absl/status/status.h"
+#include "y_absl/strings/string_view.h"
#include "y_absl/types/optional.h"
#include <grpc/support/log.h>
@@ -169,7 +170,7 @@ std::ostream& operator<<(std::ostream& out, const FlowControlAction& action);
// to be as performant as possible.
class TransportFlowControl final {
public:
- explicit TransportFlowControl(const char* name, bool enable_bdp_probe,
+ explicit TransportFlowControl(y_absl::string_view name, bool enable_bdp_probe,
MemoryOwner* memory_owner);
~TransportFlowControl() {}
diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/frame_settings.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/frame_settings.cc
index 46c15bf80f..0cfa042c9a 100644
--- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/frame_settings.cc
+++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/frame_settings.cc
@@ -29,6 +29,7 @@
#include "y_absl/base/attributes.h"
#include "y_absl/status/status.h"
#include "y_absl/strings/str_format.h"
+#include "y_absl/strings/string_view.h"
#include <grpc/slice_buffer.h>
#include <grpc/support/log.h>
@@ -42,6 +43,7 @@
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/slice/slice.h"
static uint8_t* fill_header(uint8_t* out, uint32_t length, uint8_t flags) {
*out++ = static_cast<uint8_t>(length >> 16);
@@ -230,7 +232,8 @@ grpc_error_handle grpc_chttp2_settings_parser_parse(void* p,
parser->incoming_settings[id] = parser->value;
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
gpr_log(GPR_INFO, "CHTTP2:%s:%s: got setting %s = %d",
- t->is_client ? "CLI" : "SVR", t->peer_string.c_str(),
+ t->is_client ? "CLI" : "SVR",
+ TString(t->peer_string.as_string_view()).c_str(),
sp->name, parser->value);
}
} else if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/internal.h b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/internal.h
index 49f228fb6f..c040a17363 100644
--- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/internal.h
+++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/internal.h
@@ -25,8 +25,6 @@
#include <stdint.h>
#include <memory>
-#include <util/generic/string.h>
-#include <util/string/cast.h>
#include "y_absl/strings/string_view.h"
#include "y_absl/types/optional.h"
@@ -62,6 +60,7 @@
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/resource_quota/memory_quota.h"
+#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/surface/init_internally.h"
#include "src/core/lib/transport/connectivity_state.h"
@@ -70,6 +69,14 @@
#include "src/core/lib/transport/transport_fwd.h"
#include "src/core/lib/transport/transport_impl.h"
+// Flag that this closure barrier may be covering a write in a pollset, and so
+// we should not complete this closure until we can prove that the write got
+// scheduled
+#define CLOSURE_BARRIER_MAY_COVER_WRITE (1 << 0)
+// First bit of the reference count, stored in the high order bits (with the low
+// bits being used for flags defined above)
+#define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16)
+
namespace grpc_core {
class ContextList;
}
@@ -262,7 +269,7 @@ struct grpc_chttp2_transport
grpc_transport base; // must be first
grpc_core::RefCount refs;
grpc_endpoint* ep;
- TString peer_string;
+ grpc_core::Slice peer_string;
grpc_core::MemoryOwner memory_owner;
const grpc_core::MemoryAllocator::Reservation self_reservation;
@@ -473,6 +480,10 @@ struct grpc_chttp2_transport
/// Based on channel args, preferred_rx_crypto_frame_sizes are advertised to
/// the peer
bool enable_preferred_rx_crypto_frame_advertisement = false;
+ /// Set to non zero if closures associated with the transport may be
+ /// covering a write in a pollset. Such closures cannot be scheduled until
+ /// we can prove that the write got scheduled.
+ uint8_t closure_barrier_may_cover_write = CLOSURE_BARRIER_MAY_COVER_WRITE;
std::shared_ptr<grpc_event_engine::experimental::EventEngine> event_engine;
};
@@ -700,7 +711,8 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
grpc_chttp2_stream* s,
grpc_closure** pclosure,
grpc_error_handle error,
- const char* desc);
+ const char* desc,
+ grpc_core::DebugLocation whence = {});
#define GRPC_HEADER_SIZE_IN_BYTES 5
#define MAX_SIZE_T (~(size_t)0)
diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/parsing.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/parsing.cc
index b41a17f21a..dd92295e7a 100644
--- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/parsing.cc
+++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/parsing.cc
@@ -57,6 +57,7 @@
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/bdp_estimator.h"
#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/http2_errors.h"
@@ -630,8 +631,8 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
GPR_INFO,
"transport:%p SERVER peer:%s Final GOAWAY sent. Ignoring new "
"grpc_chttp2_stream request id=%d, last grpc_chttp2_stream id=%d",
- t, t->peer_string.c_str(), t->incoming_stream_id,
- t->last_new_stream_id));
+ t, TString(t->peer_string.as_string_view()).c_str(),
+ t->incoming_stream_id, t->last_new_stream_id));
return init_header_skip_frame_parser(t, priority_type);
}
t->last_new_stream_id = t->incoming_stream_id;
diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/writing.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/writing.cc
index e381b13e69..a30a1a258e 100644
--- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/writing.cc
+++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/writing.cc
@@ -27,6 +27,7 @@
#include <util/string/cast.h>
#include "y_absl/status/status.h"
+#include "y_absl/strings/string_view.h"
#include "y_absl/types/optional.h"
#include <grpc/event_engine/event_engine.h>
@@ -95,7 +96,8 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace) ||
GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
gpr_log(GPR_INFO, "%s: Ping delayed [%s]: already pinging",
- t->is_client ? "CLIENT" : "SERVER", t->peer_string.c_str());
+ t->is_client ? "CLIENT" : "SERVER",
+ TString(t->peer_string.as_string_view()).c_str());
}
return;
}
@@ -107,7 +109,8 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
gpr_log(GPR_INFO,
"CLIENT: Ping delayed [%s]: too many recent pings: %d/%d",
- t->peer_string.c_str(), t->ping_state.pings_before_data_required,
+ TString(t->peer_string.as_string_view()).c_str(),
+ t->ping_state.pings_before_data_required,
t->ping_policy.max_pings_without_data);
}
return;
@@ -149,7 +152,8 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
"%s: Ping delayed [%s]: not enough time elapsed since last "
"ping. "
" Last ping %" PRId64 ": Next ping %" PRId64 ": Now %" PRId64,
- t->is_client ? "CLIENT" : "SERVER", t->peer_string.c_str(),
+ t->is_client ? "CLIENT" : "SERVER",
+ TString(t->peer_string.as_string_view()).c_str(),
t->ping_state.last_ping_sent_time.milliseconds_after_process_epoch(),
next_allowed_ping.milliseconds_after_process_epoch(),
now.milliseconds_after_process_epoch());
@@ -180,7 +184,8 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) {
GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace) ||
GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
gpr_log(GPR_INFO, "%s: Ping sent [%s]: %d/%d",
- t->is_client ? "CLIENT" : "SERVER", t->peer_string.c_str(),
+ t->is_client ? "CLIENT" : "SERVER",
+ TString(t->peer_string.as_string_view()).c_str(),
t->ping_state.pings_before_data_required,
t->ping_policy.max_pings_without_data);
}
@@ -218,7 +223,7 @@ static void report_stall(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
" However, if you know that there are unwanted stalls, here is some "
"helpful data: [fc:pending=%" PRIdPTR ":flowed=%" PRId64
":peer_initwin=%d:t_win=%" PRId64 ":s_win=%d:s_delta=%" PRId64 "]",
- t->peer_string.c_str(), t, s->id, staller,
+ TString(t->peer_string.as_string_view()).c_str(), t, s->id, staller,
s->flow_controlled_buffer.length, s->flow_controlled_bytes_flowed,
t->settings[GRPC_ACKED_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
diff --git a/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.cc b/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.cc
index 0370b05852..5ac4ce37de 100644
--- a/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.cc
+++ b/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.cc
@@ -409,7 +409,7 @@ void complete_if_batch_end_locked(inproc_stream* s, grpc_error_handle error,
int is_rtm = static_cast<int>(op == s->recv_trailing_md_op);
if ((is_sm + is_stm + is_rim + is_rm + is_rtm) == 1) {
- INPROC_LOG(GPR_INFO, "%s %p %p %s", msg, s, op,
+ INPROC_LOG(GPR_INFO, "%s %p %p %p %s", msg, s, op, op->on_complete,
grpc_core::StatusToString(error).c_str());
grpc_core::ExecCtx::Run(DEBUG_LOCATION, op->on_complete, error);
}
@@ -698,8 +698,9 @@ void op_state_machine_locked(inproc_stream* s, grpc_error_handle error) {
s->to_read_initial_md_filled = false;
grpc_core::ExecCtx::Run(
DEBUG_LOCATION,
- s->recv_initial_md_op->payload->recv_initial_metadata
- .recv_initial_metadata_ready,
+ std::exchange(s->recv_initial_md_op->payload->recv_initial_metadata
+ .recv_initial_metadata_ready,
+ nullptr),
y_absl::OkStatus());
complete_if_batch_end_locked(
s, y_absl::OkStatus(), s->recv_initial_md_op,
@@ -767,6 +768,8 @@ void op_state_machine_locked(inproc_stream* s, grpc_error_handle error) {
nullptr);
s->to_read_trailing_md.Clear();
s->to_read_trailing_md_filled = false;
+ s->recv_trailing_md_op->payload->recv_trailing_metadata
+ .recv_trailing_metadata->Set(grpc_core::GrpcStatusFromWire(), true);
// We should schedule the recv_trailing_md_op completion if
// 1. this stream is the client-side
@@ -907,8 +910,6 @@ bool cancel_stream_locked(inproc_stream* s, grpc_error_handle error) {
return ret;
}
-void do_nothing(void* /*arg*/, grpc_error_handle /*error*/) {}
-
void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
grpc_transport_stream_op_batch* op) {
INPROC_LOG(GPR_INFO, "perform_stream_op %p %p %p", gt, gs, op);
@@ -934,8 +935,8 @@ void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
// completed). This can go away once we move to a new C++ closure API
// that provides the ability to create a barrier closure.
if (on_complete == nullptr) {
- on_complete = GRPC_CLOSURE_INIT(&op->handler_private.closure, do_nothing,
- nullptr, grpc_schedule_on_exec_ctx);
+ on_complete = op->on_complete =
+ grpc_core::NewClosure([](grpc_error_handle) {});
}
if (op->cancel_stream) {
@@ -1178,13 +1179,18 @@ void set_pollset_set(grpc_transport* /*gt*/, grpc_stream* /*gs*/,
grpc_endpoint* get_endpoint(grpc_transport* /*t*/) { return nullptr; }
-const grpc_transport_vtable inproc_vtable = {
- sizeof(inproc_stream), "inproc",
- init_stream, nullptr,
- set_pollset, set_pollset_set,
- perform_stream_op, perform_transport_op,
- destroy_stream, destroy_transport,
- get_endpoint};
+const grpc_transport_vtable inproc_vtable = {sizeof(inproc_stream),
+ true,
+ "inproc",
+ init_stream,
+ nullptr,
+ set_pollset,
+ set_pollset_set,
+ perform_stream_op,
+ perform_transport_op,
+ destroy_stream,
+ destroy_transport,
+ get_endpoint};
//******************************************************************************
// Main inproc transport functions
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c
index 2c8d42849f..d09a3d2f38 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c
@@ -36,7 +36,7 @@
#include "upb/port_def.inc"
-static const upb_MiniTable_Sub envoy_config_bootstrap_v3_Bootstrap_submsgs[26] = {
+static const upb_MiniTable_Sub envoy_config_bootstrap_v3_Bootstrap_submsgs[27] = {
{.submsg = &envoy_config_core_v3_Node_msginit},
{.submsg = &envoy_config_bootstrap_v3_Bootstrap_StaticResources_msginit},
{.submsg = &envoy_config_bootstrap_v3_Bootstrap_DynamicResources_msginit},
@@ -63,9 +63,10 @@ static const upb_MiniTable_Sub envoy_config_bootstrap_v3_Bootstrap_submsgs[26] =
{.submsg = &envoy_config_core_v3_TypedExtensionConfig_msginit},
{.submsg = &envoy_config_core_v3_TypedExtensionConfig_msginit},
{.submsg = &envoy_config_core_v3_TypedExtensionConfig_msginit},
+ {.submsg = &envoy_config_core_v3_TypedExtensionConfig_msginit},
};
-static const upb_MiniTable_Field envoy_config_bootstrap_v3_Bootstrap__fields[34] = {
+static const upb_MiniTable_Field envoy_config_bootstrap_v3_Bootstrap__fields[35] = {
{1, UPB_SIZE(12, 16), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{2, UPB_SIZE(16, 24), UPB_SIZE(2, 2), 1, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{3, UPB_SIZE(20, 32), UPB_SIZE(3, 3), 2, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
@@ -100,12 +101,13 @@ static const upb_MiniTable_Field envoy_config_bootstrap_v3_Bootstrap__fields[34]
{34, UPB_SIZE(140, 272), UPB_SIZE(18, 18), 23, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{35, UPB_SIZE(144, 280), UPB_SIZE(19, 19), 24, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{36, UPB_SIZE(148, 288), UPB_SIZE(20, 20), 25, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+ {37, UPB_SIZE(152, 296), UPB_SIZE(21, 21), 26, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
};
const upb_MiniTable envoy_config_bootstrap_v3_Bootstrap_msginit = {
&envoy_config_bootstrap_v3_Bootstrap_submsgs[0],
&envoy_config_bootstrap_v3_Bootstrap__fields[0],
- UPB_SIZE(152, 296), 34, kUpb_ExtMode_NonExtendable, 9, 255, 0,
+ UPB_SIZE(160, 304), 35, kUpb_ExtMode_NonExtendable, 9, 255, 0,
};
static const upb_MiniTable_Sub envoy_config_bootstrap_v3_Bootstrap_StaticResources_submsgs[3] = {
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h
index 6243f9fb96..d37937a68b 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h
@@ -467,6 +467,15 @@ UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_clear_xds_config_tracker_ext
UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_bootstrap_v3_Bootstrap_xds_config_tracker_extension(const envoy_config_bootstrap_v3_Bootstrap* msg) {
return *UPB_PTR_AT(msg, UPB_SIZE(148, 288), const struct envoy_config_core_v3_TypedExtensionConfig*);
}
+UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_listener_manager(const envoy_config_bootstrap_v3_Bootstrap* msg) {
+ return _upb_hasbit(msg, 21);
+}
+UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_clear_listener_manager(const envoy_config_bootstrap_v3_Bootstrap* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(152, 296), const upb_Message*) = NULL;
+}
+UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_bootstrap_v3_Bootstrap_listener_manager(const envoy_config_bootstrap_v3_Bootstrap* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(152, 296), const struct envoy_config_core_v3_TypedExtensionConfig*);
+}
UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_node(envoy_config_bootstrap_v3_Bootstrap *msg, struct envoy_config_core_v3_Node* value) {
_upb_sethas(msg, 1);
@@ -828,6 +837,19 @@ UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_bootst
}
return sub;
}
+UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_listener_manager(envoy_config_bootstrap_v3_Bootstrap *msg, struct envoy_config_core_v3_TypedExtensionConfig* value) {
+ _upb_sethas(msg, 21);
+ *UPB_PTR_AT(msg, UPB_SIZE(152, 296), struct envoy_config_core_v3_TypedExtensionConfig*) = value;
+}
+UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_bootstrap_v3_Bootstrap_mutable_listener_manager(envoy_config_bootstrap_v3_Bootstrap* msg, upb_Arena* arena) {
+ struct envoy_config_core_v3_TypedExtensionConfig* sub = (struct envoy_config_core_v3_TypedExtensionConfig*)envoy_config_bootstrap_v3_Bootstrap_listener_manager(msg);
+ if (sub == NULL) {
+ sub = (struct envoy_config_core_v3_TypedExtensionConfig*)_upb_Message_New(&envoy_config_core_v3_TypedExtensionConfig_msginit, arena);
+ if (!sub) return NULL;
+ envoy_config_bootstrap_v3_Bootstrap_set_listener_manager(msg, sub);
+ }
+ return sub;
+}
/* envoy.config.bootstrap.v3.Bootstrap.StaticResources */
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c
index 5605081cdd..e4ae856c0a 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c
@@ -131,13 +131,14 @@ const upb_MiniTable envoy_config_core_v3_HttpProtocolOptions_msginit = {
UPB_SIZE(32, 48), 6, kUpb_ExtMode_NonExtendable, 6, 255, 0,
};
-static const upb_MiniTable_Sub envoy_config_core_v3_Http1ProtocolOptions_submsgs[3] = {
+static const upb_MiniTable_Sub envoy_config_core_v3_Http1ProtocolOptions_submsgs[4] = {
{.submsg = &google_protobuf_BoolValue_msginit},
{.submsg = &envoy_config_core_v3_Http1ProtocolOptions_HeaderKeyFormat_msginit},
{.submsg = &google_protobuf_BoolValue_msginit},
+ {.submsg = &google_protobuf_BoolValue_msginit},
};
-static const upb_MiniTable_Field envoy_config_core_v3_Http1ProtocolOptions__fields[8] = {
+static const upb_MiniTable_Field envoy_config_core_v3_Http1ProtocolOptions__fields[9] = {
{1, UPB_SIZE(8, 8), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{2, UPB_SIZE(1, 1), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
{3, UPB_SIZE(12, 16), UPB_SIZE(0, 0), kUpb_NoSub, 9, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
@@ -146,12 +147,13 @@ static const upb_MiniTable_Field envoy_config_core_v3_Http1ProtocolOptions__fiel
{6, UPB_SIZE(3, 3), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
{7, UPB_SIZE(24, 40), UPB_SIZE(3, 3), 2, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{8, UPB_SIZE(4, 4), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+ {9, UPB_SIZE(28, 48), UPB_SIZE(4, 4), 3, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
};
const upb_MiniTable envoy_config_core_v3_Http1ProtocolOptions_msginit = {
&envoy_config_core_v3_Http1ProtocolOptions_submsgs[0],
&envoy_config_core_v3_Http1ProtocolOptions__fields[0],
- UPB_SIZE(32, 48), 8, kUpb_ExtMode_NonExtendable, 8, 255, 0,
+ UPB_SIZE(32, 56), 9, kUpb_ExtMode_NonExtendable, 9, 255, 0,
};
static const upb_MiniTable_Sub envoy_config_core_v3_Http1ProtocolOptions_HeaderKeyFormat_submsgs[2] = {
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h
index c0342dd4ac..d7e59f8fbe 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h
@@ -845,6 +845,15 @@ UPB_INLINE void envoy_config_core_v3_Http1ProtocolOptions_clear_send_fully_quali
UPB_INLINE bool envoy_config_core_v3_Http1ProtocolOptions_send_fully_qualified_url(const envoy_config_core_v3_Http1ProtocolOptions* msg) {
return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool);
}
+UPB_INLINE bool envoy_config_core_v3_Http1ProtocolOptions_has_use_balsa_parser(const envoy_config_core_v3_Http1ProtocolOptions* msg) {
+ return _upb_hasbit(msg, 4);
+}
+UPB_INLINE void envoy_config_core_v3_Http1ProtocolOptions_clear_use_balsa_parser(const envoy_config_core_v3_Http1ProtocolOptions* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(28, 48), const upb_Message*) = NULL;
+}
+UPB_INLINE const struct google_protobuf_BoolValue* envoy_config_core_v3_Http1ProtocolOptions_use_balsa_parser(const envoy_config_core_v3_Http1ProtocolOptions* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(28, 48), const struct google_protobuf_BoolValue*);
+}
UPB_INLINE void envoy_config_core_v3_Http1ProtocolOptions_set_allow_absolute_url(envoy_config_core_v3_Http1ProtocolOptions *msg, struct google_protobuf_BoolValue* value) {
_upb_sethas(msg, 1);
@@ -900,6 +909,19 @@ UPB_INLINE struct google_protobuf_BoolValue* envoy_config_core_v3_Http1ProtocolO
UPB_INLINE void envoy_config_core_v3_Http1ProtocolOptions_set_send_fully_qualified_url(envoy_config_core_v3_Http1ProtocolOptions *msg, bool value) {
*UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value;
}
+UPB_INLINE void envoy_config_core_v3_Http1ProtocolOptions_set_use_balsa_parser(envoy_config_core_v3_Http1ProtocolOptions *msg, struct google_protobuf_BoolValue* value) {
+ _upb_sethas(msg, 4);
+ *UPB_PTR_AT(msg, UPB_SIZE(28, 48), struct google_protobuf_BoolValue*) = value;
+}
+UPB_INLINE struct google_protobuf_BoolValue* envoy_config_core_v3_Http1ProtocolOptions_mutable_use_balsa_parser(envoy_config_core_v3_Http1ProtocolOptions* msg, upb_Arena* arena) {
+ struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_config_core_v3_Http1ProtocolOptions_use_balsa_parser(msg);
+ if (sub == NULL) {
+ sub = (struct google_protobuf_BoolValue*)_upb_Message_New(&google_protobuf_BoolValue_msginit, arena);
+ if (!sub) return NULL;
+ envoy_config_core_v3_Http1ProtocolOptions_set_use_balsa_parser(msg, sub);
+ }
+ return sub;
+}
/* envoy.config.core.v3.Http1ProtocolOptions.HeaderKeyFormat */
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.c
index 00b25f1a83..a0548e3eb6 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.c
@@ -10,20 +10,38 @@
#include "upb/msg_internal.h"
#include "envoy/config/core/v3/proxy_protocol.upb.h"
#include "udpa/annotations/status.upb.h"
+#include "validate/validate.upb.h"
#include "upb/port_def.inc"
-static const upb_MiniTable_Field envoy_config_core_v3_ProxyProtocolConfig__fields[1] = {
+static const upb_MiniTable_Field envoy_config_core_v3_ProxyProtocolPassThroughTLVs__fields[2] = {
{1, UPB_SIZE(0, 0), UPB_SIZE(0, 0), kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+ {2, UPB_SIZE(4, 8), UPB_SIZE(0, 0), kUpb_NoSub, 13, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
};
-const upb_MiniTable envoy_config_core_v3_ProxyProtocolConfig_msginit = {
+const upb_MiniTable envoy_config_core_v3_ProxyProtocolPassThroughTLVs_msginit = {
NULL,
+ &envoy_config_core_v3_ProxyProtocolPassThroughTLVs__fields[0],
+ UPB_SIZE(8, 16), 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
+};
+
+static const upb_MiniTable_Sub envoy_config_core_v3_ProxyProtocolConfig_submsgs[1] = {
+ {.submsg = &envoy_config_core_v3_ProxyProtocolPassThroughTLVs_msginit},
+};
+
+static const upb_MiniTable_Field envoy_config_core_v3_ProxyProtocolConfig__fields[2] = {
+ {1, UPB_SIZE(4, 4), UPB_SIZE(0, 0), kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+ {2, UPB_SIZE(8, 8), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable envoy_config_core_v3_ProxyProtocolConfig_msginit = {
+ &envoy_config_core_v3_ProxyProtocolConfig_submsgs[0],
&envoy_config_core_v3_ProxyProtocolConfig__fields[0],
- UPB_SIZE(8, 8), 1, kUpb_ExtMode_NonExtendable, 1, 255, 0,
+ UPB_SIZE(16, 16), 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
};
-static const upb_MiniTable *messages_layout[1] = {
+static const upb_MiniTable *messages_layout[2] = {
+ &envoy_config_core_v3_ProxyProtocolPassThroughTLVs_msginit,
&envoy_config_core_v3_ProxyProtocolConfig_msginit,
};
@@ -31,7 +49,7 @@ const upb_MiniTable_File envoy_config_core_v3_proxy_protocol_proto_upb_file_layo
messages_layout,
NULL,
NULL,
- 1,
+ 2,
0,
0,
};
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.h
index 78a724a274..3962285c1c 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.h
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.h
@@ -20,8 +20,11 @@
extern "C" {
#endif
+struct envoy_config_core_v3_ProxyProtocolPassThroughTLVs;
struct envoy_config_core_v3_ProxyProtocolConfig;
+typedef struct envoy_config_core_v3_ProxyProtocolPassThroughTLVs envoy_config_core_v3_ProxyProtocolPassThroughTLVs;
typedef struct envoy_config_core_v3_ProxyProtocolConfig envoy_config_core_v3_ProxyProtocolConfig;
+extern const upb_MiniTable envoy_config_core_v3_ProxyProtocolPassThroughTLVs_msginit;
extern const upb_MiniTable envoy_config_core_v3_ProxyProtocolConfig_msginit;
typedef enum {
@@ -29,7 +32,73 @@ typedef enum {
envoy_config_core_v3_ProxyProtocolConfig_V2 = 1
} envoy_config_core_v3_ProxyProtocolConfig_Version;
+typedef enum {
+ envoy_config_core_v3_ProxyProtocolPassThroughTLVs_INCLUDE_ALL = 0,
+ envoy_config_core_v3_ProxyProtocolPassThroughTLVs_INCLUDE = 1
+} envoy_config_core_v3_ProxyProtocolPassThroughTLVs_PassTLVsMatchType;
+
+
+
+/* envoy.config.core.v3.ProxyProtocolPassThroughTLVs */
+
+UPB_INLINE envoy_config_core_v3_ProxyProtocolPassThroughTLVs* envoy_config_core_v3_ProxyProtocolPassThroughTLVs_new(upb_Arena* arena) {
+ return (envoy_config_core_v3_ProxyProtocolPassThroughTLVs*)_upb_Message_New(&envoy_config_core_v3_ProxyProtocolPassThroughTLVs_msginit, arena);
+}
+UPB_INLINE envoy_config_core_v3_ProxyProtocolPassThroughTLVs* envoy_config_core_v3_ProxyProtocolPassThroughTLVs_parse(const char* buf, size_t size, upb_Arena* arena) {
+ envoy_config_core_v3_ProxyProtocolPassThroughTLVs* ret = envoy_config_core_v3_ProxyProtocolPassThroughTLVs_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_config_core_v3_ProxyProtocolPassThroughTLVs_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE envoy_config_core_v3_ProxyProtocolPassThroughTLVs* envoy_config_core_v3_ProxyProtocolPassThroughTLVs_parse_ex(const char* buf, size_t size,
+ const upb_ExtensionRegistry* extreg,
+ int options, upb_Arena* arena) {
+ envoy_config_core_v3_ProxyProtocolPassThroughTLVs* ret = envoy_config_core_v3_ProxyProtocolPassThroughTLVs_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_config_core_v3_ProxyProtocolPassThroughTLVs_msginit, extreg, options, arena) !=
+ kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE char* envoy_config_core_v3_ProxyProtocolPassThroughTLVs_serialize(const envoy_config_core_v3_ProxyProtocolPassThroughTLVs* msg, upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_config_core_v3_ProxyProtocolPassThroughTLVs_msginit, 0, arena, &ptr, len);
+ return ptr;
+}
+UPB_INLINE char* envoy_config_core_v3_ProxyProtocolPassThroughTLVs_serialize_ex(const envoy_config_core_v3_ProxyProtocolPassThroughTLVs* msg, int options,
+ upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_config_core_v3_ProxyProtocolPassThroughTLVs_msginit, options, arena, &ptr, len);
+ return ptr;
+}
+UPB_INLINE void envoy_config_core_v3_ProxyProtocolPassThroughTLVs_clear_match_type(const envoy_config_core_v3_ProxyProtocolPassThroughTLVs* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t) = 0;
+}
+UPB_INLINE int32_t envoy_config_core_v3_ProxyProtocolPassThroughTLVs_match_type(const envoy_config_core_v3_ProxyProtocolPassThroughTLVs* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t);
+}
+UPB_INLINE void envoy_config_core_v3_ProxyProtocolPassThroughTLVs_clear_tlv_type(const envoy_config_core_v3_ProxyProtocolPassThroughTLVs* msg) {
+ _upb_array_detach(msg, UPB_SIZE(4, 8));
+}
+UPB_INLINE uint32_t const* envoy_config_core_v3_ProxyProtocolPassThroughTLVs_tlv_type(const envoy_config_core_v3_ProxyProtocolPassThroughTLVs* msg, size_t* len) {
+ return (uint32_t const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE void envoy_config_core_v3_ProxyProtocolPassThroughTLVs_set_match_type(envoy_config_core_v3_ProxyProtocolPassThroughTLVs *msg, int32_t value) {
+ *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t) = value;
+}
+UPB_INLINE uint32_t* envoy_config_core_v3_ProxyProtocolPassThroughTLVs_mutable_tlv_type(envoy_config_core_v3_ProxyProtocolPassThroughTLVs* msg, size_t* len) {
+ return (uint32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE uint32_t* envoy_config_core_v3_ProxyProtocolPassThroughTLVs_resize_tlv_type(envoy_config_core_v3_ProxyProtocolPassThroughTLVs* msg, size_t len, upb_Arena* arena) {
+ return (uint32_t*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(4, 8), len, 2, arena);
+}
+UPB_INLINE bool envoy_config_core_v3_ProxyProtocolPassThroughTLVs_add_tlv_type(envoy_config_core_v3_ProxyProtocolPassThroughTLVs* msg, uint32_t val, upb_Arena* arena) {
+ return _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 8), 2, &val, arena);
+}
/* envoy.config.core.v3.ProxyProtocolConfig */
@@ -67,14 +136,36 @@ UPB_INLINE char* envoy_config_core_v3_ProxyProtocolConfig_serialize_ex(const env
return ptr;
}
UPB_INLINE void envoy_config_core_v3_ProxyProtocolConfig_clear_version(const envoy_config_core_v3_ProxyProtocolConfig* msg) {
- *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t) = 0;
+ *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = 0;
}
UPB_INLINE int32_t envoy_config_core_v3_ProxyProtocolConfig_version(const envoy_config_core_v3_ProxyProtocolConfig* msg) {
- return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t);
+ return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t);
+}
+UPB_INLINE bool envoy_config_core_v3_ProxyProtocolConfig_has_pass_through_tlvs(const envoy_config_core_v3_ProxyProtocolConfig* msg) {
+ return _upb_hasbit(msg, 1);
+}
+UPB_INLINE void envoy_config_core_v3_ProxyProtocolConfig_clear_pass_through_tlvs(const envoy_config_core_v3_ProxyProtocolConfig* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(8, 8), const upb_Message*) = NULL;
+}
+UPB_INLINE const envoy_config_core_v3_ProxyProtocolPassThroughTLVs* envoy_config_core_v3_ProxyProtocolConfig_pass_through_tlvs(const envoy_config_core_v3_ProxyProtocolConfig* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), const envoy_config_core_v3_ProxyProtocolPassThroughTLVs*);
}
UPB_INLINE void envoy_config_core_v3_ProxyProtocolConfig_set_version(envoy_config_core_v3_ProxyProtocolConfig *msg, int32_t value) {
- *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t) = value;
+ *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void envoy_config_core_v3_ProxyProtocolConfig_set_pass_through_tlvs(envoy_config_core_v3_ProxyProtocolConfig *msg, envoy_config_core_v3_ProxyProtocolPassThroughTLVs* value) {
+ _upb_sethas(msg, 1);
+ *UPB_PTR_AT(msg, UPB_SIZE(8, 8), envoy_config_core_v3_ProxyProtocolPassThroughTLVs*) = value;
+}
+UPB_INLINE struct envoy_config_core_v3_ProxyProtocolPassThroughTLVs* envoy_config_core_v3_ProxyProtocolConfig_mutable_pass_through_tlvs(envoy_config_core_v3_ProxyProtocolConfig* msg, upb_Arena* arena) {
+ struct envoy_config_core_v3_ProxyProtocolPassThroughTLVs* sub = (struct envoy_config_core_v3_ProxyProtocolPassThroughTLVs*)envoy_config_core_v3_ProxyProtocolConfig_pass_through_tlvs(msg);
+ if (sub == NULL) {
+ sub = (struct envoy_config_core_v3_ProxyProtocolPassThroughTLVs*)_upb_Message_New(&envoy_config_core_v3_ProxyProtocolPassThroughTLVs_msginit, arena);
+ if (!sub) return NULL;
+ envoy_config_core_v3_ProxyProtocolConfig_set_pass_through_tlvs(msg, sub);
+ }
+ return sub;
}
extern const upb_MiniTable_File envoy_config_core_v3_proxy_protocol_proto_upb_file_layout;
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c
index 00774f6104..66d8ff7d59 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c
@@ -168,7 +168,25 @@ const upb_MiniTable envoy_config_listener_v3_Listener_InternalListenerConfig_msg
UPB_SIZE(0, 0), 0, kUpb_ExtMode_NonExtendable, 0, 255, 0,
};
-static const upb_MiniTable *messages_layout[7] = {
+const upb_MiniTable envoy_config_listener_v3_ListenerManager_msginit = {
+ NULL,
+ NULL,
+ UPB_SIZE(0, 0), 0, kUpb_ExtMode_NonExtendable, 0, 255, 0,
+};
+
+const upb_MiniTable envoy_config_listener_v3_ValidationListenerManager_msginit = {
+ NULL,
+ NULL,
+ UPB_SIZE(0, 0), 0, kUpb_ExtMode_NonExtendable, 0, 255, 0,
+};
+
+const upb_MiniTable envoy_config_listener_v3_ApiListenerManager_msginit = {
+ NULL,
+ NULL,
+ UPB_SIZE(0, 0), 0, kUpb_ExtMode_NonExtendable, 0, 255, 0,
+};
+
+static const upb_MiniTable *messages_layout[10] = {
&envoy_config_listener_v3_AdditionalAddress_msginit,
&envoy_config_listener_v3_ListenerCollection_msginit,
&envoy_config_listener_v3_Listener_msginit,
@@ -176,13 +194,16 @@ static const upb_MiniTable *messages_layout[7] = {
&envoy_config_listener_v3_Listener_ConnectionBalanceConfig_msginit,
&envoy_config_listener_v3_Listener_ConnectionBalanceConfig_ExactBalance_msginit,
&envoy_config_listener_v3_Listener_InternalListenerConfig_msginit,
+ &envoy_config_listener_v3_ListenerManager_msginit,
+ &envoy_config_listener_v3_ValidationListenerManager_msginit,
+ &envoy_config_listener_v3_ApiListenerManager_msginit,
};
const upb_MiniTable_File envoy_config_listener_v3_listener_proto_upb_file_layout = {
messages_layout,
NULL,
NULL,
- 7,
+ 10,
0,
0,
};
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h
index aa68801efb..fdb3609b39 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h
@@ -27,6 +27,9 @@ struct envoy_config_listener_v3_Listener_DeprecatedV1;
struct envoy_config_listener_v3_Listener_ConnectionBalanceConfig;
struct envoy_config_listener_v3_Listener_ConnectionBalanceConfig_ExactBalance;
struct envoy_config_listener_v3_Listener_InternalListenerConfig;
+struct envoy_config_listener_v3_ListenerManager;
+struct envoy_config_listener_v3_ValidationListenerManager;
+struct envoy_config_listener_v3_ApiListenerManager;
typedef struct envoy_config_listener_v3_AdditionalAddress envoy_config_listener_v3_AdditionalAddress;
typedef struct envoy_config_listener_v3_ListenerCollection envoy_config_listener_v3_ListenerCollection;
typedef struct envoy_config_listener_v3_Listener envoy_config_listener_v3_Listener;
@@ -34,6 +37,9 @@ typedef struct envoy_config_listener_v3_Listener_DeprecatedV1 envoy_config_liste
typedef struct envoy_config_listener_v3_Listener_ConnectionBalanceConfig envoy_config_listener_v3_Listener_ConnectionBalanceConfig;
typedef struct envoy_config_listener_v3_Listener_ConnectionBalanceConfig_ExactBalance envoy_config_listener_v3_Listener_ConnectionBalanceConfig_ExactBalance;
typedef struct envoy_config_listener_v3_Listener_InternalListenerConfig envoy_config_listener_v3_Listener_InternalListenerConfig;
+typedef struct envoy_config_listener_v3_ListenerManager envoy_config_listener_v3_ListenerManager;
+typedef struct envoy_config_listener_v3_ValidationListenerManager envoy_config_listener_v3_ValidationListenerManager;
+typedef struct envoy_config_listener_v3_ApiListenerManager envoy_config_listener_v3_ApiListenerManager;
extern const upb_MiniTable envoy_config_listener_v3_AdditionalAddress_msginit;
extern const upb_MiniTable envoy_config_listener_v3_ListenerCollection_msginit;
extern const upb_MiniTable envoy_config_listener_v3_Listener_msginit;
@@ -41,6 +47,9 @@ extern const upb_MiniTable envoy_config_listener_v3_Listener_DeprecatedV1_msgini
extern const upb_MiniTable envoy_config_listener_v3_Listener_ConnectionBalanceConfig_msginit;
extern const upb_MiniTable envoy_config_listener_v3_Listener_ConnectionBalanceConfig_ExactBalance_msginit;
extern const upb_MiniTable envoy_config_listener_v3_Listener_InternalListenerConfig_msginit;
+extern const upb_MiniTable envoy_config_listener_v3_ListenerManager_msginit;
+extern const upb_MiniTable envoy_config_listener_v3_ValidationListenerManager_msginit;
+extern const upb_MiniTable envoy_config_listener_v3_ApiListenerManager_msginit;
struct envoy_config_accesslog_v3_AccessLog;
struct envoy_config_core_v3_Address;
struct envoy_config_core_v3_Metadata;
@@ -1054,6 +1063,117 @@ UPB_INLINE char* envoy_config_listener_v3_Listener_InternalListenerConfig_serial
}
+/* envoy.config.listener.v3.ListenerManager */
+
+UPB_INLINE envoy_config_listener_v3_ListenerManager* envoy_config_listener_v3_ListenerManager_new(upb_Arena* arena) {
+ return (envoy_config_listener_v3_ListenerManager*)_upb_Message_New(&envoy_config_listener_v3_ListenerManager_msginit, arena);
+}
+UPB_INLINE envoy_config_listener_v3_ListenerManager* envoy_config_listener_v3_ListenerManager_parse(const char* buf, size_t size, upb_Arena* arena) {
+ envoy_config_listener_v3_ListenerManager* ret = envoy_config_listener_v3_ListenerManager_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_config_listener_v3_ListenerManager_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE envoy_config_listener_v3_ListenerManager* envoy_config_listener_v3_ListenerManager_parse_ex(const char* buf, size_t size,
+ const upb_ExtensionRegistry* extreg,
+ int options, upb_Arena* arena) {
+ envoy_config_listener_v3_ListenerManager* ret = envoy_config_listener_v3_ListenerManager_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_config_listener_v3_ListenerManager_msginit, extreg, options, arena) !=
+ kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE char* envoy_config_listener_v3_ListenerManager_serialize(const envoy_config_listener_v3_ListenerManager* msg, upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_config_listener_v3_ListenerManager_msginit, 0, arena, &ptr, len);
+ return ptr;
+}
+UPB_INLINE char* envoy_config_listener_v3_ListenerManager_serialize_ex(const envoy_config_listener_v3_ListenerManager* msg, int options,
+ upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_config_listener_v3_ListenerManager_msginit, options, arena, &ptr, len);
+ return ptr;
+}
+
+
+/* envoy.config.listener.v3.ValidationListenerManager */
+
+UPB_INLINE envoy_config_listener_v3_ValidationListenerManager* envoy_config_listener_v3_ValidationListenerManager_new(upb_Arena* arena) {
+ return (envoy_config_listener_v3_ValidationListenerManager*)_upb_Message_New(&envoy_config_listener_v3_ValidationListenerManager_msginit, arena);
+}
+UPB_INLINE envoy_config_listener_v3_ValidationListenerManager* envoy_config_listener_v3_ValidationListenerManager_parse(const char* buf, size_t size, upb_Arena* arena) {
+ envoy_config_listener_v3_ValidationListenerManager* ret = envoy_config_listener_v3_ValidationListenerManager_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_config_listener_v3_ValidationListenerManager_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE envoy_config_listener_v3_ValidationListenerManager* envoy_config_listener_v3_ValidationListenerManager_parse_ex(const char* buf, size_t size,
+ const upb_ExtensionRegistry* extreg,
+ int options, upb_Arena* arena) {
+ envoy_config_listener_v3_ValidationListenerManager* ret = envoy_config_listener_v3_ValidationListenerManager_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_config_listener_v3_ValidationListenerManager_msginit, extreg, options, arena) !=
+ kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE char* envoy_config_listener_v3_ValidationListenerManager_serialize(const envoy_config_listener_v3_ValidationListenerManager* msg, upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_config_listener_v3_ValidationListenerManager_msginit, 0, arena, &ptr, len);
+ return ptr;
+}
+UPB_INLINE char* envoy_config_listener_v3_ValidationListenerManager_serialize_ex(const envoy_config_listener_v3_ValidationListenerManager* msg, int options,
+ upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_config_listener_v3_ValidationListenerManager_msginit, options, arena, &ptr, len);
+ return ptr;
+}
+
+
+/* envoy.config.listener.v3.ApiListenerManager */
+
+UPB_INLINE envoy_config_listener_v3_ApiListenerManager* envoy_config_listener_v3_ApiListenerManager_new(upb_Arena* arena) {
+ return (envoy_config_listener_v3_ApiListenerManager*)_upb_Message_New(&envoy_config_listener_v3_ApiListenerManager_msginit, arena);
+}
+UPB_INLINE envoy_config_listener_v3_ApiListenerManager* envoy_config_listener_v3_ApiListenerManager_parse(const char* buf, size_t size, upb_Arena* arena) {
+ envoy_config_listener_v3_ApiListenerManager* ret = envoy_config_listener_v3_ApiListenerManager_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_config_listener_v3_ApiListenerManager_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE envoy_config_listener_v3_ApiListenerManager* envoy_config_listener_v3_ApiListenerManager_parse_ex(const char* buf, size_t size,
+ const upb_ExtensionRegistry* extreg,
+ int options, upb_Arena* arena) {
+ envoy_config_listener_v3_ApiListenerManager* ret = envoy_config_listener_v3_ApiListenerManager_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_config_listener_v3_ApiListenerManager_msginit, extreg, options, arena) !=
+ kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE char* envoy_config_listener_v3_ApiListenerManager_serialize(const envoy_config_listener_v3_ApiListenerManager* msg, upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_config_listener_v3_ApiListenerManager_msginit, 0, arena, &ptr, len);
+ return ptr;
+}
+UPB_INLINE char* envoy_config_listener_v3_ApiListenerManager_serialize_ex(const envoy_config_listener_v3_ApiListenerManager* msg, int options,
+ upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_config_listener_v3_ApiListenerManager_msginit, options, arena, &ptr, len);
+ return ptr;
+}
+
+
extern const upb_MiniTable_File envoy_config_listener_v3_listener_proto_upb_file_layout;
#ifdef __cplusplus
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.c
index b5a49feca1..9b691c4eb4 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.c
@@ -14,13 +14,14 @@
#include "envoy/config/core/v3/protocol.upb.h"
#include "google/protobuf/duration.upb.h"
#include "google/protobuf/wrappers.upb.h"
+#include "xds/annotations/v3/status.upb.h"
#include "udpa/annotations/status.upb.h"
#include "udpa/annotations/versioning.upb.h"
#include "validate/validate.upb.h"
#include "upb/port_def.inc"
-static const upb_MiniTable_Sub envoy_config_listener_v3_QuicProtocolOptions_submsgs[8] = {
+static const upb_MiniTable_Sub envoy_config_listener_v3_QuicProtocolOptions_submsgs[9] = {
{.submsg = &envoy_config_core_v3_QuicProtocolOptions_msginit},
{.submsg = &google_protobuf_Duration_msginit},
{.submsg = &google_protobuf_Duration_msginit},
@@ -29,9 +30,10 @@ static const upb_MiniTable_Sub envoy_config_listener_v3_QuicProtocolOptions_subm
{.submsg = &envoy_config_core_v3_TypedExtensionConfig_msginit},
{.submsg = &envoy_config_core_v3_TypedExtensionConfig_msginit},
{.submsg = &envoy_config_core_v3_TypedExtensionConfig_msginit},
+ {.submsg = &envoy_config_core_v3_TypedExtensionConfig_msginit},
};
-static const upb_MiniTable_Field envoy_config_listener_v3_QuicProtocolOptions__fields[8] = {
+static const upb_MiniTable_Field envoy_config_listener_v3_QuicProtocolOptions__fields[9] = {
{1, UPB_SIZE(4, 8), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{2, UPB_SIZE(8, 16), UPB_SIZE(2, 2), 1, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{3, UPB_SIZE(12, 24), UPB_SIZE(3, 3), 2, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
@@ -40,12 +42,13 @@ static const upb_MiniTable_Field envoy_config_listener_v3_QuicProtocolOptions__f
{6, UPB_SIZE(24, 48), UPB_SIZE(6, 6), 5, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{7, UPB_SIZE(28, 56), UPB_SIZE(7, 7), 6, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{8, UPB_SIZE(32, 64), UPB_SIZE(8, 8), 7, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+ {9, UPB_SIZE(36, 72), UPB_SIZE(9, 9), 8, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
};
const upb_MiniTable envoy_config_listener_v3_QuicProtocolOptions_msginit = {
&envoy_config_listener_v3_QuicProtocolOptions_submsgs[0],
&envoy_config_listener_v3_QuicProtocolOptions__fields[0],
- UPB_SIZE(40, 72), 8, kUpb_ExtMode_NonExtendable, 8, 255, 0,
+ UPB_SIZE(40, 80), 9, kUpb_ExtMode_NonExtendable, 9, 255, 0,
};
static const upb_MiniTable *messages_layout[1] = {
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.h
index 973f2cffb6..8cd563fe0d 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.h
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/listener/v3/quic_config.upb.h
@@ -143,6 +143,15 @@ UPB_INLINE void envoy_config_listener_v3_QuicProtocolOptions_clear_connection_id
UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_listener_v3_QuicProtocolOptions_connection_id_generator_config(const envoy_config_listener_v3_QuicProtocolOptions* msg) {
return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const struct envoy_config_core_v3_TypedExtensionConfig*);
}
+UPB_INLINE bool envoy_config_listener_v3_QuicProtocolOptions_has_server_preferred_address_config(const envoy_config_listener_v3_QuicProtocolOptions* msg) {
+ return _upb_hasbit(msg, 9);
+}
+UPB_INLINE void envoy_config_listener_v3_QuicProtocolOptions_clear_server_preferred_address_config(const envoy_config_listener_v3_QuicProtocolOptions* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(36, 72), const upb_Message*) = NULL;
+}
+UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_listener_v3_QuicProtocolOptions_server_preferred_address_config(const envoy_config_listener_v3_QuicProtocolOptions* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(36, 72), const struct envoy_config_core_v3_TypedExtensionConfig*);
+}
UPB_INLINE void envoy_config_listener_v3_QuicProtocolOptions_set_quic_protocol_options(envoy_config_listener_v3_QuicProtocolOptions *msg, struct envoy_config_core_v3_QuicProtocolOptions* value) {
_upb_sethas(msg, 1);
@@ -248,6 +257,19 @@ UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_listen
}
return sub;
}
+UPB_INLINE void envoy_config_listener_v3_QuicProtocolOptions_set_server_preferred_address_config(envoy_config_listener_v3_QuicProtocolOptions *msg, struct envoy_config_core_v3_TypedExtensionConfig* value) {
+ _upb_sethas(msg, 9);
+ *UPB_PTR_AT(msg, UPB_SIZE(36, 72), struct envoy_config_core_v3_TypedExtensionConfig*) = value;
+}
+UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_listener_v3_QuicProtocolOptions_mutable_server_preferred_address_config(envoy_config_listener_v3_QuicProtocolOptions* msg, upb_Arena* arena) {
+ struct envoy_config_core_v3_TypedExtensionConfig* sub = (struct envoy_config_core_v3_TypedExtensionConfig*)envoy_config_listener_v3_QuicProtocolOptions_server_preferred_address_config(msg);
+ if (sub == NULL) {
+ sub = (struct envoy_config_core_v3_TypedExtensionConfig*)_upb_Message_New(&envoy_config_core_v3_TypedExtensionConfig_msginit, arena);
+ if (!sub) return NULL;
+ envoy_config_listener_v3_QuicProtocolOptions_set_server_preferred_address_config(msg, sub);
+ }
+ return sub;
+}
extern const upb_MiniTable_File envoy_config_listener_v3_quic_config_proto_upb_file_layout;
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c
index b8b8fbee00..4166b86da8 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c
@@ -27,18 +27,35 @@
#include "upb/port_def.inc"
-static const upb_MiniTable_Sub envoy_config_rbac_v3_RBAC_submsgs[1] = {
+static const upb_MiniTable_Sub envoy_config_rbac_v3_RBAC_submsgs[2] = {
{.submsg = &envoy_config_rbac_v3_RBAC_PoliciesEntry_msginit},
+ {.submsg = &envoy_config_rbac_v3_RBAC_AuditLoggingOptions_msginit},
};
-static const upb_MiniTable_Field envoy_config_rbac_v3_RBAC__fields[2] = {
- {1, UPB_SIZE(0, 0), UPB_SIZE(0, 0), kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
- {2, UPB_SIZE(4, 8), UPB_SIZE(0, 0), 0, 11, kUpb_FieldMode_Map | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+static const upb_MiniTable_Field envoy_config_rbac_v3_RBAC__fields[3] = {
+ {1, UPB_SIZE(4, 4), UPB_SIZE(0, 0), kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+ {2, UPB_SIZE(8, 8), UPB_SIZE(0, 0), 0, 11, kUpb_FieldMode_Map | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+ {3, UPB_SIZE(12, 16), UPB_SIZE(1, 1), 1, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
};
const upb_MiniTable envoy_config_rbac_v3_RBAC_msginit = {
&envoy_config_rbac_v3_RBAC_submsgs[0],
&envoy_config_rbac_v3_RBAC__fields[0],
+ UPB_SIZE(16, 24), 3, kUpb_ExtMode_NonExtendable, 3, 255, 0,
+};
+
+static const upb_MiniTable_Sub envoy_config_rbac_v3_RBAC_AuditLoggingOptions_submsgs[1] = {
+ {.submsg = &envoy_config_core_v3_TypedExtensionConfig_msginit},
+};
+
+static const upb_MiniTable_Field envoy_config_rbac_v3_RBAC_AuditLoggingOptions__fields[2] = {
+ {1, UPB_SIZE(0, 0), UPB_SIZE(0, 0), kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+ {2, UPB_SIZE(4, 8), UPB_SIZE(0, 0), 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable envoy_config_rbac_v3_RBAC_AuditLoggingOptions_msginit = {
+ &envoy_config_rbac_v3_RBAC_AuditLoggingOptions_submsgs[0],
+ &envoy_config_rbac_v3_RBAC_AuditLoggingOptions__fields[0],
UPB_SIZE(8, 16), 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
};
@@ -199,8 +216,9 @@ const upb_MiniTable envoy_config_rbac_v3_Action_msginit = {
UPB_SIZE(16, 24), 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
};
-static const upb_MiniTable *messages_layout[9] = {
+static const upb_MiniTable *messages_layout[10] = {
&envoy_config_rbac_v3_RBAC_msginit,
+ &envoy_config_rbac_v3_RBAC_AuditLoggingOptions_msginit,
&envoy_config_rbac_v3_RBAC_PoliciesEntry_msginit,
&envoy_config_rbac_v3_Policy_msginit,
&envoy_config_rbac_v3_Permission_msginit,
@@ -215,7 +233,7 @@ const upb_MiniTable_File envoy_config_rbac_v3_rbac_proto_upb_file_layout = {
messages_layout,
NULL,
NULL,
- 9,
+ 10,
0,
0,
};
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h
index 705b29d23a..9ca05e19ae 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h
@@ -21,6 +21,7 @@ extern "C" {
#endif
struct envoy_config_rbac_v3_RBAC;
+struct envoy_config_rbac_v3_RBAC_AuditLoggingOptions;
struct envoy_config_rbac_v3_RBAC_PoliciesEntry;
struct envoy_config_rbac_v3_Policy;
struct envoy_config_rbac_v3_Permission;
@@ -30,6 +31,7 @@ struct envoy_config_rbac_v3_Principal_Set;
struct envoy_config_rbac_v3_Principal_Authenticated;
struct envoy_config_rbac_v3_Action;
typedef struct envoy_config_rbac_v3_RBAC envoy_config_rbac_v3_RBAC;
+typedef struct envoy_config_rbac_v3_RBAC_AuditLoggingOptions envoy_config_rbac_v3_RBAC_AuditLoggingOptions;
typedef struct envoy_config_rbac_v3_RBAC_PoliciesEntry envoy_config_rbac_v3_RBAC_PoliciesEntry;
typedef struct envoy_config_rbac_v3_Policy envoy_config_rbac_v3_Policy;
typedef struct envoy_config_rbac_v3_Permission envoy_config_rbac_v3_Permission;
@@ -39,6 +41,7 @@ typedef struct envoy_config_rbac_v3_Principal_Set envoy_config_rbac_v3_Principal
typedef struct envoy_config_rbac_v3_Principal_Authenticated envoy_config_rbac_v3_Principal_Authenticated;
typedef struct envoy_config_rbac_v3_Action envoy_config_rbac_v3_Action;
extern const upb_MiniTable envoy_config_rbac_v3_RBAC_msginit;
+extern const upb_MiniTable envoy_config_rbac_v3_RBAC_AuditLoggingOptions_msginit;
extern const upb_MiniTable envoy_config_rbac_v3_RBAC_PoliciesEntry_msginit;
extern const upb_MiniTable envoy_config_rbac_v3_Policy_msginit;
extern const upb_MiniTable envoy_config_rbac_v3_Permission_msginit;
@@ -74,6 +77,13 @@ typedef enum {
envoy_config_rbac_v3_RBAC_LOG = 2
} envoy_config_rbac_v3_RBAC_Action;
+typedef enum {
+ envoy_config_rbac_v3_RBAC_AuditLoggingOptions_NONE = 0,
+ envoy_config_rbac_v3_RBAC_AuditLoggingOptions_ON_DENY = 1,
+ envoy_config_rbac_v3_RBAC_AuditLoggingOptions_ON_ALLOW = 2,
+ envoy_config_rbac_v3_RBAC_AuditLoggingOptions_ON_DENY_AND_ALLOW = 3
+} envoy_config_rbac_v3_RBAC_AuditLoggingOptions_AuditCondition;
+
/* envoy.config.rbac.v3.RBAC */
@@ -112,39 +122,128 @@ UPB_INLINE char* envoy_config_rbac_v3_RBAC_serialize_ex(const envoy_config_rbac_
return ptr;
}
UPB_INLINE void envoy_config_rbac_v3_RBAC_clear_action(const envoy_config_rbac_v3_RBAC* msg) {
- *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t) = 0;
+ *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = 0;
}
UPB_INLINE int32_t envoy_config_rbac_v3_RBAC_action(const envoy_config_rbac_v3_RBAC* msg) {
- return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t);
+ return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t);
}
UPB_INLINE bool envoy_config_rbac_v3_RBAC_has_policies(const envoy_config_rbac_v3_RBAC* msg) {
- return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8));
+ return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 8));
}
UPB_INLINE void envoy_config_rbac_v3_RBAC_clear_policies(const envoy_config_rbac_v3_RBAC* msg) {
- _upb_array_detach(msg, UPB_SIZE(4, 8));
+ _upb_array_detach(msg, UPB_SIZE(8, 8));
}
UPB_INLINE size_t envoy_config_rbac_v3_RBAC_policies_size(const envoy_config_rbac_v3_RBAC* msg) {
- return _upb_msg_map_size(msg, UPB_SIZE(4, 8));
+ return _upb_msg_map_size(msg, UPB_SIZE(8, 8));
}
UPB_INLINE bool envoy_config_rbac_v3_RBAC_policies_get(const envoy_config_rbac_v3_RBAC* msg, upb_StringView key, envoy_config_rbac_v3_Policy** val) {
- return _upb_msg_map_get(msg, UPB_SIZE(4, 8), &key, 0, val, sizeof(*val));
+ return _upb_msg_map_get(msg, UPB_SIZE(8, 8), &key, 0, val, sizeof(*val));
}
UPB_INLINE const envoy_config_rbac_v3_RBAC_PoliciesEntry* envoy_config_rbac_v3_RBAC_policies_next(const envoy_config_rbac_v3_RBAC* msg, size_t* iter) {
- return (const envoy_config_rbac_v3_RBAC_PoliciesEntry*)_upb_msg_map_next(msg, UPB_SIZE(4, 8), iter);
+ return (const envoy_config_rbac_v3_RBAC_PoliciesEntry*)_upb_msg_map_next(msg, UPB_SIZE(8, 8), iter);
+}
+UPB_INLINE bool envoy_config_rbac_v3_RBAC_has_audit_logging_options(const envoy_config_rbac_v3_RBAC* msg) {
+ return _upb_hasbit(msg, 1);
+}
+UPB_INLINE void envoy_config_rbac_v3_RBAC_clear_audit_logging_options(const envoy_config_rbac_v3_RBAC* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const upb_Message*) = NULL;
+}
+UPB_INLINE const envoy_config_rbac_v3_RBAC_AuditLoggingOptions* envoy_config_rbac_v3_RBAC_audit_logging_options(const envoy_config_rbac_v3_RBAC* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const envoy_config_rbac_v3_RBAC_AuditLoggingOptions*);
}
UPB_INLINE void envoy_config_rbac_v3_RBAC_set_action(envoy_config_rbac_v3_RBAC *msg, int32_t value) {
- *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t) = value;
+ *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
}
-UPB_INLINE void envoy_config_rbac_v3_RBAC_policies_clear(envoy_config_rbac_v3_RBAC* msg) { _upb_msg_map_clear(msg, UPB_SIZE(4, 8)); }
+UPB_INLINE void envoy_config_rbac_v3_RBAC_policies_clear(envoy_config_rbac_v3_RBAC* msg) { _upb_msg_map_clear(msg, UPB_SIZE(8, 8)); }
UPB_INLINE bool envoy_config_rbac_v3_RBAC_policies_set(envoy_config_rbac_v3_RBAC* msg, upb_StringView key, envoy_config_rbac_v3_Policy* val, upb_Arena* a) {
- return _upb_msg_map_set(msg, UPB_SIZE(4, 8), &key, 0, &val, sizeof(val), a);
+ return _upb_msg_map_set(msg, UPB_SIZE(8, 8), &key, 0, &val, sizeof(val), a);
}
UPB_INLINE bool envoy_config_rbac_v3_RBAC_policies_delete(envoy_config_rbac_v3_RBAC* msg, upb_StringView key) {
- return _upb_msg_map_delete(msg, UPB_SIZE(4, 8), &key, 0);
+ return _upb_msg_map_delete(msg, UPB_SIZE(8, 8), &key, 0);
}
UPB_INLINE envoy_config_rbac_v3_RBAC_PoliciesEntry* envoy_config_rbac_v3_RBAC_policies_nextmutable(envoy_config_rbac_v3_RBAC* msg, size_t* iter) {
- return (envoy_config_rbac_v3_RBAC_PoliciesEntry*)_upb_msg_map_next(msg, UPB_SIZE(4, 8), iter);
+ return (envoy_config_rbac_v3_RBAC_PoliciesEntry*)_upb_msg_map_next(msg, UPB_SIZE(8, 8), iter);
+}
+UPB_INLINE void envoy_config_rbac_v3_RBAC_set_audit_logging_options(envoy_config_rbac_v3_RBAC *msg, envoy_config_rbac_v3_RBAC_AuditLoggingOptions* value) {
+ _upb_sethas(msg, 1);
+ *UPB_PTR_AT(msg, UPB_SIZE(12, 16), envoy_config_rbac_v3_RBAC_AuditLoggingOptions*) = value;
+}
+UPB_INLINE struct envoy_config_rbac_v3_RBAC_AuditLoggingOptions* envoy_config_rbac_v3_RBAC_mutable_audit_logging_options(envoy_config_rbac_v3_RBAC* msg, upb_Arena* arena) {
+ struct envoy_config_rbac_v3_RBAC_AuditLoggingOptions* sub = (struct envoy_config_rbac_v3_RBAC_AuditLoggingOptions*)envoy_config_rbac_v3_RBAC_audit_logging_options(msg);
+ if (sub == NULL) {
+ sub = (struct envoy_config_rbac_v3_RBAC_AuditLoggingOptions*)_upb_Message_New(&envoy_config_rbac_v3_RBAC_AuditLoggingOptions_msginit, arena);
+ if (!sub) return NULL;
+ envoy_config_rbac_v3_RBAC_set_audit_logging_options(msg, sub);
+ }
+ return sub;
+}
+
+/* envoy.config.rbac.v3.RBAC.AuditLoggingOptions */
+
+UPB_INLINE envoy_config_rbac_v3_RBAC_AuditLoggingOptions* envoy_config_rbac_v3_RBAC_AuditLoggingOptions_new(upb_Arena* arena) {
+ return (envoy_config_rbac_v3_RBAC_AuditLoggingOptions*)_upb_Message_New(&envoy_config_rbac_v3_RBAC_AuditLoggingOptions_msginit, arena);
+}
+UPB_INLINE envoy_config_rbac_v3_RBAC_AuditLoggingOptions* envoy_config_rbac_v3_RBAC_AuditLoggingOptions_parse(const char* buf, size_t size, upb_Arena* arena) {
+ envoy_config_rbac_v3_RBAC_AuditLoggingOptions* ret = envoy_config_rbac_v3_RBAC_AuditLoggingOptions_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_config_rbac_v3_RBAC_AuditLoggingOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE envoy_config_rbac_v3_RBAC_AuditLoggingOptions* envoy_config_rbac_v3_RBAC_AuditLoggingOptions_parse_ex(const char* buf, size_t size,
+ const upb_ExtensionRegistry* extreg,
+ int options, upb_Arena* arena) {
+ envoy_config_rbac_v3_RBAC_AuditLoggingOptions* ret = envoy_config_rbac_v3_RBAC_AuditLoggingOptions_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_config_rbac_v3_RBAC_AuditLoggingOptions_msginit, extreg, options, arena) !=
+ kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE char* envoy_config_rbac_v3_RBAC_AuditLoggingOptions_serialize(const envoy_config_rbac_v3_RBAC_AuditLoggingOptions* msg, upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_config_rbac_v3_RBAC_AuditLoggingOptions_msginit, 0, arena, &ptr, len);
+ return ptr;
+}
+UPB_INLINE char* envoy_config_rbac_v3_RBAC_AuditLoggingOptions_serialize_ex(const envoy_config_rbac_v3_RBAC_AuditLoggingOptions* msg, int options,
+ upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_config_rbac_v3_RBAC_AuditLoggingOptions_msginit, options, arena, &ptr, len);
+ return ptr;
+}
+UPB_INLINE void envoy_config_rbac_v3_RBAC_AuditLoggingOptions_clear_audit_condition(const envoy_config_rbac_v3_RBAC_AuditLoggingOptions* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t) = 0;
+}
+UPB_INLINE int32_t envoy_config_rbac_v3_RBAC_AuditLoggingOptions_audit_condition(const envoy_config_rbac_v3_RBAC_AuditLoggingOptions* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t);
+}
+UPB_INLINE bool envoy_config_rbac_v3_RBAC_AuditLoggingOptions_has_audit_loggers(const envoy_config_rbac_v3_RBAC_AuditLoggingOptions* msg) {
+ return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8));
+}
+UPB_INLINE void envoy_config_rbac_v3_RBAC_AuditLoggingOptions_clear_audit_loggers(const envoy_config_rbac_v3_RBAC_AuditLoggingOptions* msg) {
+ _upb_array_detach(msg, UPB_SIZE(4, 8));
+}
+UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* const* envoy_config_rbac_v3_RBAC_AuditLoggingOptions_audit_loggers(const envoy_config_rbac_v3_RBAC_AuditLoggingOptions* msg, size_t* len) {
+ return (const struct envoy_config_core_v3_TypedExtensionConfig* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len);
+}
+
+UPB_INLINE void envoy_config_rbac_v3_RBAC_AuditLoggingOptions_set_audit_condition(envoy_config_rbac_v3_RBAC_AuditLoggingOptions *msg, int32_t value) {
+ *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t) = value;
+}
+UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig** envoy_config_rbac_v3_RBAC_AuditLoggingOptions_mutable_audit_loggers(envoy_config_rbac_v3_RBAC_AuditLoggingOptions* msg, size_t* len) {
+ return (struct envoy_config_core_v3_TypedExtensionConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig** envoy_config_rbac_v3_RBAC_AuditLoggingOptions_resize_audit_loggers(envoy_config_rbac_v3_RBAC_AuditLoggingOptions* msg, size_t len, upb_Arena* arena) {
+ return (struct envoy_config_core_v3_TypedExtensionConfig**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_rbac_v3_RBAC_AuditLoggingOptions_add_audit_loggers(envoy_config_rbac_v3_RBAC_AuditLoggingOptions* msg, upb_Arena* arena) {
+ struct envoy_config_core_v3_TypedExtensionConfig* sub = (struct envoy_config_core_v3_TypedExtensionConfig*)_upb_Message_New(&envoy_config_core_v3_TypedExtensionConfig_msginit, arena);
+ bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
+ if (!ok) return NULL;
+ return sub;
}
/* envoy.config.rbac.v3.RBAC.PoliciesEntry */
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c
index cb10e3830b..d2b3c084a3 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c
@@ -930,17 +930,18 @@ static const upb_MiniTable_Sub envoy_config_route_v3_RateLimit_Action_MetaData_s
{.submsg = &envoy_type_metadata_v3_MetadataKey_msginit},
};
-static const upb_MiniTable_Field envoy_config_route_v3_RateLimit_Action_MetaData__fields[4] = {
- {1, UPB_SIZE(8, 8), UPB_SIZE(0, 0), kUpb_NoSub, 9, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
- {2, UPB_SIZE(16, 24), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
- {3, UPB_SIZE(20, 32), UPB_SIZE(0, 0), kUpb_NoSub, 9, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+static const upb_MiniTable_Field envoy_config_route_v3_RateLimit_Action_MetaData__fields[5] = {
+ {1, UPB_SIZE(12, 16), UPB_SIZE(0, 0), kUpb_NoSub, 9, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+ {2, UPB_SIZE(20, 32), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+ {3, UPB_SIZE(24, 40), UPB_SIZE(0, 0), kUpb_NoSub, 9, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
{4, UPB_SIZE(4, 4), UPB_SIZE(0, 0), kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+ {5, UPB_SIZE(8, 8), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
};
const upb_MiniTable envoy_config_route_v3_RateLimit_Action_MetaData_msginit = {
&envoy_config_route_v3_RateLimit_Action_MetaData_submsgs[0],
&envoy_config_route_v3_RateLimit_Action_MetaData__fields[0],
- UPB_SIZE(32, 48), 4, kUpb_ExtMode_NonExtendable, 4, 255, 0,
+ UPB_SIZE(32, 56), 5, kUpb_ExtMode_NonExtendable, 5, 255, 0,
};
static const upb_MiniTable_Sub envoy_config_route_v3_RateLimit_Action_QueryParameterValueMatch_submsgs[2] = {
@@ -1053,15 +1054,16 @@ static const upb_MiniTable_Sub envoy_config_route_v3_FilterConfig_submsgs[1] = {
{.submsg = &google_protobuf_Any_msginit},
};
-static const upb_MiniTable_Field envoy_config_route_v3_FilterConfig__fields[2] = {
+static const upb_MiniTable_Field envoy_config_route_v3_FilterConfig__fields[3] = {
{1, UPB_SIZE(4, 8), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{2, UPB_SIZE(1, 1), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+ {3, UPB_SIZE(2, 2), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
};
const upb_MiniTable envoy_config_route_v3_FilterConfig_msginit = {
&envoy_config_route_v3_FilterConfig_submsgs[0],
&envoy_config_route_v3_FilterConfig__fields[0],
- UPB_SIZE(8, 16), 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
+ UPB_SIZE(8, 16), 3, kUpb_ExtMode_NonExtendable, 3, 255, 0,
};
static const upb_MiniTable *messages_layout[57] = {
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h
index a4acf1b96c..fe44a874be 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h
@@ -5934,25 +5934,25 @@ UPB_INLINE char* envoy_config_route_v3_RateLimit_Action_MetaData_serialize_ex(co
return ptr;
}
UPB_INLINE void envoy_config_route_v3_RateLimit_Action_MetaData_clear_descriptor_key(const envoy_config_route_v3_RateLimit_Action_MetaData* msg) {
- *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_StringView) = upb_StringView_FromDataAndSize(NULL, 0);
+ *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_StringView) = upb_StringView_FromDataAndSize(NULL, 0);
}
UPB_INLINE upb_StringView envoy_config_route_v3_RateLimit_Action_MetaData_descriptor_key(const envoy_config_route_v3_RateLimit_Action_MetaData* msg) {
- return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_StringView);
+ return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_StringView);
}
UPB_INLINE bool envoy_config_route_v3_RateLimit_Action_MetaData_has_metadata_key(const envoy_config_route_v3_RateLimit_Action_MetaData* msg) {
return _upb_hasbit(msg, 1);
}
UPB_INLINE void envoy_config_route_v3_RateLimit_Action_MetaData_clear_metadata_key(const envoy_config_route_v3_RateLimit_Action_MetaData* msg) {
- *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const upb_Message*) = NULL;
+ *UPB_PTR_AT(msg, UPB_SIZE(20, 32), const upb_Message*) = NULL;
}
UPB_INLINE const struct envoy_type_metadata_v3_MetadataKey* envoy_config_route_v3_RateLimit_Action_MetaData_metadata_key(const envoy_config_route_v3_RateLimit_Action_MetaData* msg) {
- return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const struct envoy_type_metadata_v3_MetadataKey*);
+ return *UPB_PTR_AT(msg, UPB_SIZE(20, 32), const struct envoy_type_metadata_v3_MetadataKey*);
}
UPB_INLINE void envoy_config_route_v3_RateLimit_Action_MetaData_clear_default_value(const envoy_config_route_v3_RateLimit_Action_MetaData* msg) {
- *UPB_PTR_AT(msg, UPB_SIZE(20, 32), upb_StringView) = upb_StringView_FromDataAndSize(NULL, 0);
+ *UPB_PTR_AT(msg, UPB_SIZE(24, 40), upb_StringView) = upb_StringView_FromDataAndSize(NULL, 0);
}
UPB_INLINE upb_StringView envoy_config_route_v3_RateLimit_Action_MetaData_default_value(const envoy_config_route_v3_RateLimit_Action_MetaData* msg) {
- return *UPB_PTR_AT(msg, UPB_SIZE(20, 32), upb_StringView);
+ return *UPB_PTR_AT(msg, UPB_SIZE(24, 40), upb_StringView);
}
UPB_INLINE void envoy_config_route_v3_RateLimit_Action_MetaData_clear_source(const envoy_config_route_v3_RateLimit_Action_MetaData* msg) {
*UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = 0;
@@ -5960,13 +5960,19 @@ UPB_INLINE void envoy_config_route_v3_RateLimit_Action_MetaData_clear_source(con
UPB_INLINE int32_t envoy_config_route_v3_RateLimit_Action_MetaData_source(const envoy_config_route_v3_RateLimit_Action_MetaData* msg) {
return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t);
}
+UPB_INLINE void envoy_config_route_v3_RateLimit_Action_MetaData_clear_skip_if_absent(const envoy_config_route_v3_RateLimit_Action_MetaData* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = 0;
+}
+UPB_INLINE bool envoy_config_route_v3_RateLimit_Action_MetaData_skip_if_absent(const envoy_config_route_v3_RateLimit_Action_MetaData* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool);
+}
UPB_INLINE void envoy_config_route_v3_RateLimit_Action_MetaData_set_descriptor_key(envoy_config_route_v3_RateLimit_Action_MetaData *msg, upb_StringView value) {
- *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_StringView) = value;
+ *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_StringView) = value;
}
UPB_INLINE void envoy_config_route_v3_RateLimit_Action_MetaData_set_metadata_key(envoy_config_route_v3_RateLimit_Action_MetaData *msg, struct envoy_type_metadata_v3_MetadataKey* value) {
_upb_sethas(msg, 1);
- *UPB_PTR_AT(msg, UPB_SIZE(16, 24), struct envoy_type_metadata_v3_MetadataKey*) = value;
+ *UPB_PTR_AT(msg, UPB_SIZE(20, 32), struct envoy_type_metadata_v3_MetadataKey*) = value;
}
UPB_INLINE struct envoy_type_metadata_v3_MetadataKey* envoy_config_route_v3_RateLimit_Action_MetaData_mutable_metadata_key(envoy_config_route_v3_RateLimit_Action_MetaData* msg, upb_Arena* arena) {
struct envoy_type_metadata_v3_MetadataKey* sub = (struct envoy_type_metadata_v3_MetadataKey*)envoy_config_route_v3_RateLimit_Action_MetaData_metadata_key(msg);
@@ -5978,11 +5984,14 @@ UPB_INLINE struct envoy_type_metadata_v3_MetadataKey* envoy_config_route_v3_Rate
return sub;
}
UPB_INLINE void envoy_config_route_v3_RateLimit_Action_MetaData_set_default_value(envoy_config_route_v3_RateLimit_Action_MetaData *msg, upb_StringView value) {
- *UPB_PTR_AT(msg, UPB_SIZE(20, 32), upb_StringView) = value;
+ *UPB_PTR_AT(msg, UPB_SIZE(24, 40), upb_StringView) = value;
}
UPB_INLINE void envoy_config_route_v3_RateLimit_Action_MetaData_set_source(envoy_config_route_v3_RateLimit_Action_MetaData *msg, int32_t value) {
*UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
}
+UPB_INLINE void envoy_config_route_v3_RateLimit_Action_MetaData_set_skip_if_absent(envoy_config_route_v3_RateLimit_Action_MetaData *msg, bool value) {
+ *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value;
+}
/* envoy.config.route.v3.RateLimit.Action.QueryParameterValueMatch */
@@ -6648,6 +6657,12 @@ UPB_INLINE void envoy_config_route_v3_FilterConfig_clear_is_optional(const envoy
UPB_INLINE bool envoy_config_route_v3_FilterConfig_is_optional(const envoy_config_route_v3_FilterConfig* msg) {
return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
}
+UPB_INLINE void envoy_config_route_v3_FilterConfig_clear_disabled(const envoy_config_route_v3_FilterConfig* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = 0;
+}
+UPB_INLINE bool envoy_config_route_v3_FilterConfig_disabled(const envoy_config_route_v3_FilterConfig* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool);
+}
UPB_INLINE void envoy_config_route_v3_FilterConfig_set_config(envoy_config_route_v3_FilterConfig *msg, struct google_protobuf_Any* value) {
_upb_sethas(msg, 1);
@@ -6665,6 +6680,9 @@ UPB_INLINE struct google_protobuf_Any* envoy_config_route_v3_FilterConfig_mutabl
UPB_INLINE void envoy_config_route_v3_FilterConfig_set_is_optional(envoy_config_route_v3_FilterConfig *msg, bool value) {
*UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
}
+UPB_INLINE void envoy_config_route_v3_FilterConfig_set_disabled(envoy_config_route_v3_FilterConfig *msg, bool value) {
+ *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
+}
extern const upb_MiniTable_File envoy_config_route_v3_route_components_proto_upb_file_layout;
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/trace/v3/opentelemetry.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/trace/v3/opentelemetry.upb.c
index 874b1a5329..813e3dc16e 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/trace/v3/opentelemetry.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/config/trace/v3/opentelemetry.upb.c
@@ -11,7 +11,6 @@
#include "envoy/config/trace/v3/opentelemetry.upb.h"
#include "envoy/config/core/v3/grpc_service.upb.h"
#include "udpa/annotations/status.upb.h"
-#include "validate/validate.upb.h"
#include "upb/port_def.inc"
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c
index 8a27e0eb63..86f0f5870e 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c
@@ -33,7 +33,7 @@
#include "upb/port_def.inc"
-static const upb_MiniTable_Sub envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_submsgs[32] = {
+static const upb_MiniTable_Sub envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_submsgs[34] = {
{.submsg = &envoy_extensions_filters_network_http_connection_manager_v3_Rds_msginit},
{.submsg = &envoy_config_route_v3_RouteConfiguration_msginit},
{.submsg = &envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_msginit},
@@ -66,13 +66,15 @@ static const upb_MiniTable_Sub envoy_extensions_filters_network_http_connection_
{.submsg = &envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_ProxyStatusConfig_msginit},
{.submsg = &envoy_config_core_v3_TypedExtensionConfig_msginit},
{.submsg = &envoy_config_core_v3_TypedExtensionConfig_msginit},
+ {.submsg = &google_protobuf_BoolValue_msginit},
+ {.submsg = &google_protobuf_Duration_msginit},
};
-static const upb_MiniTable_Field envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager__fields[50] = {
+static const upb_MiniTable_Field envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager__fields[52] = {
{1, UPB_SIZE(4, 4), UPB_SIZE(0, 0), kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
{2, UPB_SIZE(52, 56), UPB_SIZE(0, 0), kUpb_NoSub, 9, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
- {3, UPB_SIZE(192, 336), UPB_SIZE(-25, -25), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
- {4, UPB_SIZE(192, 336), UPB_SIZE(-25, -25), 1, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+ {3, UPB_SIZE(200, 352), UPB_SIZE(-25, -25), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+ {4, UPB_SIZE(200, 352), UPB_SIZE(-25, -25), 1, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{5, UPB_SIZE(60, 72), UPB_SIZE(0, 0), 2, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{6, UPB_SIZE(64, 80), UPB_SIZE(1, 1), 3, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{7, UPB_SIZE(68, 88), UPB_SIZE(2, 2), 4, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
@@ -97,7 +99,7 @@ static const upb_MiniTable_Field envoy_extensions_filters_network_http_connectio
{28, UPB_SIZE(132, 216), UPB_SIZE(12, 12), 16, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{29, UPB_SIZE(136, 224), UPB_SIZE(13, 13), 17, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{30, UPB_SIZE(140, 232), UPB_SIZE(14, 14), 18, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
- {31, UPB_SIZE(192, 336), UPB_SIZE(-25, -25), 19, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+ {31, UPB_SIZE(200, 352), UPB_SIZE(-25, -25), 19, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{32, UPB_SIZE(28, 28), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
{33, UPB_SIZE(29, 29), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
{34, UPB_SIZE(32, 32), UPB_SIZE(0, 0), kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
@@ -108,7 +110,7 @@ static const upb_MiniTable_Field envoy_extensions_filters_network_http_connectio
{39, UPB_SIZE(37, 37), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
{40, UPB_SIZE(156, 264), UPB_SIZE(18, 18), 23, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{41, UPB_SIZE(160, 272), UPB_SIZE(19, 19), 24, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
- {42, UPB_SIZE(196, 344), UPB_SIZE(-41, -41), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+ {42, UPB_SIZE(204, 360), UPB_SIZE(-41, -41), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
{43, UPB_SIZE(164, 280), UPB_SIZE(20, 20), 25, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{44, UPB_SIZE(168, 288), UPB_SIZE(21, 21), 26, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{45, UPB_SIZE(44, 44), UPB_SIZE(0, 0), kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
@@ -119,12 +121,14 @@ static const upb_MiniTable_Field envoy_extensions_filters_network_http_connectio
{50, UPB_SIZE(184, 320), UPB_SIZE(24, 24), 30, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{51, UPB_SIZE(49, 49), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
{52, UPB_SIZE(188, 328), UPB_SIZE(0, 0), 31, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+ {53, UPB_SIZE(192, 336), UPB_SIZE(25, 25), 32, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+ {54, UPB_SIZE(196, 344), UPB_SIZE(26, 26), 33, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
};
const upb_MiniTable envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_msginit = {
&envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_submsgs[0],
&envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager__fields[0],
- UPB_SIZE(200, 352), 50, kUpb_ExtMode_NonExtendable, 10, 255, 0,
+ UPB_SIZE(208, 368), 52, kUpb_ExtMode_NonExtendable, 10, 255, 0,
};
static const upb_MiniTable_Sub envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_Tracing_submsgs[6] = {
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h
index 81c3f2774d..47a55ea9ae 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h
@@ -232,19 +232,19 @@ UPB_INLINE bool envoy_extensions_filters_network_http_connection_manager_v3_Http
return _upb_getoneofcase(msg, UPB_SIZE(24, 24)) == 3;
}
UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_clear_rds(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
- UPB_WRITE_ONEOF(msg, envoy_extensions_filters_network_http_connection_manager_v3_Rds*, UPB_SIZE(192, 336), 0, UPB_SIZE(24, 24), envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_specifier_NOT_SET);
+ UPB_WRITE_ONEOF(msg, envoy_extensions_filters_network_http_connection_manager_v3_Rds*, UPB_SIZE(200, 352), 0, UPB_SIZE(24, 24), envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_specifier_NOT_SET);
}
UPB_INLINE const envoy_extensions_filters_network_http_connection_manager_v3_Rds* envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_rds(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
- return UPB_READ_ONEOF(msg, const envoy_extensions_filters_network_http_connection_manager_v3_Rds*, UPB_SIZE(192, 336), UPB_SIZE(24, 24), 3, NULL);
+ return UPB_READ_ONEOF(msg, const envoy_extensions_filters_network_http_connection_manager_v3_Rds*, UPB_SIZE(200, 352), UPB_SIZE(24, 24), 3, NULL);
}
UPB_INLINE bool envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_route_config(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
return _upb_getoneofcase(msg, UPB_SIZE(24, 24)) == 4;
}
UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_clear_route_config(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
- UPB_WRITE_ONEOF(msg, struct envoy_config_route_v3_RouteConfiguration*, UPB_SIZE(192, 336), 0, UPB_SIZE(24, 24), envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_specifier_NOT_SET);
+ UPB_WRITE_ONEOF(msg, struct envoy_config_route_v3_RouteConfiguration*, UPB_SIZE(200, 352), 0, UPB_SIZE(24, 24), envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_specifier_NOT_SET);
}
UPB_INLINE const struct envoy_config_route_v3_RouteConfiguration* envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_config(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
- return UPB_READ_ONEOF(msg, const struct envoy_config_route_v3_RouteConfiguration*, UPB_SIZE(192, 336), UPB_SIZE(24, 24), 4, NULL);
+ return UPB_READ_ONEOF(msg, const struct envoy_config_route_v3_RouteConfiguration*, UPB_SIZE(200, 352), UPB_SIZE(24, 24), 4, NULL);
}
UPB_INLINE bool envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_http_filters(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
return _upb_has_submsg_nohasbit(msg, UPB_SIZE(60, 72));
@@ -445,10 +445,10 @@ UPB_INLINE bool envoy_extensions_filters_network_http_connection_manager_v3_Http
return _upb_getoneofcase(msg, UPB_SIZE(24, 24)) == 31;
}
UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_clear_scoped_routes(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
- UPB_WRITE_ONEOF(msg, envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes*, UPB_SIZE(192, 336), 0, UPB_SIZE(24, 24), envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_specifier_NOT_SET);
+ UPB_WRITE_ONEOF(msg, envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes*, UPB_SIZE(200, 352), 0, UPB_SIZE(24, 24), envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_specifier_NOT_SET);
}
UPB_INLINE const envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes* envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_scoped_routes(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
- return UPB_READ_ONEOF(msg, const envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes*, UPB_SIZE(192, 336), UPB_SIZE(24, 24), 31, NULL);
+ return UPB_READ_ONEOF(msg, const envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes*, UPB_SIZE(200, 352), UPB_SIZE(24, 24), 31, NULL);
}
UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_clear_preserve_external_request_id(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
*UPB_PTR_AT(msg, UPB_SIZE(28, 28), bool) = 0;
@@ -529,10 +529,10 @@ UPB_INLINE bool envoy_extensions_filters_network_http_connection_manager_v3_Http
return _upb_getoneofcase(msg, UPB_SIZE(40, 40)) == 42;
}
UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_clear_strip_any_host_port(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
- UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(196, 344), 0, UPB_SIZE(40, 40), envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_strip_port_mode_NOT_SET);
+ UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(204, 360), 0, UPB_SIZE(40, 40), envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_strip_port_mode_NOT_SET);
}
UPB_INLINE bool envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_strip_any_host_port(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
- return UPB_READ_ONEOF(msg, bool, UPB_SIZE(196, 344), UPB_SIZE(40, 40), 42, false);
+ return UPB_READ_ONEOF(msg, bool, UPB_SIZE(204, 360), UPB_SIZE(40, 40), 42, false);
}
UPB_INLINE bool envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_path_normalization_options(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
return _upb_hasbit(msg, 20);
@@ -615,6 +615,24 @@ UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_Http
UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* const* envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_early_header_mutation_extensions(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg, size_t* len) {
return (const struct envoy_config_core_v3_TypedExtensionConfig* const*)_upb_array_accessor(msg, UPB_SIZE(188, 328), len);
}
+UPB_INLINE bool envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_add_proxy_protocol_connection_state(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
+ return _upb_hasbit(msg, 25);
+}
+UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_clear_add_proxy_protocol_connection_state(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(192, 336), const upb_Message*) = NULL;
+}
+UPB_INLINE const struct google_protobuf_BoolValue* envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_add_proxy_protocol_connection_state(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(192, 336), const struct google_protobuf_BoolValue*);
+}
+UPB_INLINE bool envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_access_log_flush_interval(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
+ return _upb_hasbit(msg, 26);
+}
+UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_clear_access_log_flush_interval(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(196, 344), const upb_Message*) = NULL;
+}
+UPB_INLINE const struct google_protobuf_Duration* envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_access_log_flush_interval(const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(196, 344), const struct google_protobuf_Duration*);
+}
UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_set_codec_type(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager *msg, int32_t value) {
*UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
@@ -623,7 +641,7 @@ UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_Http
*UPB_PTR_AT(msg, UPB_SIZE(52, 56), upb_StringView) = value;
}
UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_set_rds(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager *msg, envoy_extensions_filters_network_http_connection_manager_v3_Rds* value) {
- UPB_WRITE_ONEOF(msg, envoy_extensions_filters_network_http_connection_manager_v3_Rds*, UPB_SIZE(192, 336), value, UPB_SIZE(24, 24), 3);
+ UPB_WRITE_ONEOF(msg, envoy_extensions_filters_network_http_connection_manager_v3_Rds*, UPB_SIZE(200, 352), value, UPB_SIZE(24, 24), 3);
}
UPB_INLINE struct envoy_extensions_filters_network_http_connection_manager_v3_Rds* envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_mutable_rds(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg, upb_Arena* arena) {
struct envoy_extensions_filters_network_http_connection_manager_v3_Rds* sub = (struct envoy_extensions_filters_network_http_connection_manager_v3_Rds*)envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_rds(msg);
@@ -635,7 +653,7 @@ UPB_INLINE struct envoy_extensions_filters_network_http_connection_manager_v3_Rd
return sub;
}
UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_set_route_config(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager *msg, struct envoy_config_route_v3_RouteConfiguration* value) {
- UPB_WRITE_ONEOF(msg, struct envoy_config_route_v3_RouteConfiguration*, UPB_SIZE(192, 336), value, UPB_SIZE(24, 24), 4);
+ UPB_WRITE_ONEOF(msg, struct envoy_config_route_v3_RouteConfiguration*, UPB_SIZE(200, 352), value, UPB_SIZE(24, 24), 4);
}
UPB_INLINE struct envoy_config_route_v3_RouteConfiguration* envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_mutable_route_config(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg, upb_Arena* arena) {
struct envoy_config_route_v3_RouteConfiguration* sub = (struct envoy_config_route_v3_RouteConfiguration*)envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_config(msg);
@@ -886,7 +904,7 @@ UPB_INLINE struct google_protobuf_BoolValue* envoy_extensions_filters_network_ht
return sub;
}
UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_set_scoped_routes(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager *msg, envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes* value) {
- UPB_WRITE_ONEOF(msg, envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes*, UPB_SIZE(192, 336), value, UPB_SIZE(24, 24), 31);
+ UPB_WRITE_ONEOF(msg, envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes*, UPB_SIZE(200, 352), value, UPB_SIZE(24, 24), 31);
}
UPB_INLINE struct envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes* envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_mutable_scoped_routes(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg, upb_Arena* arena) {
struct envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes* sub = (struct envoy_extensions_filters_network_http_connection_manager_v3_ScopedRoutes*)envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_scoped_routes(msg);
@@ -978,7 +996,7 @@ UPB_INLINE struct google_protobuf_Duration* envoy_extensions_filters_network_htt
return sub;
}
UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_set_strip_any_host_port(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager *msg, bool value) {
- UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(196, 344), value, UPB_SIZE(40, 40), 42);
+ UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(204, 360), value, UPB_SIZE(40, 40), 42);
}
UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_set_path_normalization_options(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager *msg, envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_PathNormalizationOptions* value) {
_upb_sethas(msg, 20);
@@ -1078,6 +1096,32 @@ UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_extensions_fi
if (!ok) return NULL;
return sub;
}
+UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_set_add_proxy_protocol_connection_state(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager *msg, struct google_protobuf_BoolValue* value) {
+ _upb_sethas(msg, 25);
+ *UPB_PTR_AT(msg, UPB_SIZE(192, 336), struct google_protobuf_BoolValue*) = value;
+}
+UPB_INLINE struct google_protobuf_BoolValue* envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_mutable_add_proxy_protocol_connection_state(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg, upb_Arena* arena) {
+ struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_add_proxy_protocol_connection_state(msg);
+ if (sub == NULL) {
+ sub = (struct google_protobuf_BoolValue*)_upb_Message_New(&google_protobuf_BoolValue_msginit, arena);
+ if (!sub) return NULL;
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_set_add_proxy_protocol_connection_state(msg, sub);
+ }
+ return sub;
+}
+UPB_INLINE void envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_set_access_log_flush_interval(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager *msg, struct google_protobuf_Duration* value) {
+ _upb_sethas(msg, 26);
+ *UPB_PTR_AT(msg, UPB_SIZE(196, 344), struct google_protobuf_Duration*) = value;
+}
+UPB_INLINE struct google_protobuf_Duration* envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_mutable_access_log_flush_interval(envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* msg, upb_Arena* arena) {
+ struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_access_log_flush_interval(msg);
+ if (sub == NULL) {
+ sub = (struct google_protobuf_Duration*)_upb_Message_New(&google_protobuf_Duration_msginit, arena);
+ if (!sub) return NULL;
+ envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_set_access_log_flush_interval(msg, sub);
+ }
+ return sub;
+}
/* envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.Tracing */
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c
index ceb88b26e0..e53fccd4e5 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.c
@@ -15,26 +15,28 @@
#include "upb/port_def.inc"
-static const upb_MiniTable_Sub envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_submsgs[5] = {
+static const upb_MiniTable_Sub envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_submsgs[6] = {
{.submsg = &google_protobuf_BoolValue_msginit},
{.submsg = &google_protobuf_Duration_msginit},
{.submsg = &google_protobuf_Duration_msginit},
{.submsg = &google_protobuf_Duration_msginit},
{.submsg = &google_protobuf_Duration_msginit},
+ {.submsg = &google_protobuf_FloatValue_msginit},
};
-static const upb_MiniTable_Field envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin__fields[5] = {
+static const upb_MiniTable_Field envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin__fields[6] = {
{1, UPB_SIZE(4, 8), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{2, UPB_SIZE(8, 16), UPB_SIZE(2, 2), 1, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{3, UPB_SIZE(12, 24), UPB_SIZE(3, 3), 2, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{4, UPB_SIZE(16, 32), UPB_SIZE(4, 4), 3, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{5, UPB_SIZE(20, 40), UPB_SIZE(5, 5), 4, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+ {6, UPB_SIZE(24, 48), UPB_SIZE(6, 6), 5, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
};
const upb_MiniTable envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_msginit = {
&envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_submsgs[0],
&envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin__fields[0],
- UPB_SIZE(24, 48), 5, kUpb_ExtMode_NonExtendable, 5, 255, 0,
+ UPB_SIZE(32, 56), 6, kUpb_ExtMode_NonExtendable, 6, 255, 0,
};
static const upb_MiniTable *messages_layout[1] = {
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h
index 03f8a56db7..506bd29c5a 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.upb.h
@@ -25,8 +25,10 @@ typedef struct envoy_extensions_load_balancing_policies_client_side_weighted_rou
extern const upb_MiniTable envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_msginit;
struct google_protobuf_BoolValue;
struct google_protobuf_Duration;
+struct google_protobuf_FloatValue;
extern const upb_MiniTable google_protobuf_BoolValue_msginit;
extern const upb_MiniTable google_protobuf_Duration_msginit;
+extern const upb_MiniTable google_protobuf_FloatValue_msginit;
@@ -110,6 +112,15 @@ UPB_INLINE void envoy_extensions_load_balancing_policies_client_side_weighted_ro
UPB_INLINE const struct google_protobuf_Duration* envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_weight_update_period(const envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin* msg) {
return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), const struct google_protobuf_Duration*);
}
+UPB_INLINE bool envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_has_error_utilization_penalty(const envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin* msg) {
+ return _upb_hasbit(msg, 6);
+}
+UPB_INLINE void envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_clear_error_utilization_penalty(const envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(24, 48), const upb_Message*) = NULL;
+}
+UPB_INLINE const struct google_protobuf_FloatValue* envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_error_utilization_penalty(const envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(24, 48), const struct google_protobuf_FloatValue*);
+}
UPB_INLINE void envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_set_enable_oob_load_report(envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin *msg, struct google_protobuf_BoolValue* value) {
_upb_sethas(msg, 1);
@@ -176,6 +187,19 @@ UPB_INLINE struct google_protobuf_Duration* envoy_extensions_load_balancing_poli
}
return sub;
}
+UPB_INLINE void envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_set_error_utilization_penalty(envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin *msg, struct google_protobuf_FloatValue* value) {
+ _upb_sethas(msg, 6);
+ *UPB_PTR_AT(msg, UPB_SIZE(24, 48), struct google_protobuf_FloatValue*) = value;
+}
+UPB_INLINE struct google_protobuf_FloatValue* envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_mutable_error_utilization_penalty(envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin* msg, upb_Arena* arena) {
+ struct google_protobuf_FloatValue* sub = (struct google_protobuf_FloatValue*)envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_error_utilization_penalty(msg);
+ if (sub == NULL) {
+ sub = (struct google_protobuf_FloatValue*)_upb_Message_New(&google_protobuf_FloatValue_msginit, arena);
+ if (!sub) return NULL;
+ envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_set_error_utilization_penalty(msg, sub);
+ }
+ return sub;
+}
extern const upb_MiniTable_File envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_client_side_weighted_round_robin_proto_upb_file_layout;
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c
index b90f22d53f..44e93fcb22 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.c
@@ -17,26 +17,28 @@
#include "upb/port_def.inc"
-static const upb_MiniTable_Sub envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_submsgs[4] = {
+static const upb_MiniTable_Sub envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_submsgs[5] = {
{.submsg = &google_protobuf_UInt64Value_msginit},
{.submsg = &google_protobuf_UInt64Value_msginit},
{.submsg = &google_protobuf_UInt32Value_msginit},
{.submsg = &envoy_extensions_load_balancing_policies_common_v3_ConsistentHashingLbConfig_msginit},
+ {.submsg = &envoy_extensions_load_balancing_policies_common_v3_LocalityLbConfig_LocalityWeightedLbConfig_msginit},
};
-static const upb_MiniTable_Field envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash__fields[6] = {
+static const upb_MiniTable_Field envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash__fields[7] = {
{1, UPB_SIZE(4, 4), UPB_SIZE(0, 0), kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
{2, UPB_SIZE(12, 16), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{3, UPB_SIZE(16, 24), UPB_SIZE(2, 2), 1, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{4, UPB_SIZE(8, 8), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
{5, UPB_SIZE(20, 32), UPB_SIZE(3, 3), 2, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{6, UPB_SIZE(24, 40), UPB_SIZE(4, 4), 3, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
+ {7, UPB_SIZE(28, 48), UPB_SIZE(5, 5), 4, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
};
const upb_MiniTable envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit = {
&envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_submsgs[0],
&envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash__fields[0],
- UPB_SIZE(32, 48), 6, kUpb_ExtMode_NonExtendable, 6, 255, 0,
+ UPB_SIZE(32, 56), 7, kUpb_ExtMode_NonExtendable, 7, 255, 0,
};
static const upb_MiniTable *messages_layout[1] = {
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h
index 6488a809ff..a84e5d00da 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h
@@ -24,9 +24,11 @@ struct envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash;
typedef struct envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash;
extern const upb_MiniTable envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit;
struct envoy_extensions_load_balancing_policies_common_v3_ConsistentHashingLbConfig;
+struct envoy_extensions_load_balancing_policies_common_v3_LocalityLbConfig_LocalityWeightedLbConfig;
struct google_protobuf_UInt32Value;
struct google_protobuf_UInt64Value;
extern const upb_MiniTable envoy_extensions_load_balancing_policies_common_v3_ConsistentHashingLbConfig_msginit;
+extern const upb_MiniTable envoy_extensions_load_balancing_policies_common_v3_LocalityLbConfig_LocalityWeightedLbConfig_msginit;
extern const upb_MiniTable google_protobuf_UInt32Value_msginit;
extern const upb_MiniTable google_protobuf_UInt64Value_msginit;
@@ -121,6 +123,15 @@ UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_c
UPB_INLINE const struct envoy_extensions_load_balancing_policies_common_v3_ConsistentHashingLbConfig* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_consistent_hashing_lb_config(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) {
return *UPB_PTR_AT(msg, UPB_SIZE(24, 40), const struct envoy_extensions_load_balancing_policies_common_v3_ConsistentHashingLbConfig*);
}
+UPB_INLINE bool envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_has_locality_weighted_lb_config(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) {
+ return _upb_hasbit(msg, 5);
+}
+UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_clear_locality_weighted_lb_config(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(28, 48), const upb_Message*) = NULL;
+}
+UPB_INLINE const struct envoy_extensions_load_balancing_policies_common_v3_LocalityLbConfig_LocalityWeightedLbConfig* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_locality_weighted_lb_config(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(28, 48), const struct envoy_extensions_load_balancing_policies_common_v3_LocalityLbConfig_LocalityWeightedLbConfig*);
+}
UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_hash_function(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg, int32_t value) {
*UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
@@ -180,6 +191,19 @@ UPB_INLINE struct envoy_extensions_load_balancing_policies_common_v3_ConsistentH
}
return sub;
}
+UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_locality_weighted_lb_config(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg, struct envoy_extensions_load_balancing_policies_common_v3_LocalityLbConfig_LocalityWeightedLbConfig* value) {
+ _upb_sethas(msg, 5);
+ *UPB_PTR_AT(msg, UPB_SIZE(28, 48), struct envoy_extensions_load_balancing_policies_common_v3_LocalityLbConfig_LocalityWeightedLbConfig*) = value;
+}
+UPB_INLINE struct envoy_extensions_load_balancing_policies_common_v3_LocalityLbConfig_LocalityWeightedLbConfig* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_mutable_locality_weighted_lb_config(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg, upb_Arena* arena) {
+ struct envoy_extensions_load_balancing_policies_common_v3_LocalityLbConfig_LocalityWeightedLbConfig* sub = (struct envoy_extensions_load_balancing_policies_common_v3_LocalityLbConfig_LocalityWeightedLbConfig*)envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_locality_weighted_lb_config(msg);
+ if (sub == NULL) {
+ sub = (struct envoy_extensions_load_balancing_policies_common_v3_LocalityLbConfig_LocalityWeightedLbConfig*)_upb_Message_New(&envoy_extensions_load_balancing_policies_common_v3_LocalityLbConfig_LocalityWeightedLbConfig_msginit, arena);
+ if (!sub) return NULL;
+ envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_locality_weighted_lb_config(msg, sub);
+ }
+ return sub;
+}
extern const upb_MiniTable_File envoy_extensions_load_balancing_policies_ring_hash_v3_ring_hash_proto_upb_file_layout;
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/type/matcher/v3/http_inputs.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/type/matcher/v3/http_inputs.upb.c
index 271aa37f73..29a3a16fd2 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/type/matcher/v3/http_inputs.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/type/matcher/v3/http_inputs.upb.c
@@ -54,18 +54,29 @@ const upb_MiniTable envoy_type_matcher_v3_HttpResponseTrailerMatchInput_msginit
UPB_SIZE(8, 16), 1, kUpb_ExtMode_NonExtendable, 1, 255, 0,
};
-static const upb_MiniTable *messages_layout[4] = {
+static const upb_MiniTable_Field envoy_type_matcher_v3_HttpRequestQueryParamMatchInput__fields[1] = {
+ {1, UPB_SIZE(0, 0), UPB_SIZE(0, 0), kUpb_NoSub, 9, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_msginit = {
+ NULL,
+ &envoy_type_matcher_v3_HttpRequestQueryParamMatchInput__fields[0],
+ UPB_SIZE(8, 16), 1, kUpb_ExtMode_NonExtendable, 1, 255, 0,
+};
+
+static const upb_MiniTable *messages_layout[5] = {
&envoy_type_matcher_v3_HttpRequestHeaderMatchInput_msginit,
&envoy_type_matcher_v3_HttpRequestTrailerMatchInput_msginit,
&envoy_type_matcher_v3_HttpResponseHeaderMatchInput_msginit,
&envoy_type_matcher_v3_HttpResponseTrailerMatchInput_msginit,
+ &envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_msginit,
};
const upb_MiniTable_File envoy_type_matcher_v3_http_inputs_proto_upb_file_layout = {
messages_layout,
NULL,
NULL,
- 4,
+ 5,
0,
0,
};
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/type/matcher/v3/http_inputs.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/type/matcher/v3/http_inputs.upb.h
index 7cde108420..1e23a824d3 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/type/matcher/v3/http_inputs.upb.h
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/type/matcher/v3/http_inputs.upb.h
@@ -24,14 +24,17 @@ struct envoy_type_matcher_v3_HttpRequestHeaderMatchInput;
struct envoy_type_matcher_v3_HttpRequestTrailerMatchInput;
struct envoy_type_matcher_v3_HttpResponseHeaderMatchInput;
struct envoy_type_matcher_v3_HttpResponseTrailerMatchInput;
+struct envoy_type_matcher_v3_HttpRequestQueryParamMatchInput;
typedef struct envoy_type_matcher_v3_HttpRequestHeaderMatchInput envoy_type_matcher_v3_HttpRequestHeaderMatchInput;
typedef struct envoy_type_matcher_v3_HttpRequestTrailerMatchInput envoy_type_matcher_v3_HttpRequestTrailerMatchInput;
typedef struct envoy_type_matcher_v3_HttpResponseHeaderMatchInput envoy_type_matcher_v3_HttpResponseHeaderMatchInput;
typedef struct envoy_type_matcher_v3_HttpResponseTrailerMatchInput envoy_type_matcher_v3_HttpResponseTrailerMatchInput;
+typedef struct envoy_type_matcher_v3_HttpRequestQueryParamMatchInput envoy_type_matcher_v3_HttpRequestQueryParamMatchInput;
extern const upb_MiniTable envoy_type_matcher_v3_HttpRequestHeaderMatchInput_msginit;
extern const upb_MiniTable envoy_type_matcher_v3_HttpRequestTrailerMatchInput_msginit;
extern const upb_MiniTable envoy_type_matcher_v3_HttpResponseHeaderMatchInput_msginit;
extern const upb_MiniTable envoy_type_matcher_v3_HttpResponseTrailerMatchInput_msginit;
+extern const upb_MiniTable envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_msginit;
@@ -219,6 +222,52 @@ UPB_INLINE void envoy_type_matcher_v3_HttpResponseTrailerMatchInput_set_header_n
*UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_StringView) = value;
}
+/* envoy.type.matcher.v3.HttpRequestQueryParamMatchInput */
+
+UPB_INLINE envoy_type_matcher_v3_HttpRequestQueryParamMatchInput* envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_new(upb_Arena* arena) {
+ return (envoy_type_matcher_v3_HttpRequestQueryParamMatchInput*)_upb_Message_New(&envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_msginit, arena);
+}
+UPB_INLINE envoy_type_matcher_v3_HttpRequestQueryParamMatchInput* envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_parse(const char* buf, size_t size, upb_Arena* arena) {
+ envoy_type_matcher_v3_HttpRequestQueryParamMatchInput* ret = envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE envoy_type_matcher_v3_HttpRequestQueryParamMatchInput* envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_parse_ex(const char* buf, size_t size,
+ const upb_ExtensionRegistry* extreg,
+ int options, upb_Arena* arena) {
+ envoy_type_matcher_v3_HttpRequestQueryParamMatchInput* ret = envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_new(arena);
+ if (!ret) return NULL;
+ if (upb_Decode(buf, size, ret, &envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_msginit, extreg, options, arena) !=
+ kUpb_DecodeStatus_Ok) {
+ return NULL;
+ }
+ return ret;
+}
+UPB_INLINE char* envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_serialize(const envoy_type_matcher_v3_HttpRequestQueryParamMatchInput* msg, upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_msginit, 0, arena, &ptr, len);
+ return ptr;
+}
+UPB_INLINE char* envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_serialize_ex(const envoy_type_matcher_v3_HttpRequestQueryParamMatchInput* msg, int options,
+ upb_Arena* arena, size_t* len) {
+ char* ptr;
+ (void)upb_Encode(msg, &envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_msginit, options, arena, &ptr, len);
+ return ptr;
+}
+UPB_INLINE void envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_clear_query_param(const envoy_type_matcher_v3_HttpRequestQueryParamMatchInput* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_StringView) = upb_StringView_FromDataAndSize(NULL, 0);
+}
+UPB_INLINE upb_StringView envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_query_param(const envoy_type_matcher_v3_HttpRequestQueryParamMatchInput* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_StringView);
+}
+
+UPB_INLINE void envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_set_query_param(envoy_type_matcher_v3_HttpRequestQueryParamMatchInput *msg, upb_StringView value) {
+ *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_StringView) = value;
+}
+
extern const upb_MiniTable_File envoy_type_matcher_v3_http_inputs_proto_upb_file_layout;
#ifdef __cplusplus
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c
index dc15579d2e..3c77cc75ca 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.c
@@ -13,24 +13,27 @@
#include "upb/port_def.inc"
-static const upb_MiniTable_Sub xds_data_orca_v3_OrcaLoadReport_submsgs[2] = {
+static const upb_MiniTable_Sub xds_data_orca_v3_OrcaLoadReport_submsgs[3] = {
{.submsg = &xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_msginit},
{.submsg = &xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_msginit},
+ {.submsg = &xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry_msginit},
};
-static const upb_MiniTable_Field xds_data_orca_v3_OrcaLoadReport__fields[6] = {
- {1, UPB_SIZE(8, 16), UPB_SIZE(0, 0), kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
- {2, UPB_SIZE(16, 24), UPB_SIZE(0, 0), kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
- {3, UPB_SIZE(24, 32), UPB_SIZE(0, 0), kUpb_NoSub, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
+static const upb_MiniTable_Field xds_data_orca_v3_OrcaLoadReport__fields[8] = {
+ {1, UPB_SIZE(16, 24), UPB_SIZE(0, 0), kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
+ {2, UPB_SIZE(24, 32), UPB_SIZE(0, 0), kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
+ {3, UPB_SIZE(32, 40), UPB_SIZE(0, 0), kUpb_NoSub, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
{4, UPB_SIZE(0, 0), UPB_SIZE(0, 0), 0, 11, kUpb_FieldMode_Map | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
{5, UPB_SIZE(4, 8), UPB_SIZE(0, 0), 1, 11, kUpb_FieldMode_Map | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
- {6, UPB_SIZE(32, 40), UPB_SIZE(0, 0), kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
+ {6, UPB_SIZE(40, 48), UPB_SIZE(0, 0), kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
+ {7, UPB_SIZE(48, 56), UPB_SIZE(0, 0), kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
+ {8, UPB_SIZE(8, 16), UPB_SIZE(0, 0), 2, 11, kUpb_FieldMode_Map | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
};
const upb_MiniTable xds_data_orca_v3_OrcaLoadReport_msginit = {
&xds_data_orca_v3_OrcaLoadReport_submsgs[0],
&xds_data_orca_v3_OrcaLoadReport__fields[0],
- UPB_SIZE(40, 48), 6, kUpb_ExtMode_NonExtendable, 6, 255, 0,
+ UPB_SIZE(56, 64), 8, kUpb_ExtMode_NonExtendable, 8, 255, 0,
};
static const upb_MiniTable_Field xds_data_orca_v3_OrcaLoadReport_RequestCostEntry__fields[2] = {
@@ -55,17 +58,29 @@ const upb_MiniTable xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_msginit = {
UPB_SIZE(16, 32), 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
};
-static const upb_MiniTable *messages_layout[3] = {
+static const upb_MiniTable_Field xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry__fields[2] = {
+ {1, UPB_SIZE(0, 0), UPB_SIZE(0, 0), kUpb_NoSub, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+ {2, UPB_SIZE(8, 16), UPB_SIZE(0, 0), kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry_msginit = {
+ NULL,
+ &xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry__fields[0],
+ UPB_SIZE(16, 32), 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
+};
+
+static const upb_MiniTable *messages_layout[4] = {
&xds_data_orca_v3_OrcaLoadReport_msginit,
&xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_msginit,
&xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_msginit,
+ &xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry_msginit,
};
const upb_MiniTable_File xds_data_orca_v3_orca_load_report_proto_upb_file_layout = {
messages_layout,
NULL,
NULL,
- 3,
+ 4,
0,
0,
};
diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h
index cdc36be307..fcca0b4871 100644
--- a/contrib/libs/grpc/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h
+++ b/contrib/libs/grpc/src/core/ext/upb-generated/xds/data/orca/v3/orca_load_report.upb.h
@@ -23,12 +23,15 @@ extern "C" {
struct xds_data_orca_v3_OrcaLoadReport;
struct xds_data_orca_v3_OrcaLoadReport_RequestCostEntry;
struct xds_data_orca_v3_OrcaLoadReport_UtilizationEntry;
+struct xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry;
typedef struct xds_data_orca_v3_OrcaLoadReport xds_data_orca_v3_OrcaLoadReport;
typedef struct xds_data_orca_v3_OrcaLoadReport_RequestCostEntry xds_data_orca_v3_OrcaLoadReport_RequestCostEntry;
typedef struct xds_data_orca_v3_OrcaLoadReport_UtilizationEntry xds_data_orca_v3_OrcaLoadReport_UtilizationEntry;
+typedef struct xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry;
extern const upb_MiniTable xds_data_orca_v3_OrcaLoadReport_msginit;
extern const upb_MiniTable xds_data_orca_v3_OrcaLoadReport_RequestCostEntry_msginit;
extern const upb_MiniTable xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_msginit;
+extern const upb_MiniTable xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry_msginit;
@@ -68,22 +71,22 @@ UPB_INLINE char* xds_data_orca_v3_OrcaLoadReport_serialize_ex(const xds_data_orc
return ptr;
}
UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_clear_cpu_utilization(const xds_data_orca_v3_OrcaLoadReport* msg) {
- *UPB_PTR_AT(msg, UPB_SIZE(8, 16), double) = 0;
+ *UPB_PTR_AT(msg, UPB_SIZE(16, 24), double) = 0;
}
UPB_INLINE double xds_data_orca_v3_OrcaLoadReport_cpu_utilization(const xds_data_orca_v3_OrcaLoadReport* msg) {
- return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), double);
+ return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), double);
}
UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_clear_mem_utilization(const xds_data_orca_v3_OrcaLoadReport* msg) {
- *UPB_PTR_AT(msg, UPB_SIZE(16, 24), double) = 0;
+ *UPB_PTR_AT(msg, UPB_SIZE(24, 32), double) = 0;
}
UPB_INLINE double xds_data_orca_v3_OrcaLoadReport_mem_utilization(const xds_data_orca_v3_OrcaLoadReport* msg) {
- return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), double);
+ return *UPB_PTR_AT(msg, UPB_SIZE(24, 32), double);
}
UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_clear_rps(const xds_data_orca_v3_OrcaLoadReport* msg) {
- *UPB_PTR_AT(msg, UPB_SIZE(24, 32), uint64_t) = 0;
+ *UPB_PTR_AT(msg, UPB_SIZE(32, 40), uint64_t) = 0;
}
UPB_INLINE uint64_t xds_data_orca_v3_OrcaLoadReport_rps(const xds_data_orca_v3_OrcaLoadReport* msg) {
- return *UPB_PTR_AT(msg, UPB_SIZE(24, 32), uint64_t);
+ return *UPB_PTR_AT(msg, UPB_SIZE(32, 40), uint64_t);
}
UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_has_request_cost(const xds_data_orca_v3_OrcaLoadReport* msg) {
return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0));
@@ -116,20 +119,41 @@ UPB_INLINE const xds_data_orca_v3_OrcaLoadReport_UtilizationEntry* xds_data_orca
return (const xds_data_orca_v3_OrcaLoadReport_UtilizationEntry*)_upb_msg_map_next(msg, UPB_SIZE(4, 8), iter);
}
UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_clear_rps_fractional(const xds_data_orca_v3_OrcaLoadReport* msg) {
- *UPB_PTR_AT(msg, UPB_SIZE(32, 40), double) = 0;
+ *UPB_PTR_AT(msg, UPB_SIZE(40, 48), double) = 0;
}
UPB_INLINE double xds_data_orca_v3_OrcaLoadReport_rps_fractional(const xds_data_orca_v3_OrcaLoadReport* msg) {
- return *UPB_PTR_AT(msg, UPB_SIZE(32, 40), double);
+ return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), double);
+}
+UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_clear_eps(const xds_data_orca_v3_OrcaLoadReport* msg) {
+ *UPB_PTR_AT(msg, UPB_SIZE(48, 56), double) = 0;
+}
+UPB_INLINE double xds_data_orca_v3_OrcaLoadReport_eps(const xds_data_orca_v3_OrcaLoadReport* msg) {
+ return *UPB_PTR_AT(msg, UPB_SIZE(48, 56), double);
+}
+UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_has_named_metrics(const xds_data_orca_v3_OrcaLoadReport* msg) {
+ return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16));
+}
+UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_clear_named_metrics(const xds_data_orca_v3_OrcaLoadReport* msg) {
+ _upb_array_detach(msg, UPB_SIZE(8, 16));
+}
+UPB_INLINE size_t xds_data_orca_v3_OrcaLoadReport_named_metrics_size(const xds_data_orca_v3_OrcaLoadReport* msg) {
+ return _upb_msg_map_size(msg, UPB_SIZE(8, 16));
+}
+UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_named_metrics_get(const xds_data_orca_v3_OrcaLoadReport* msg, upb_StringView key, double* val) {
+ return _upb_msg_map_get(msg, UPB_SIZE(8, 16), &key, 0, val, sizeof(*val));
+}
+UPB_INLINE const xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry* xds_data_orca_v3_OrcaLoadReport_named_metrics_next(const xds_data_orca_v3_OrcaLoadReport* msg, size_t* iter) {
+ return (const xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry*)_upb_msg_map_next(msg, UPB_SIZE(8, 16), iter);
}
UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_set_cpu_utilization(xds_data_orca_v3_OrcaLoadReport *msg, double value) {
- *UPB_PTR_AT(msg, UPB_SIZE(8, 16), double) = value;
+ *UPB_PTR_AT(msg, UPB_SIZE(16, 24), double) = value;
}
UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_set_mem_utilization(xds_data_orca_v3_OrcaLoadReport *msg, double value) {
- *UPB_PTR_AT(msg, UPB_SIZE(16, 24), double) = value;
+ *UPB_PTR_AT(msg, UPB_SIZE(24, 32), double) = value;
}
UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_set_rps(xds_data_orca_v3_OrcaLoadReport *msg, uint64_t value) {
- *UPB_PTR_AT(msg, UPB_SIZE(24, 32), uint64_t) = value;
+ *UPB_PTR_AT(msg, UPB_SIZE(32, 40), uint64_t) = value;
}
UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_request_cost_clear(xds_data_orca_v3_OrcaLoadReport* msg) { _upb_msg_map_clear(msg, UPB_SIZE(0, 0)); }
UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_request_cost_set(xds_data_orca_v3_OrcaLoadReport* msg, upb_StringView key, double val, upb_Arena* a) {
@@ -152,7 +176,20 @@ UPB_INLINE xds_data_orca_v3_OrcaLoadReport_UtilizationEntry* xds_data_orca_v3_Or
return (xds_data_orca_v3_OrcaLoadReport_UtilizationEntry*)_upb_msg_map_next(msg, UPB_SIZE(4, 8), iter);
}
UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_set_rps_fractional(xds_data_orca_v3_OrcaLoadReport *msg, double value) {
- *UPB_PTR_AT(msg, UPB_SIZE(32, 40), double) = value;
+ *UPB_PTR_AT(msg, UPB_SIZE(40, 48), double) = value;
+}
+UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_set_eps(xds_data_orca_v3_OrcaLoadReport *msg, double value) {
+ *UPB_PTR_AT(msg, UPB_SIZE(48, 56), double) = value;
+}
+UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_named_metrics_clear(xds_data_orca_v3_OrcaLoadReport* msg) { _upb_msg_map_clear(msg, UPB_SIZE(8, 16)); }
+UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_named_metrics_set(xds_data_orca_v3_OrcaLoadReport* msg, upb_StringView key, double val, upb_Arena* a) {
+ return _upb_msg_map_set(msg, UPB_SIZE(8, 16), &key, 0, &val, sizeof(val), a);
+}
+UPB_INLINE bool xds_data_orca_v3_OrcaLoadReport_named_metrics_delete(xds_data_orca_v3_OrcaLoadReport* msg, upb_StringView key) {
+ return _upb_msg_map_delete(msg, UPB_SIZE(8, 16), &key, 0);
+}
+UPB_INLINE xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry* xds_data_orca_v3_OrcaLoadReport_named_metrics_nextmutable(xds_data_orca_v3_OrcaLoadReport* msg, size_t* iter) {
+ return (xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry*)_upb_msg_map_next(msg, UPB_SIZE(8, 16), iter);
}
/* xds.data.orca.v3.OrcaLoadReport.RequestCostEntry */
@@ -189,6 +226,23 @@ UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_UtilizationEntry_set_value(xds_d
_upb_msg_map_set_value(msg, &value, sizeof(double));
}
+/* xds.data.orca.v3.OrcaLoadReport.NamedMetricsEntry */
+
+UPB_INLINE upb_StringView xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry_key(const xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry* msg) {
+ upb_StringView ret;
+ _upb_msg_map_key(msg, &ret, 0);
+ return ret;
+}
+UPB_INLINE double xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry_value(const xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry* msg) {
+ double ret;
+ _upb_msg_map_value(msg, &ret, sizeof(ret));
+ return ret;
+}
+
+UPB_INLINE void xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry_set_value(xds_data_orca_v3_OrcaLoadReport_NamedMetricsEntry *msg, double value) {
+ _upb_msg_map_set_value(msg, &value, sizeof(double));
+}
+
extern const upb_MiniTable_File xds_data_orca_v3_orca_load_report_proto_upb_file_layout;
#ifdef __cplusplus
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c
index 83fbec6a7a..814c5a858c 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c
@@ -34,7 +34,7 @@ extern _upb_DefPool_Init udpa_annotations_security_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_versioning_proto_upbdefinit;
extern _upb_DefPool_Init validate_validate_proto_upbdefinit;
-static const char descriptor[8318] = {'\n', ')', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '/',
+static const char descriptor[8405] = {'\n', ')', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '/',
'v', '3', '/', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'p', 'r', 'o', 't', 'o', '\022', '\031', 'e', 'n', 'v', 'o', 'y',
'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '\032', ')', 'e', 'n', 'v',
'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'a', 'c', 'c', 'e', 's', 's', 'l', 'o', 'g', '/', 'v', '3', '/', 'a', 'c',
@@ -72,7 +72,7 @@ static const char descriptor[8318] = {'\n', ')', 'e', 'n', 'v', 'o', 'y', '/', '
'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't',
'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i',
'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l',
-'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\213', '\034', '\n', '\t', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p',
+'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\342', '\034', '\n', '\t', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p',
'\022', '.', '\n', '\004', 'n', 'o', 'd', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\032', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o',
'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'N', 'o', 'd', 'e', 'R', '\004', 'n', 'o', 'd', 'e', '\022', '.',
'\n', '\023', 'n', 'o', 'd', 'e', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 'p', 'a', 'r', 'a', 'm', 's', '\030', '\032', ' ', '\003',
@@ -180,193 +180,197 @@ static const char descriptor[8318] = {'\n', ')', 'e', 'n', 'v', 'o', 'y', '/', '
'f', 'i', 'g', '_', 't', 'r', 'a', 'c', 'k', 'e', 'r', '_', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '$', ' ', '\001',
'(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3',
'.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\031', 'x', 'd',
-'s', 'C', 'o', 'n', 'f', 'i', 'g', 'T', 'r', 'a', 'c', 'k', 'e', 'r', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\032', '\232',
-'\002', '\n', '\017', 'S', 't', 'a', 't', 'i', 'c', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '\022', '@', '\n', '\t', 'l', 'i', 's',
-'t', 'e', 'n', 'e', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f',
-'i', 'g', '.', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '.', 'v', '3', '.', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'R', '\t',
-'l', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', '\022', '<', '\n', '\010', 'c', 'l', 'u', 's', 't', 'e', 'r', 's', '\030', '\002', ' ', '\003',
-'(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r',
-'.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'R', '\010', 'c', 'l', 'u', 's', 't', 'e', 'r', 's', '\022', 'K', '\n', '\007',
-'s', 'e', 'c', 'r', 'e', 't', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '1', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't',
-'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's',
-'.', 't', 'l', 's', '.', 'v', '3', '.', 'S', 'e', 'c', 'r', 'e', 't', 'R', '\007', 's', 'e', 'c', 'r', 'e', 't', 's', ':', ':',
-'\232', '\305', '\210', '\036', '5', '\n', '3', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's',
-'t', 'r', 'a', 'p', '.', 'v', '2', '.', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'S', 't', 'a', 't', 'i', 'c', 'R',
-'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '\032', '\211', '\003', '\n', '\020', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'R', 'e', 's', 'o', 'u',
-'r', 'c', 'e', 's', '\022', 'A', '\n', '\n', 'l', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2',
-'\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o',
-'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\t', 'l', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '2', '\n', '\025',
-'l', 'd', 's', '_', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '_', 'l', 'o', 'c', 'a', 't', 'o', 'r', '\030', '\005', ' ', '\001',
-'(', '\t', 'R', '\023', 'l', 'd', 's', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', 'L', 'o', 'c', 'a', 't', 'o', 'r', '\022', 'A',
-'\n', '\n', 'c', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o',
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o',
-'u', 'r', 'c', 'e', 'R', '\t', 'c', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '2', '\n', '\025', 'c', 'd', 's', '_', 'r', 'e',
-'s', 'o', 'u', 'r', 'c', 'e', 's', '_', 'l', 'o', 'c', 'a', 't', 'o', 'r', '\030', '\006', ' ', '\001', '(', '\t', 'R', '\023', 'c', 'd',
-'s', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', 'L', 'o', 'c', 'a', 't', 'o', 'r', '\022', 'D', '\n', '\n', 'a', 'd', 's', '_',
-'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '%', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f',
-'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'p', 'i', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c',
-'e', 'R', '\t', 'a', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', ':', ';', '\232', '\305', '\210', '\036', '6', '\n', '4', 'e', 'n', 'v', 'o',
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'B', 'o', 'o',
-'t', 's', 't', 'r', 'a', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', 'J', '\004',
-'\010', '\004', '\020', '\005', '\032', '{', '\n', '!', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd',
-'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001',
-' ', '\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', '@', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2',
+'s', 'C', 'o', 'n', 'f', 'i', 'g', 'T', 'r', 'a', 'c', 'k', 'e', 'r', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\022', 'U',
+'\n', '\020', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '\030', '%', ' ', '\001', '(', '\013', '2',
'*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y',
-'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\005', 'v', 'a', 'l', 'u', 'e',
-':', '\002', '8', '\001', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g',
-'.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', 'B', '\r',
-'\n', '\013', 's', 't', 'a', 't', 's', '_', 'f', 'l', 'u', 's', 'h', 'J', '\004', '\010', '\n', '\020', '\013', 'J', '\004', '\010', '\013', '\020', '\014',
-'R', '\007', 'r', 'u', 'n', 't', 'i', 'm', 'e', '\"', '\211', '\003', '\n', '\005', 'A', 'd', 'm', 'i', 'n', '\022', 'C', '\n', '\n', 'a', 'c',
-'c', 'e', 's', 's', '_', 'l', 'o', 'g', '\030', '\005', ' ', '\003', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o',
-'n', 'f', 'i', 'g', '.', 'a', 'c', 'c', 'e', 's', 's', 'l', 'o', 'g', '.', 'v', '3', '.', 'A', 'c', 'c', 'e', 's', 's', 'L',
-'o', 'g', 'R', '\t', 'a', 'c', 'c', 'e', 's', 's', 'L', 'o', 'g', '\022', '3', '\n', '\017', 'a', 'c', 'c', 'e', 's', 's', '_', 'l',
-'o', 'g', '_', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.',
-'0', 'R', '\r', 'a', 'c', 'c', 'e', 's', 's', 'L', 'o', 'g', 'P', 'a', 't', 'h', '\022', '!', '\n', '\014', 'p', 'r', 'o', 'f', 'i',
-'l', 'e', '_', 'p', 'a', 't', 'h', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\013', 'p', 'r', 'o', 'f', 'i', 'l', 'e', 'P', 'a', 't',
-'h', '\022', '7', '\n', '\007', 'a', 'd', 'd', 'r', 'e', 's', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '\035', '.', 'e', 'n', 'v', 'o',
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'd', 'd', 'r', 'e', 's', 's', 'R',
-'\007', 'a', 'd', 'd', 'r', 'e', 's', 's', '\022', 'I', '\n', '\016', 's', 'o', 'c', 'k', 'e', 't', '_', 'o', 'p', 't', 'i', 'o', 'n',
-'s', '\030', '\004', ' ', '\003', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o',
-'r', 'e', '.', 'v', '3', '.', 'S', 'o', 'c', 'k', 'e', 't', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\r', 's', 'o', 'c', 'k', 'e',
-'t', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '7', '\n', '\030', 'i', 'g', 'n', 'o', 'r', 'e', '_', 'g', 'l', 'o', 'b', 'a', 'l',
-'_', 'c', 'o', 'n', 'n', '_', 'l', 'i', 'm', 'i', 't', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\025', 'i', 'g', 'n', 'o', 'r', 'e',
-'G', 'l', 'o', 'b', 'a', 'l', 'C', 'o', 'n', 'n', 'L', 'i', 'm', 'i', 't', ':', '&', '\232', '\305', '\210', '\036', '!', '\n', '\037', 'e',
-'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.',
-'A', 'd', 'm', 'i', 'n', '\"', '\313', '\004', '\n', '\016', 'C', 'l', 'u', 's', 't', 'e', 'r', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '\022',
-',', '\n', '\022', 'l', 'o', 'c', 'a', 'l', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001',
-'(', '\t', 'R', '\020', 'l', 'o', 'c', 'a', 'l', 'C', 'l', 'u', 's', 't', 'e', 'r', 'N', 'a', 'm', 'e', '\022', 'g', '\n', '\021', 'o',
-'u', 't', 'l', 'i', 'e', 'r', '_', 'd', 'e', 't', 'e', 'c', 't', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\013', '2', ':', '.',
-'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3',
-'.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'O', 'u', 't', 'l', 'i', 'e', 'r', 'D', 'e',
-'t', 'e', 'c', 't', 'i', 'o', 'n', 'R', '\020', 'o', 'u', 't', 'l', 'i', 'e', 'r', 'D', 'e', 't', 'e', 'c', 't', 'i', 'o', 'n',
-'\022', 'R', '\n', '\024', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', '_', 'b', 'i', 'n', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030',
-'\003', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e',
-'.', 'v', '3', '.', 'B', 'i', 'n', 'd', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\022', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', 'B',
-'i', 'n', 'd', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'Q', '\n', '\021', 'l', 'o', 'a', 'd', '_', 's', 't', 'a', 't', 's', '_', 'c',
-'o', 'n', 'f', 'i', 'g', '\030', '\004', ' ', '\001', '(', '\013', '2', '%', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
-'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'p', 'i', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e',
-'R', '\017', 'l', 'o', 'a', 'd', 'S', 't', 'a', 't', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\311', '\001', '\n', '\020', 'O', 'u', 't',
-'l', 'i', 'e', 'r', 'D', 'e', 't', 'e', 'c', 't', 'i', 'o', 'n', '\022', '$', '\n', '\016', 'e', 'v', 'e', 'n', 't', '_', 'l', 'o',
-'g', '_', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\014', 'e', 'v', 'e', 'n', 't', 'L', 'o', 'g', 'P', 'a', 't',
-'h', '\022', 'M', '\n', '\r', 'e', 'v', 'e', 'n', 't', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2',
-'(', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'E', 'v',
-'e', 'n', 't', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\014', 'e', 'v', 'e', 'n', 't', 'S', 'e',
-'r', 'v', 'i', 'c', 'e', ':', '@', '\232', '\305', '\210', '\036', ';', '\n', '9', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
-'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'M', 'a', 'n',
-'a', 'g', 'e', 'r', '.', 'O', 'u', 't', 'l', 'i', 'e', 'r', 'D', 'e', 't', 'e', 'c', 't', 'i', 'o', 'n', ':', '/', '\232', '\305',
-'\210', '\036', '*', '\n', '(', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r',
-'a', 'p', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '\"', '\260', '\001', '\n', '\t',
-'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 's', '\022', 'U', '\n', '\024', 'm', 'a', 'i', 'n', '_', 't', 'h', 'r', 'e', 'a', 'd', '_',
-'w', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o',
-'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o',
-'g', 'R', '\022', 'm', 'a', 'i', 'n', 'T', 'h', 'r', 'e', 'a', 'd', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\022', 'L', '\n', '\017',
-'w', 'o', 'r', 'k', 'e', 'r', '_', 'w', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '#', '.', 'e',
-'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.',
-'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'R', '\016', 'w', 'o', 'r', 'k', 'e', 'r', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\"',
-'\272', '\006', '\n', '\010', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\022', 'L', '\n', '\007', 'a', 'c', 't', 'i', 'o', 'n', 's', '\030', '\007',
-' ', '\003', '(', '\013', '2', '2', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's',
-'t', 'r', 'a', 'p', '.', 'v', '3', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g',
-'A', 'c', 't', 'i', 'o', 'n', 'R', '\007', 'a', 'c', 't', 'i', 'o', 'n', 's', '\022', '<', '\n', '\014', 'm', 'i', 's', 's', '_', 't',
-'i', 'm', 'e', 'o', 'u', 't', '\030', '\001', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o',
-'t', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\013', 'm', 'i', 's', 's', 'T', 'i', 'm', 'e', 'o',
-'u', 't', '\022', 'D', '\n', '\020', 'm', 'e', 'g', 'a', 'm', 'i', 's', 's', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\002', ' ',
-'\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r',
-'a', 't', 'i', 'o', 'n', 'R', '\017', 'm', 'e', 'g', 'a', 'm', 'i', 's', 's', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', '<', '\n',
-'\014', 'k', 'i', 'l', 'l', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\003', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o',
-'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\013', 'k', 'i',
-'l', 'l', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'Z', '\n', '\027', 'm', 'a', 'x', '_', 'k', 'i', 'l', 'l', '_', 't', 'i', 'm',
-'e', 'o', 'u', 't', '_', 'j', 'i', 't', 't', 'e', 'r', '\030', '\006', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l',
-'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\252',
-'\001', '\002', '2', '\000', 'R', '\024', 'm', 'a', 'x', 'K', 'i', 'l', 'l', 'T', 'i', 'm', 'e', 'o', 'u', 't', 'J', 'i', 't', 't', 'e',
-'r', '\022', 'F', '\n', '\021', 'm', 'u', 'l', 't', 'i', 'k', 'i', 'l', 'l', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\004', ' ',
-'\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r',
-'a', 't', 'i', 'o', 'n', 'R', '\020', 'm', 'u', 'l', 't', 'i', 'k', 'i', 'l', 'l', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'G',
-'\n', '\023', 'm', 'u', 'l', 't', 'i', 'k', 'i', 'l', 'l', '_', 't', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\030', '\005', ' ', '\001',
-'(', '\013', '2', '\026', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n',
-'t', 'R', '\022', 'm', 'u', 'l', 't', 'i', 'k', 'i', 'l', 'l', 'T', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\032', '\205', '\002', '\n',
-'\016', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'A', 'c', 't', 'i', 'o', 'n', '\022', 'B', '\n', '\006', 'c', 'o', 'n', 'f', 'i', 'g',
-'\030', '\001', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r',
-'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g',
-'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\022', '`', '\n', '\005', 'e', 'v', 'e', 'n', 't', '\030', '\002', ' ', '\001', '(', '\016', '2', '@',
-'.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v',
-'3', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'A', 'c', 't', 'i', 'o', 'n',
-'.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'E', 'v', 'e', 'n', 't', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R',
-'\005', 'e', 'v', 'e', 'n', 't', '\"', 'M', '\n', '\r', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'E', 'v', 'e', 'n', 't', '\022', '\013',
-'\n', '\007', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\010', '\n', '\004', 'K', 'I', 'L', 'L', '\020', '\001', '\022', '\r', '\n', '\t',
-'M', 'U', 'L', 'T', 'I', 'K', 'I', 'L', 'L', '\020', '\002', '\022', '\014', '\n', '\010', 'M', 'E', 'G', 'A', 'M', 'I', 'S', 'S', '\020', '\003',
-'\022', '\010', '\n', '\004', 'M', 'I', 'S', 'S', '\020', '\004', ':', ')', '\232', '\305', '\210', '\036', '$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', '.',
-'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'W', 'a', 't', 'c', 'h',
-'d', 'o', 'g', '\"', 'Q', '\n', '\013', 'F', 'a', 't', 'a', 'l', 'A', 'c', 't', 'i', 'o', 'n', '\022', 'B', '\n', '\006', 'c', 'o', 'n',
-'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.',
-'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n',
-'f', 'i', 'g', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\"', '\334', '\001', '\n', '\007', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\022', '!',
+'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\017', 'l', 'i', 's', 't', 'e',
+'n', 'e', 'r', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '\032', '\232', '\002', '\n', '\017', 'S', 't', 'a', 't', 'i', 'c', 'R', 'e', 's', 'o',
+'u', 'r', 'c', 'e', 's', '\022', '@', '\n', '\t', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2',
+'\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '.', 'v',
+'3', '.', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'R', '\t', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', '\022', '<', '\n', '\010',
+'c', 'l', 'u', 's', 't', 'e', 'r', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o',
+'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', 'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'R', '\010',
+'c', 'l', 'u', 's', 't', 'e', 'r', 's', '\022', 'K', '\n', '\007', 's', 'e', 'c', 'r', 'e', 't', 's', '\030', '\003', ' ', '\003', '(', '\013',
+'2', '1', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's',
+'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'S', 'e', 'c', 'r', 'e',
+'t', 'R', '\007', 's', 'e', 'c', 'r', 'e', 't', 's', ':', ':', '\232', '\305', '\210', '\036', '5', '\n', '3', 'e', 'n', 'v', 'o', 'y', '.',
+'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'B', 'o', 'o', 't', 's',
+'t', 'r', 'a', 'p', '.', 'S', 't', 'a', 't', 'i', 'c', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '\032', '\211', '\003', '\n', '\020',
+'D', 'y', 'n', 'a', 'm', 'i', 'c', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '\022', 'A', '\n', '\n', 'l', 'd', 's', '_', 'c',
+'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
+'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\t', 'l',
+'d', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '2', '\n', '\025', 'l', 'd', 's', '_', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's',
+'_', 'l', 'o', 'c', 'a', 't', 'o', 'r', '\030', '\005', ' ', '\001', '(', '\t', 'R', '\023', 'l', 'd', 's', 'R', 'e', 's', 'o', 'u', 'r',
+'c', 'e', 's', 'L', 'o', 'c', 'a', 't', 'o', 'r', '\022', 'A', '\n', '\n', 'c', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030',
+'\002', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e',
+'.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\t', 'c', 'd', 's', 'C', 'o', 'n', 'f',
+'i', 'g', '\022', '2', '\n', '\025', 'c', 'd', 's', '_', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '_', 'l', 'o', 'c', 'a', 't',
+'o', 'r', '\030', '\006', ' ', '\001', '(', '\t', 'R', '\023', 'c', 'd', 's', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', 'L', 'o', 'c',
+'a', 't', 'o', 'r', '\022', 'D', '\n', '\n', 'a', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2',
+'%', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'p',
+'i', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\t', 'a', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', ':',
+';', '\232', '\305', '\210', '\036', '6', '\n', '4', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't',
+'s', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i',
+'c', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', 'J', '\004', '\010', '\004', '\020', '\005', '\032', '{', '\n', '!', 'C', 'e', 'r', 't', 'i',
+'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 's', 'E', 'n',
+'t', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', '@', '\n', '\005',
+'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
+'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C',
+'o', 'n', 'f', 'i', 'g', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#',
+'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2',
+'.', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', 'B', '\r', '\n', '\013', 's', 't', 'a', 't', 's', '_', 'f', 'l', 'u', 's', 'h',
+'J', '\004', '\010', '\n', '\020', '\013', 'J', '\004', '\010', '\013', '\020', '\014', 'R', '\007', 'r', 'u', 'n', 't', 'i', 'm', 'e', '\"', '\211', '\003', '\n',
+'\005', 'A', 'd', 'm', 'i', 'n', '\022', 'C', '\n', '\n', 'a', 'c', 'c', 'e', 's', 's', '_', 'l', 'o', 'g', '\030', '\005', ' ', '\003', '(',
+'\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'a', 'c', 'c', 'e', 's', 's', 'l', 'o',
+'g', '.', 'v', '3', '.', 'A', 'c', 'c', 'e', 's', 's', 'L', 'o', 'g', 'R', '\t', 'a', 'c', 'c', 'e', 's', 's', 'L', 'o', 'g',
+'\022', '3', '\n', '\017', 'a', 'c', 'c', 'e', 's', 's', '_', 'l', 'o', 'g', '_', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\001', '(', '\t',
+'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'R', '\r', 'a', 'c', 'c', 'e', 's', 's', 'L', 'o', 'g', 'P',
+'a', 't', 'h', '\022', '!', '\n', '\014', 'p', 'r', 'o', 'f', 'i', 'l', 'e', '_', 'p', 'a', 't', 'h', '\030', '\002', ' ', '\001', '(', '\t',
+'R', '\013', 'p', 'r', 'o', 'f', 'i', 'l', 'e', 'P', 'a', 't', 'h', '\022', '7', '\n', '\007', 'a', 'd', 'd', 'r', 'e', 's', 's', '\030',
+'\003', ' ', '\001', '(', '\013', '2', '\035', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e',
+'.', 'v', '3', '.', 'A', 'd', 'd', 'r', 'e', 's', 's', 'R', '\007', 'a', 'd', 'd', 'r', 'e', 's', 's', '\022', 'I', '\n', '\016', 's',
+'o', 'c', 'k', 'e', 't', '_', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\004', ' ', '\003', '(', '\013', '2', '\"', '.', 'e', 'n', 'v',
+'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'S', 'o', 'c', 'k', 'e', 't', 'O',
+'p', 't', 'i', 'o', 'n', 'R', '\r', 's', 'o', 'c', 'k', 'e', 't', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '7', '\n', '\030', 'i',
+'g', 'n', 'o', 'r', 'e', '_', 'g', 'l', 'o', 'b', 'a', 'l', '_', 'c', 'o', 'n', 'n', '_', 'l', 'i', 'm', 'i', 't', '\030', '\006',
+' ', '\001', '(', '\010', 'R', '\025', 'i', 'g', 'n', 'o', 'r', 'e', 'G', 'l', 'o', 'b', 'a', 'l', 'C', 'o', 'n', 'n', 'L', 'i', 'm',
+'i', 't', ':', '&', '\232', '\305', '\210', '\036', '!', '\n', '\037', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b',
+'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'A', 'd', 'm', 'i', 'n', '\"', '\313', '\004', '\n', '\016', 'C', 'l', 'u',
+'s', 't', 'e', 'r', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '\022', ',', '\n', '\022', 'l', 'o', 'c', 'a', 'l', '_', 'c', 'l', 'u', 's',
+'t', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\020', 'l', 'o', 'c', 'a', 'l', 'C', 'l', 'u', 's',
+'t', 'e', 'r', 'N', 'a', 'm', 'e', '\022', 'g', '\n', '\021', 'o', 'u', 't', 'l', 'i', 'e', 'r', '_', 'd', 'e', 't', 'e', 'c', 't',
+'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\013', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.',
+'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'M', 'a', 'n', 'a', 'g',
+'e', 'r', '.', 'O', 'u', 't', 'l', 'i', 'e', 'r', 'D', 'e', 't', 'e', 'c', 't', 'i', 'o', 'n', 'R', '\020', 'o', 'u', 't', 'l',
+'i', 'e', 'r', 'D', 'e', 't', 'e', 'c', 't', 'i', 'o', 'n', '\022', 'R', '\n', '\024', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', '_',
+'b', 'i', 'n', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y',
+'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'B', 'i', 'n', 'd', 'C', 'o', 'n', 'f', 'i',
+'g', 'R', '\022', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', 'B', 'i', 'n', 'd', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'Q', '\n', '\021',
+'l', 'o', 'a', 'd', '_', 's', 't', 'a', 't', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\004', ' ', '\001', '(', '\013', '2', '%',
+'.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'p', 'i',
+'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\017', 'l', 'o', 'a', 'd', 'S', 't', 'a', 't', 's', 'C', 'o',
+'n', 'f', 'i', 'g', '\032', '\311', '\001', '\n', '\020', 'O', 'u', 't', 'l', 'i', 'e', 'r', 'D', 'e', 't', 'e', 'c', 't', 'i', 'o', 'n',
+'\022', '$', '\n', '\016', 'e', 'v', 'e', 'n', 't', '_', 'l', 'o', 'g', '_', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\001', '(', '\t', 'R',
+'\014', 'e', 'v', 'e', 'n', 't', 'L', 'o', 'g', 'P', 'a', 't', 'h', '\022', 'M', '\n', '\r', 'e', 'v', 'e', 'n', 't', '_', 's', 'e',
+'r', 'v', 'i', 'c', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '(', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
+'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'E', 'v', 'e', 'n', 't', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'C', 'o', 'n',
+'f', 'i', 'g', 'R', '\014', 'e', 'v', 'e', 'n', 't', 'S', 'e', 'r', 'v', 'i', 'c', 'e', ':', '@', '\232', '\305', '\210', '\036', ';', '\n',
+'9', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v',
+'2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'O', 'u', 't', 'l', 'i', 'e', 'r', 'D',
+'e', 't', 'e', 'c', 't', 'i', 'o', 'n', ':', '/', '\232', '\305', '\210', '\036', '*', '\n', '(', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o',
+'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r',
+'M', 'a', 'n', 'a', 'g', 'e', 'r', '\"', '\260', '\001', '\n', '\t', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 's', '\022', 'U', '\n', '\024',
+'m', 'a', 'i', 'n', '_', 't', 'h', 'r', 'e', 'a', 'd', '_', 'w', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\030', '\001', ' ', '\001', '(',
+'\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a',
+'p', '.', 'v', '3', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'R', '\022', 'm', 'a', 'i', 'n', 'T', 'h', 'r', 'e', 'a', 'd',
+'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\022', 'L', '\n', '\017', 'w', 'o', 'r', 'k', 'e', 'r', '_', 'w', 'a', 't', 'c', 'h', 'd',
+'o', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b',
+'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'R', '\016', 'w', 'o', 'r',
+'k', 'e', 'r', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\"', '\272', '\006', '\n', '\010', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\022',
+'L', '\n', '\007', 'a', 'c', 't', 'i', 'o', 'n', 's', '\030', '\007', ' ', '\003', '(', '\013', '2', '2', '.', 'e', 'n', 'v', 'o', 'y', '.',
+'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'W', 'a', 't', 'c', 'h',
+'d', 'o', 'g', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'A', 'c', 't', 'i', 'o', 'n', 'R', '\007', 'a', 'c', 't', 'i', 'o',
+'n', 's', '\022', '<', '\n', '\014', 'm', 'i', 's', 's', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\001', ' ', '\001', '(', '\013', '2',
+'\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o',
+'n', 'R', '\013', 'm', 'i', 's', 's', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'D', '\n', '\020', 'm', 'e', 'g', 'a', 'm', 'i', 's',
+'s', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\002', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.',
+'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\017', 'm', 'e', 'g', 'a', 'm', 'i',
+'s', 's', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', '<', '\n', '\014', 'k', 'i', 'l', 'l', '_', 't', 'i', 'm', 'e', 'o', 'u', 't',
+'\030', '\003', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.',
+'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\013', 'k', 'i', 'l', 'l', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'Z', '\n', '\027',
+'m', 'a', 'x', '_', 'k', 'i', 'l', 'l', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '_', 'j', 'i', 't', 't', 'e', 'r', '\030', '\006',
+' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u',
+'r', 'a', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\252', '\001', '\002', '2', '\000', 'R', '\024', 'm', 'a', 'x', 'K', 'i', 'l', 'l',
+'T', 'i', 'm', 'e', 'o', 'u', 't', 'J', 'i', 't', 't', 'e', 'r', '\022', 'F', '\n', '\021', 'm', 'u', 'l', 't', 'i', 'k', 'i', 'l',
+'l', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.',
+'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\020', 'm', 'u', 'l', 't', 'i', 'k',
+'i', 'l', 'l', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'G', '\n', '\023', 'm', 'u', 'l', 't', 'i', 'k', 'i', 'l', 'l', '_', 't',
+'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\030', '\005', ' ', '\001', '(', '\013', '2', '\026', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y',
+'p', 'e', '.', 'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\022', 'm', 'u', 'l', 't', 'i', 'k', 'i', 'l', 'l', 'T',
+'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\032', '\205', '\002', '\n', '\016', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'A', 'c', 't', 'i',
+'o', 'n', '\022', 'B', '\n', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o',
+'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't',
+'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\022', '`', '\n', '\005', 'e',
+'v', 'e', 'n', 't', '\030', '\002', ' ', '\001', '(', '\016', '2', '@', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g',
+'.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '.', 'W', 'a',
+'t', 'c', 'h', 'd', 'o', 'g', 'A', 'c', 't', 'i', 'o', 'n', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'E', 'v', 'e', 'n',
+'t', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\005', 'e', 'v', 'e', 'n', 't', '\"', 'M', '\n', '\r', 'W', 'a', 't',
+'c', 'h', 'd', 'o', 'g', 'E', 'v', 'e', 'n', 't', '\022', '\013', '\n', '\007', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\010',
+'\n', '\004', 'K', 'I', 'L', 'L', '\020', '\001', '\022', '\r', '\n', '\t', 'M', 'U', 'L', 'T', 'I', 'K', 'I', 'L', 'L', '\020', '\002', '\022', '\014',
+'\n', '\010', 'M', 'E', 'G', 'A', 'M', 'I', 'S', 'S', '\020', '\003', '\022', '\010', '\n', '\004', 'M', 'I', 'S', 'S', '\020', '\004', ':', ')', '\232',
+'\305', '\210', '\036', '$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't',
+'r', 'a', 'p', '.', 'v', '2', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\"', 'Q', '\n', '\013', 'F', 'a', 't', 'a', 'l', 'A',
+'c', 't', 'i', 'o', 'n', '\022', 'B', '\n', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '*', '.', 'e',
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd',
+'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\"', '\334',
+'\001', '\n', '\007', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\022', '!', '\n', '\014', 's', 'y', 'm', 'l', 'i', 'n', 'k', '_', 'r', 'o', 'o',
+'t', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 's', 'y', 'm', 'l', 'i', 'n', 'k', 'R', 'o', 'o', 't', '\022', '\"', '\n', '\014', 's',
+'u', 'b', 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\014', 's', 'u', 'b', 'd', 'i', 'r',
+'e', 'c', 't', 'o', 'r', 'y', '\022', '3', '\n', '\025', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '_', 's', 'u', 'b', 'd', 'i', 'r',
+'e', 'c', 't', 'o', 'r', 'y', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\024', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', 'S', 'u', 'b',
+'d', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\022', '+', '\n', '\004', 'b', 'a', 's', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '\027',
+'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 't', 'R', '\004',
+'b', 'a', 's', 'e', ':', '(', '\232', '\305', '\210', '\036', '#', '\n', '!', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g',
+'.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\"', '\333', '\006', '\n',
+'\014', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001',
+'(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '<', '\n', '\014', 's', 't', 'a', 't',
+'i', 'c', '_', 'l', 'a', 'y', 'e', 'r', '\030', '\002', ' ', '\001', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p',
+'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 't', 'H', '\000', 'R', '\013', 's', 't', 'a', 't', 'i', 'c', 'L',
+'a', 'y', 'e', 'r', '\022', 'R', '\n', '\n', 'd', 'i', 's', 'k', '_', 'l', 'a', 'y', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\013', '2',
+'1', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.',
+'v', '3', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '.', 'D', 'i', 's', 'k', 'L', 'a', 'y', 'e', 'r',
+'H', '\000', 'R', '\t', 'd', 'i', 's', 'k', 'L', 'a', 'y', 'e', 'r', '\022', 'U', '\n', '\013', 'a', 'd', 'm', 'i', 'n', '_', 'l', 'a',
+'y', 'e', 'r', '\030', '\004', ' ', '\001', '(', '\013', '2', '2', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.',
+'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r',
+'.', 'A', 'd', 'm', 'i', 'n', 'L', 'a', 'y', 'e', 'r', 'H', '\000', 'R', '\n', 'a', 'd', 'm', 'i', 'n', 'L', 'a', 'y', 'e', 'r',
+'\022', 'R', '\n', '\n', 'r', 't', 'd', 's', '_', 'l', 'a', 'y', 'e', 'r', '\030', '\005', ' ', '\001', '(', '\013', '2', '1', '.', 'e', 'n',
+'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'R',
+'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '.', 'R', 't', 'd', 's', 'L', 'a', 'y', 'e', 'r', 'H', '\000', 'R', '\t',
+'r', 't', 'd', 's', 'L', 'a', 'y', 'e', 'r', '\032', '\301', '\001', '\n', '\t', 'D', 'i', 's', 'k', 'L', 'a', 'y', 'e', 'r', '\022', '!',
'\n', '\014', 's', 'y', 'm', 'l', 'i', 'n', 'k', '_', 'r', 'o', 'o', 't', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 's', 'y', 'm',
'l', 'i', 'n', 'k', 'R', 'o', 'o', 't', '\022', '\"', '\n', '\014', 's', 'u', 'b', 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\030',
-'\002', ' ', '\001', '(', '\t', 'R', '\014', 's', 'u', 'b', 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\022', '3', '\n', '\025', 'o', 'v',
-'e', 'r', 'r', 'i', 'd', 'e', '_', 's', 'u', 'b', 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\030', '\003', ' ', '\001', '(', '\t',
-'R', '\024', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', 'S', 'u', 'b', 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\022', '+', '\n',
-'\004', 'b', 'a', 's', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't',
-'o', 'b', 'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 't', 'R', '\004', 'b', 'a', 's', 'e', ':', '(', '\232', '\305', '\210', '\036', '#', '\n',
-'!', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v',
-'2', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\"', '\333', '\006', '\n', '\014', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e',
-'r', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R',
-'\004', 'n', 'a', 'm', 'e', '\022', '<', '\n', '\014', 's', 't', 'a', 't', 'i', 'c', '_', 'l', 'a', 'y', 'e', 'r', '\030', '\002', ' ', '\001',
-'(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 't', 'r', 'u',
-'c', 't', 'H', '\000', 'R', '\013', 's', 't', 'a', 't', 'i', 'c', 'L', 'a', 'y', 'e', 'r', '\022', 'R', '\n', '\n', 'd', 'i', 's', 'k',
-'_', 'l', 'a', 'y', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\013', '2', '1', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f',
-'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a',
-'y', 'e', 'r', '.', 'D', 'i', 's', 'k', 'L', 'a', 'y', 'e', 'r', 'H', '\000', 'R', '\t', 'd', 'i', 's', 'k', 'L', 'a', 'y', 'e',
-'r', '\022', 'U', '\n', '\013', 'a', 'd', 'm', 'i', 'n', '_', 'l', 'a', 'y', 'e', 'r', '\030', '\004', ' ', '\001', '(', '\013', '2', '2', '.',
-'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3',
-'.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '.', 'A', 'd', 'm', 'i', 'n', 'L', 'a', 'y', 'e', 'r', 'H',
-'\000', 'R', '\n', 'a', 'd', 'm', 'i', 'n', 'L', 'a', 'y', 'e', 'r', '\022', 'R', '\n', '\n', 'r', 't', 'd', 's', '_', 'l', 'a', 'y',
-'e', 'r', '\030', '\005', ' ', '\001', '(', '\013', '2', '1', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b',
-'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '.',
-'R', 't', 'd', 's', 'L', 'a', 'y', 'e', 'r', 'H', '\000', 'R', '\t', 'r', 't', 'd', 's', 'L', 'a', 'y', 'e', 'r', '\032', '\301', '\001',
-'\n', '\t', 'D', 'i', 's', 'k', 'L', 'a', 'y', 'e', 'r', '\022', '!', '\n', '\014', 's', 'y', 'm', 'l', 'i', 'n', 'k', '_', 'r', 'o',
-'o', 't', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 's', 'y', 'm', 'l', 'i', 'n', 'k', 'R', 'o', 'o', 't', '\022', '\"', '\n', '\014',
-'s', 'u', 'b', 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\014', 's', 'u', 'b', 'd', 'i',
-'r', 'e', 'c', 't', 'o', 'r', 'y', '\022', '4', '\n', '\026', 'a', 'p', 'p', 'e', 'n', 'd', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e',
-'_', 'c', 'l', 'u', 's', 't', 'e', 'r', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\024', 'a', 'p', 'p', 'e', 'n', 'd', 'S', 'e', 'r',
-'v', 'i', 'c', 'e', 'C', 'l', 'u', 's', 't', 'e', 'r', ':', '7', '\232', '\305', '\210', '\036', '2', '\n', '0', 'e', 'n', 'v', 'o', 'y',
-'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'R', 'u', 'n', 't',
-'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '.', 'D', 'i', 's', 'k', 'L', 'a', 'y', 'e', 'r', '\032', 'F', '\n', '\n', 'A', 'd', 'm',
-'i', 'n', 'L', 'a', 'y', 'e', 'r', ':', '8', '\232', '\305', '\210', '\036', '3', '\n', '1', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n',
-'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L',
-'a', 'y', 'e', 'r', '.', 'A', 'd', 'm', 'i', 'n', 'L', 'a', 'y', 'e', 'r', '\032', '\235', '\001', '\n', '\t', 'R', 't', 'd', 's', 'L',
-'a', 'y', 'e', 'r', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022',
-'C', '\n', '\013', 'r', 't', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n',
-'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g',
-'S', 'o', 'u', 'r', 'c', 'e', 'R', '\n', 'r', 't', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', ':', '7', '\232', '\305', '\210', '\036', '2',
-'\n', '0', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.',
-'v', '2', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '.', 'R', 't', 'd', 's', 'L', 'a', 'y', 'e', 'r',
-':', '-', '\232', '\305', '\210', '\036', '(', '\n', '&', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o',
-'t', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', 'B', '\026', '\n',
-'\017', 'l', 'a', 'y', 'e', 'r', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', '\"', '\202', '\001', '\n',
-'\016', 'L', 'a', 'y', 'e', 'r', 'e', 'd', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\022', '?', '\n', '\006', 'l', 'a', 'y', 'e', 'r', 's',
-'\030', '\001', ' ', '\003', '(', '\013', '2', '\'', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o',
-'t', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', 'R', '\006', 'l',
-'a', 'y', 'e', 'r', 's', ':', '/', '\232', '\305', '\210', '\036', '*', '\n', '(', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
-'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'L', 'a', 'y', 'e', 'r', 'e', 'd', 'R', 'u', 'n',
-'t', 'i', 'm', 'e', '\"', '\261', '\002', '\n', '\022', 'C', 'u', 's', 't', 'o', 'm', 'I', 'n', 'l', 'i', 'n', 'e', 'H', 'e', 'a', 'd',
-'e', 'r', '\022', ';', '\n', '\022', 'i', 'n', 'l', 'i', 'n', 'e', '_', 'h', 'e', 'a', 'd', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030',
-'\001', ' ', '\001', '(', '\t', 'B', '\r', '\372', 'B', '\n', 'r', '\010', '\020', '\001', '\300', '\001', '\001', '\310', '\001', '\000', 'R', '\020', 'i', 'n', 'l',
-'i', 'n', 'e', 'H', 'e', 'a', 'd', 'e', 'r', 'N', 'a', 'm', 'e', '\022', 'v', '\n', '\022', 'i', 'n', 'l', 'i', 'n', 'e', '_', 'h',
-'e', 'a', 'd', 'e', 'r', '_', 't', 'y', 'p', 'e', '\030', '\002', ' ', '\001', '(', '\016', '2', '>', '.', 'e', 'n', 'v', 'o', 'y', '.',
-'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'C', 'u', 's', 't', 'o',
-'m', 'I', 'n', 'l', 'i', 'n', 'e', 'H', 'e', 'a', 'd', 'e', 'r', '.', 'I', 'n', 'l', 'i', 'n', 'e', 'H', 'e', 'a', 'd', 'e',
-'r', 'T', 'y', 'p', 'e', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\020', 'i', 'n', 'l', 'i', 'n', 'e', 'H', 'e',
-'a', 'd', 'e', 'r', 'T', 'y', 'p', 'e', '\"', 'f', '\n', '\020', 'I', 'n', 'l', 'i', 'n', 'e', 'H', 'e', 'a', 'd', 'e', 'r', 'T',
-'y', 'p', 'e', '\022', '\022', '\n', '\016', 'R', 'E', 'Q', 'U', 'E', 'S', 'T', '_', 'H', 'E', 'A', 'D', 'E', 'R', '\020', '\000', '\022', '\023',
-'\n', '\017', 'R', 'E', 'Q', 'U', 'E', 'S', 'T', '_', 'T', 'R', 'A', 'I', 'L', 'E', 'R', '\020', '\001', '\022', '\023', '\n', '\017', 'R', 'E',
-'S', 'P', 'O', 'N', 'S', 'E', '_', 'H', 'E', 'A', 'D', 'E', 'R', '\020', '\002', '\022', '\024', '\n', '\020', 'R', 'E', 'S', 'P', 'O', 'N',
-'S', 'E', '_', 'T', 'R', 'A', 'I', 'L', 'E', 'R', '\020', '\003', 'B', '\221', '\001', '\n', '\'', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y',
-'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't',
-'r', 'a', 'p', '.', 'v', '3', 'B', '\016', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z',
-'L', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o',
-'-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f',
-'i', 'g', '/', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '/', 'v', '3', ';', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p',
-'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
+'\003', ' ', '\001', '(', '\t', 'R', '\014', 's', 'u', 'b', 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\022', '4', '\n', '\026', 'a', 'p',
+'p', 'e', 'n', 'd', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', '\030', '\002', ' ', '\001', '(',
+'\010', 'R', '\024', 'a', 'p', 'p', 'e', 'n', 'd', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'C', 'l', 'u', 's', 't', 'e', 'r', ':', '7',
+'\232', '\305', '\210', '\036', '2', '\n', '0', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's',
+'t', 'r', 'a', 'p', '.', 'v', '2', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '.', 'D', 'i', 's', 'k',
+'L', 'a', 'y', 'e', 'r', '\032', 'F', '\n', '\n', 'A', 'd', 'm', 'i', 'n', 'L', 'a', 'y', 'e', 'r', ':', '8', '\232', '\305', '\210', '\036',
+'3', '\n', '1', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p',
+'.', 'v', '2', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '.', 'A', 'd', 'm', 'i', 'n', 'L', 'a', 'y',
+'e', 'r', '\032', '\235', '\001', '\n', '\t', 'R', 't', 'd', 's', 'L', 'a', 'y', 'e', 'r', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030',
+'\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'C', '\n', '\013', 'r', 't', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i',
+'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o',
+'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\n', 'r', 't', 'd', 's', 'C',
+'o', 'n', 'f', 'i', 'g', ':', '7', '\232', '\305', '\210', '\036', '2', '\n', '0', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
+'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y',
+'e', 'r', '.', 'R', 't', 'd', 's', 'L', 'a', 'y', 'e', 'r', ':', '-', '\232', '\305', '\210', '\036', '(', '\n', '&', 'e', 'n', 'v', 'o',
+'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'R', 'u', 'n',
+'t', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', 'B', '\026', '\n', '\017', 'l', 'a', 'y', 'e', 'r', '_', 's', 'p', 'e', 'c', 'i', 'f',
+'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', '\"', '\202', '\001', '\n', '\016', 'L', 'a', 'y', 'e', 'r', 'e', 'd', 'R', 'u', 'n', 't', 'i',
+'m', 'e', '\022', '?', '\n', '\006', 'l', 'a', 'y', 'e', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\'', '.', 'e', 'n', 'v', 'o',
+'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'R', 'u', 'n',
+'t', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', 'R', '\006', 'l', 'a', 'y', 'e', 'r', 's', ':', '/', '\232', '\305', '\210', '\036', '*', '\n',
+'(', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v',
+'2', '.', 'L', 'a', 'y', 'e', 'r', 'e', 'd', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\"', '\261', '\002', '\n', '\022', 'C', 'u', 's', 't',
+'o', 'm', 'I', 'n', 'l', 'i', 'n', 'e', 'H', 'e', 'a', 'd', 'e', 'r', '\022', ';', '\n', '\022', 'i', 'n', 'l', 'i', 'n', 'e', '_',
+'h', 'e', 'a', 'd', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\r', '\372', 'B', '\n', 'r', '\010', '\020',
+'\001', '\300', '\001', '\001', '\310', '\001', '\000', 'R', '\020', 'i', 'n', 'l', 'i', 'n', 'e', 'H', 'e', 'a', 'd', 'e', 'r', 'N', 'a', 'm', 'e',
+'\022', 'v', '\n', '\022', 'i', 'n', 'l', 'i', 'n', 'e', '_', 'h', 'e', 'a', 'd', 'e', 'r', '_', 't', 'y', 'p', 'e', '\030', '\002', ' ',
+'\001', '(', '\016', '2', '>', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't',
+'r', 'a', 'p', '.', 'v', '3', '.', 'C', 'u', 's', 't', 'o', 'm', 'I', 'n', 'l', 'i', 'n', 'e', 'H', 'e', 'a', 'd', 'e', 'r',
+'.', 'I', 'n', 'l', 'i', 'n', 'e', 'H', 'e', 'a', 'd', 'e', 'r', 'T', 'y', 'p', 'e', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002',
+'\020', '\001', 'R', '\020', 'i', 'n', 'l', 'i', 'n', 'e', 'H', 'e', 'a', 'd', 'e', 'r', 'T', 'y', 'p', 'e', '\"', 'f', '\n', '\020', 'I',
+'n', 'l', 'i', 'n', 'e', 'H', 'e', 'a', 'd', 'e', 'r', 'T', 'y', 'p', 'e', '\022', '\022', '\n', '\016', 'R', 'E', 'Q', 'U', 'E', 'S',
+'T', '_', 'H', 'E', 'A', 'D', 'E', 'R', '\020', '\000', '\022', '\023', '\n', '\017', 'R', 'E', 'Q', 'U', 'E', 'S', 'T', '_', 'T', 'R', 'A',
+'I', 'L', 'E', 'R', '\020', '\001', '\022', '\023', '\n', '\017', 'R', 'E', 'S', 'P', 'O', 'N', 'S', 'E', '_', 'H', 'E', 'A', 'D', 'E', 'R',
+'\020', '\002', '\022', '\024', '\n', '\020', 'R', 'E', 'S', 'P', 'O', 'N', 'S', 'E', '_', 'T', 'R', 'A', 'I', 'L', 'E', 'R', '\020', '\003', 'B',
+'\221', '\001', '\n', '\'', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c',
+'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', 'B', '\016', 'B', 'o', 'o', 't', 's',
+'t', 'r', 'a', 'p', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'L', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e',
+'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n',
+'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '/',
+'v', '3', ';', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p',
+'r', 'o', 't', 'o', '3',
};
static _upb_DefPool_Init *deps[25] = {
@@ -401,5 +405,5 @@ _upb_DefPool_Init envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit = {
deps,
&envoy_config_bootstrap_v3_bootstrap_proto_upb_file_layout,
"envoy/config/bootstrap/v3/bootstrap.proto",
- UPB_STRINGVIEW_INIT(descriptor, 8318)
+ UPB_STRINGVIEW_INIT(descriptor, 8405)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.c
index 7e8581731b..d8c0ee9506 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.c
@@ -19,7 +19,7 @@ extern _upb_DefPool_Init envoy_annotations_deprecation_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_versioning_proto_upbdefinit;
extern _upb_DefPool_Init validate_validate_proto_upbdefinit;
-static const char descriptor[6489] = {'\n', '#', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'p', 'r',
+static const char descriptor[6569] = {'\n', '#', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'p', 'r',
'o', 't', 'o', 'c', 'o', 'l', '.', 'p', 'r', 'o', 't', 'o', '\022', '\024', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', '$', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c',
'o', 'r', 'e', '/', 'v', '3', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '.', 'p', 'r', 'o', 't', 'o', '\032', '\033', 'e',
@@ -123,7 +123,7 @@ static const char descriptor[6489] = {'\n', '#', 'e', 'n', 'v', 'o', 'y', '/', '
'E', 'C', 'T', '_', 'R', 'E', 'Q', 'U', 'E', 'S', 'T', '\020', '\001', '\022', '\017', '\n', '\013', 'D', 'R', 'O', 'P', '_', 'H', 'E', 'A',
'D', 'E', 'R', '\020', '\002', ':', ',', '\232', '\305', '\210', '\036', '\'', '\n', '%', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v',
'2', '.', 'c', 'o', 'r', 'e', '.', 'H', 't', 't', 'p', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n',
-'s', '\"', '\207', '\010', '\n', '\024', 'H', 't', 't', 'p', '1', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n',
+'s', '\"', '\327', '\010', '\n', '\024', 'H', 't', 't', 'p', '1', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n',
's', '\022', 'H', '\n', '\022', 'a', 'l', 'l', 'o', 'w', '_', 'a', 'b', 's', 'o', 'l', 'u', 't', 'e', '_', 'u', 'r', 'l', '\030', '\001',
' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o',
'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', '\020', 'a', 'l', 'l', 'o', 'w', 'A', 'b', 's', 'o', 'l', 'u', 't', 'e', 'U', 'r', 'l',
@@ -145,140 +145,143 @@ static const char descriptor[6489] = {'\n', '#', 'e', 'n', 'v', 'o', 'y', '/', '
'v', 'e', 'r', 'r', 'i', 'd', 'e', 'S', 't', 'r', 'e', 'a', 'm', 'E', 'r', 'r', 'o', 'r', 'O', 'n', 'I', 'n', 'v', 'a', 'l',
'i', 'd', 'H', 't', 't', 'p', 'M', 'e', 's', 's', 'a', 'g', 'e', '\022', '7', '\n', '\030', 's', 'e', 'n', 'd', '_', 'f', 'u', 'l',
'l', 'y', '_', 'q', 'u', 'a', 'l', 'i', 'f', 'i', 'e', 'd', '_', 'u', 'r', 'l', '\030', '\010', ' ', '\001', '(', '\010', 'R', '\025', 's',
-'e', 'n', 'd', 'F', 'u', 'l', 'l', 'y', 'Q', 'u', 'a', 'l', 'i', 'f', 'i', 'e', 'd', 'U', 'r', 'l', '\032', '\237', '\003', '\n', '\017',
-'H', 'e', 'a', 'd', 'e', 'r', 'K', 'e', 'y', 'F', 'o', 'r', 'm', 'a', 't', '\022', 'x', '\n', '\021', 'p', 'r', 'o', 'p', 'e', 'r',
-'_', 'c', 'a', 's', 'e', '_', 'w', 'o', 'r', 'd', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', 'J', '.', 'e', 'n', 'v', 'o', 'y',
-'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 't', 't', 'p', '1', 'P', 'r', 'o', 't',
-'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'K', 'e', 'y', 'F', 'o', 'r', 'm',
-'a', 't', '.', 'P', 'r', 'o', 'p', 'e', 'r', 'C', 'a', 's', 'e', 'W', 'o', 'r', 'd', 's', 'H', '\000', 'R', '\017', 'p', 'r', 'o',
-'p', 'e', 'r', 'C', 'a', 's', 'e', 'W', 'o', 'r', 'd', 's', '\022', '[', '\n', '\022', 's', 't', 'a', 't', 'e', 'f', 'u', 'l', '_',
-'f', 'o', 'r', 'm', 'a', 't', 't', 'e', 'r', '\030', '\010', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c',
-'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's',
-'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', '\021', 's', 't', 'a', 't', 'e', 'f', 'u', 'l', 'F', 'o', 'r', 'm',
-'a', 't', 't', 'e', 'r', '\032', '`', '\n', '\017', 'P', 'r', 'o', 'p', 'e', 'r', 'C', 'a', 's', 'e', 'W', 'o', 'r', 'd', 's', ':',
-'M', '\232', '\305', '\210', '\036', 'H', '\n', 'F', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e',
-'.', 'H', 't', 't', 'p', '1', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'H', 'e', 'a',
-'d', 'e', 'r', 'K', 'e', 'y', 'F', 'o', 'r', 'm', 'a', 't', '.', 'P', 'r', 'o', 'p', 'e', 'r', 'C', 'a', 's', 'e', 'W', 'o',
-'r', 'd', 's', ':', '=', '\232', '\305', '\210', '\036', '8', '\n', '6', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.',
-'c', 'o', 'r', 'e', '.', 'H', 't', 't', 'p', '1', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's',
-'.', 'H', 'e', 'a', 'd', 'e', 'r', 'K', 'e', 'y', 'F', 'o', 'r', 'm', 'a', 't', 'B', '\024', '\n', '\r', 'h', 'e', 'a', 'd', 'e',
-'r', '_', 'f', 'o', 'r', 'm', 'a', 't', '\022', '\003', '\370', 'B', '\001', ':', '-', '\232', '\305', '\210', '\036', '(', '\n', '&', 'e', 'n', 'v',
-'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 't', 't', 'p', '1', 'P', 'r', 'o', 't', 'o',
-'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\"', '\301', '\002', '\n', '\021', 'K', 'e', 'e', 'p', 'a', 'l', 'i', 'v', 'e', 'S',
-'e', 't', 't', 'i', 'n', 'g', 's', '\022', 'C', '\n', '\010', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '\001', ' ', '\001', '(', '\013',
-'2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i',
-'o', 'n', 'B', '\014', '\372', 'B', '\t', '\252', '\001', '\006', '2', '\004', '\020', '\300', '\204', '=', 'R', '\010', 'i', 'n', 't', 'e', 'r', 'v', 'a',
-'l', '\022', 'C', '\n', '\007', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\002', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g',
-'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\016', '\372', 'B', '\013',
-'\252', '\001', '\010', '\010', '\001', '2', '\004', '\020', '\300', '\204', '=', 'R', '\007', 't', 'i', 'm', 'e', 'o', 'u', 't', '\022', '?', '\n', '\017', 'i',
-'n', 't', 'e', 'r', 'v', 'a', 'l', '_', 'j', 'i', 't', 't', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\013', '2', '\026', '.', 'e', 'n',
-'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\016', 'i', 'n', 't', 'e',
-'r', 'v', 'a', 'l', 'J', 'i', 't', 't', 'e', 'r', '\022', 'a', '\n', '\030', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_',
-'i', 'd', 'l', 'e', '_', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '\004', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o',
-'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\014', '\372', 'B',
-'\t', '\252', '\001', '\006', '2', '\004', '\020', '\300', '\204', '=', 'R', '\026', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'I', 'd', 'l',
-'e', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\"', '\201', '\016', '\n', '\024', 'H', 't', 't', 'p', '2', 'P', 'r', 'o', 't', 'o', 'c',
-'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'F', '\n', '\020', 'h', 'p', 'a', 'c', 'k', '_', 't', 'a', 'b', 'l', 'e', '_',
-'s', 'i', 'z', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o',
-'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '\016', 'h', 'p', 'a', 'c', 'k', 'T', 'a', 'b',
-'l', 'e', 'S', 'i', 'z', 'e', '\022', 'a', '\n', '\026', 'm', 'a', 'x', '_', 'c', 'o', 'n', 'c', 'u', 'r', 'r', 'e', 'n', 't', '_',
-'s', 't', 'r', 'e', 'a', 'm', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r',
-'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\r', '\372', 'B', '\n', '*', '\010',
-'\030', '\377', '\377', '\377', '\377', '\007', '(', '\001', 'R', '\024', 'm', 'a', 'x', 'C', 'o', 'n', 'c', 'u', 'r', 'r', 'e', 'n', 't', 'S', 't',
-'r', 'e', 'a', 'm', 's', '\022', 'j', '\n', '\032', 'i', 'n', 'i', 't', 'i', 'a', 'l', '_', 's', 't', 'r', 'e', 'a', 'm', '_', 'w',
-'i', 'n', 'd', 'o', 'w', '_', 's', 'i', 'z', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e',
-'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\017', '\372', 'B',
-'\014', '*', '\n', '\030', '\377', '\377', '\377', '\377', '\007', '(', '\377', '\377', '\003', 'R', '\027', 'i', 'n', 'i', 't', 'i', 'a', 'l', 'S', 't', 'r',
-'e', 'a', 'm', 'W', 'i', 'n', 'd', 'o', 'w', 'S', 'i', 'z', 'e', '\022', 'r', '\n', '\036', 'i', 'n', 'i', 't', 'i', 'a', 'l', '_',
-'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'w', 'i', 'n', 'd', 'o', 'w', '_', 's', 'i', 'z', 'e', '\030', '\004', ' ',
-'\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n',
-'t', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\017', '\372', 'B', '\014', '*', '\n', '\030', '\377', '\377', '\377', '\377', '\007', '(', '\377', '\377', '\003',
-'R', '\033', 'i', 'n', 'i', 't', 'i', 'a', 'l', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'W', 'i', 'n', 'd', 'o', 'w',
-'S', 'i', 'z', 'e', '\022', '#', '\n', '\r', 'a', 'l', 'l', 'o', 'w', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', '\030', '\005', ' ', '\001',
-'(', '\010', 'R', '\014', 'a', 'l', 'l', 'o', 'w', 'C', 'o', 'n', 'n', 'e', 'c', 't', '\022', '%', '\n', '\016', 'a', 'l', 'l', 'o', 'w',
-'_', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\r', 'a', 'l', 'l', 'o', 'w', 'M', 'e', 't',
-'a', 'd', 'a', 't', 'a', '\022', 'U', '\n', '\023', 'm', 'a', 'x', '_', 'o', 'u', 't', 'b', 'o', 'u', 'n', 'd', '_', 'f', 'r', 'a',
-'m', 'e', 's', '\030', '\007', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b',
-'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\001', 'R', '\021',
-'m', 'a', 'x', 'O', 'u', 't', 'b', 'o', 'u', 'n', 'd', 'F', 'r', 'a', 'm', 'e', 's', '\022', 'd', '\n', '\033', 'm', 'a', 'x', '_',
-'o', 'u', 't', 'b', 'o', 'u', 'n', 'd', '_', 'c', 'o', 'n', 't', 'r', 'o', 'l', '_', 'f', 'r', 'a', 'm', 'e', 's', '\030', '\010',
-' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I',
-'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\001', 'R', '\030', 'm', 'a', 'x', 'O', 'u',
-'t', 'b', 'o', 'u', 'n', 'd', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'F', 'r', 'a', 'm', 'e', 's', '\022', '\204', '\001', '\n', '1', 'm',
-'a', 'x', '_', 'c', 'o', 'n', 's', 'e', 'c', 'u', 't', 'i', 'v', 'e', '_', 'i', 'n', 'b', 'o', 'u', 'n', 'd', '_', 'f', 'r',
-'a', 'm', 'e', 's', '_', 'w', 'i', 't', 'h', '_', 'e', 'm', 'p', 't', 'y', '_', 'p', 'a', 'y', 'l', 'o', 'a', 'd', '\030', '\t',
-' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I',
-'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '+', 'm', 'a', 'x', 'C', 'o', 'n', 's', 'e', 'c', 'u', 't', 'i', 'v', 'e',
-'I', 'n', 'b', 'o', 'u', 'n', 'd', 'F', 'r', 'a', 'm', 'e', 's', 'W', 'i', 't', 'h', 'E', 'm', 'p', 't', 'y', 'P', 'a', 'y',
-'l', 'o', 'a', 'd', '\022', 'o', '\n', '&', 'm', 'a', 'x', '_', 'i', 'n', 'b', 'o', 'u', 'n', 'd', '_', 'p', 'r', 'i', 'o', 'r',
-'i', 't', 'y', '_', 'f', 'r', 'a', 'm', 'e', 's', '_', 'p', 'e', 'r', '_', 's', 't', 'r', 'e', 'a', 'm', '\030', '\n', ' ', '\001',
-'(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't',
-'3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '!', 'm', 'a', 'x', 'I', 'n', 'b', 'o', 'u', 'n', 'd', 'P', 'r', 'i', 'o', 'r', 'i',
-'t', 'y', 'F', 'r', 'a', 'm', 'e', 's', 'P', 'e', 'r', 'S', 't', 'r', 'e', 'a', 'm', '\022', '\221', '\001', '\n', '4', 'm', 'a', 'x',
-'_', 'i', 'n', 'b', 'o', 'u', 'n', 'd', '_', 'w', 'i', 'n', 'd', 'o', 'w', '_', 'u', 'p', 'd', 'a', 't', 'e', '_', 'f', 'r',
-'a', 'm', 'e', 's', '_', 'p', 'e', 'r', '_', 'd', 'a', 't', 'a', '_', 'f', 'r', 'a', 'm', 'e', '_', 's', 'e', 'n', 't', '\030',
-'\013', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U',
-'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\001', 'R', ',', 'm', 'a', 'x', 'I',
-'n', 'b', 'o', 'u', 'n', 'd', 'W', 'i', 'n', 'd', 'o', 'w', 'U', 'p', 'd', 'a', 't', 'e', 'F', 'r', 'a', 'm', 'e', 's', 'P',
-'e', 'r', 'D', 'a', 't', 'a', 'F', 'r', 'a', 'm', 'e', 'S', 'e', 'n', 't', '\022', '^', '\n', '&', 's', 't', 'r', 'e', 'a', 'm',
-'_', 'e', 'r', 'r', 'o', 'r', '_', 'o', 'n', '_', 'i', 'n', 'v', 'a', 'l', 'i', 'd', '_', 'h', 't', 't', 'p', '_', 'm', 'e',
-'s', 's', 'a', 'g', 'i', 'n', 'g', '\030', '\014', ' ', '\001', '(', '\010', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.',
-'0', 'R', '!', 's', 't', 'r', 'e', 'a', 'm', 'E', 'r', 'r', 'o', 'r', 'O', 'n', 'I', 'n', 'v', 'a', 'l', 'i', 'd', 'H', 't',
-'t', 'p', 'M', 'e', 's', 's', 'a', 'g', 'i', 'n', 'g', '\022', 'z', '\n', '-', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '_', 's',
-'t', 'r', 'e', 'a', 'm', '_', 'e', 'r', 'r', 'o', 'r', '_', 'o', 'n', '_', 'i', 'n', 'v', 'a', 'l', 'i', 'd', '_', 'h', 't',
-'t', 'p', '_', 'm', 'e', 's', 's', 'a', 'g', 'e', '\030', '\016', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e',
-'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', '\'', 'o', 'v', 'e', 'r',
-'r', 'i', 'd', 'e', 'S', 't', 'r', 'e', 'a', 'm', 'E', 'r', 'r', 'o', 'r', 'O', 'n', 'I', 'n', 'v', 'a', 'l', 'i', 'd', 'H',
-'t', 't', 'p', 'M', 'e', 's', 's', 'a', 'g', 'e', '\022', 'z', '\n', '\032', 'c', 'u', 's', 't', 'o', 'm', '_', 's', 'e', 't', 't',
-'i', 'n', 'g', 's', '_', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 's', '\030', '\r', ' ', '\003', '(', '\013', '2', '<', '.', 'e',
-'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 't', 't', 'p', '2',
-'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'S', 'e', 't', 't', 'i', 'n', 'g', 's', 'P',
-'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 'R', '\030', 'c', 'u', 's', 't', 'o', 'm', 'S', 'e', 't', 't', 'i', 'n', 'g', 's', 'P',
-'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 's', '\022', 'Z', '\n', '\024', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'k',
-'e', 'e', 'p', 'a', 'l', 'i', 'v', 'e', '\030', '\017', ' ', '\001', '(', '\013', '2', '\'', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o',
-'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'K', 'e', 'e', 'p', 'a', 'l', 'i', 'v', 'e', 'S', 'e', 't',
-'t', 'i', 'n', 'g', 's', 'R', '\023', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'K', 'e', 'e', 'p', 'a', 'l', 'i', 'v',
-'e', '\032', '\345', '\001', '\n', '\021', 'S', 'e', 't', 't', 'i', 'n', 'g', 's', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', '\022', 'Q',
-'\n', '\n', 'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g',
-'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\023',
-'\372', 'B', '\010', '*', '\006', '\030', '\377', '\377', '\003', '(', '\000', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\n', 'i', 'd', 'e', 'n',
-'t', 'i', 'f', 'i', 'e', 'r', '\022', '<', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'g',
+'e', 'n', 'd', 'F', 'u', 'l', 'l', 'y', 'Q', 'u', 'a', 'l', 'i', 'f', 'i', 'e', 'd', 'U', 'r', 'l', '\022', 'N', '\n', '\020', 'u',
+'s', 'e', '_', 'b', 'a', 'l', 's', 'a', '_', 'p', 'a', 'r', 's', 'e', 'r', '\030', '\t', ' ', '\001', '(', '\013', '2', '\032', '.', 'g',
+'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'B',
+'\010', '\322', '\306', '\244', '\341', '\006', '\002', '\010', '\001', 'R', '\016', 'u', 's', 'e', 'B', 'a', 'l', 's', 'a', 'P', 'a', 'r', 's', 'e', 'r',
+'\032', '\237', '\003', '\n', '\017', 'H', 'e', 'a', 'd', 'e', 'r', 'K', 'e', 'y', 'F', 'o', 'r', 'm', 'a', 't', '\022', 'x', '\n', '\021', 'p',
+'r', 'o', 'p', 'e', 'r', '_', 'c', 'a', 's', 'e', '_', 'w', 'o', 'r', 'd', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', 'J', '.',
+'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 't', 't', 'p',
+'1', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'K', 'e',
+'y', 'F', 'o', 'r', 'm', 'a', 't', '.', 'P', 'r', 'o', 'p', 'e', 'r', 'C', 'a', 's', 'e', 'W', 'o', 'r', 'd', 's', 'H', '\000',
+'R', '\017', 'p', 'r', 'o', 'p', 'e', 'r', 'C', 'a', 's', 'e', 'W', 'o', 'r', 'd', 's', '\022', '[', '\n', '\022', 's', 't', 'a', 't',
+'e', 'f', 'u', 'l', '_', 'f', 'o', 'r', 'm', 'a', 't', 't', 'e', 'r', '\030', '\010', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n',
+'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E',
+'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', '\021', 's', 't', 'a', 't', 'e', 'f', 'u',
+'l', 'F', 'o', 'r', 'm', 'a', 't', 't', 'e', 'r', '\032', '`', '\n', '\017', 'P', 'r', 'o', 'p', 'e', 'r', 'C', 'a', 's', 'e', 'W',
+'o', 'r', 'd', 's', ':', 'M', '\232', '\305', '\210', '\036', 'H', '\n', 'F', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2',
+'.', 'c', 'o', 'r', 'e', '.', 'H', 't', 't', 'p', '1', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n',
+'s', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'K', 'e', 'y', 'F', 'o', 'r', 'm', 'a', 't', '.', 'P', 'r', 'o', 'p', 'e', 'r', 'C',
+'a', 's', 'e', 'W', 'o', 'r', 'd', 's', ':', '=', '\232', '\305', '\210', '\036', '8', '\n', '6', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p',
+'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 't', 't', 'p', '1', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p',
+'t', 'i', 'o', 'n', 's', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'K', 'e', 'y', 'F', 'o', 'r', 'm', 'a', 't', 'B', '\024', '\n', '\r',
+'h', 'e', 'a', 'd', 'e', 'r', '_', 'f', 'o', 'r', 'm', 'a', 't', '\022', '\003', '\370', 'B', '\001', ':', '-', '\232', '\305', '\210', '\036', '(',
+'\n', '&', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 't', 't', 'p', '1',
+'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\"', '\301', '\002', '\n', '\021', 'K', 'e', 'e', 'p', 'a',
+'l', 'i', 'v', 'e', 'S', 'e', 't', 't', 'i', 'n', 'g', 's', '\022', 'C', '\n', '\010', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\030',
+'\001', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D',
+'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\014', '\372', 'B', '\t', '\252', '\001', '\006', '2', '\004', '\020', '\300', '\204', '=', 'R', '\010', 'i', 'n',
+'t', 'e', 'r', 'v', 'a', 'l', '\022', 'C', '\n', '\007', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\002', ' ', '\001', '(', '\013', '2', '\031',
+'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n',
+'B', '\016', '\372', 'B', '\013', '\252', '\001', '\010', '\010', '\001', '2', '\004', '\020', '\300', '\204', '=', 'R', '\007', 't', 'i', 'm', 'e', 'o', 'u', 't',
+'\022', '?', '\n', '\017', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '_', 'j', 'i', 't', 't', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\013',
+'2', '\026', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R',
+'\016', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', 'J', 'i', 't', 't', 'e', 'r', '\022', 'a', '\n', '\030', 'c', 'o', 'n', 'n', 'e', 'c',
+'t', 'i', 'o', 'n', '_', 'i', 'd', 'l', 'e', '_', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '\004', ' ', '\001', '(', '\013', '2',
+'\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o',
+'n', 'B', '\014', '\372', 'B', '\t', '\252', '\001', '\006', '2', '\004', '\020', '\300', '\204', '=', 'R', '\026', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i',
+'o', 'n', 'I', 'd', 'l', 'e', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\"', '\201', '\016', '\n', '\024', 'H', 't', 't', 'p', '2', 'P',
+'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'F', '\n', '\020', 'h', 'p', 'a', 'c', 'k', '_', 't',
+'a', 'b', 'l', 'e', '_', 's', 'i', 'z', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.',
+'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '\016', 'h', 'p', 'a',
+'c', 'k', 'T', 'a', 'b', 'l', 'e', 'S', 'i', 'z', 'e', '\022', 'a', '\n', '\026', 'm', 'a', 'x', '_', 'c', 'o', 'n', 'c', 'u', 'r',
+'r', 'e', 'n', 't', '_', 's', 't', 'r', 'e', 'a', 'm', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g',
+'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\r',
+'\372', 'B', '\n', '*', '\010', '\030', '\377', '\377', '\377', '\377', '\007', '(', '\001', 'R', '\024', 'm', 'a', 'x', 'C', 'o', 'n', 'c', 'u', 'r', 'r',
+'e', 'n', 't', 'S', 't', 'r', 'e', 'a', 'm', 's', '\022', 'j', '\n', '\032', 'i', 'n', 'i', 't', 'i', 'a', 'l', '_', 's', 't', 'r',
+'e', 'a', 'm', '_', 'w', 'i', 'n', 'd', 'o', 'w', '_', 's', 'i', 'z', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '\034', '.', 'g',
'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u',
-'e', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '?', '\232', '\305', '\210', '\036', ':',
-'\n', '8', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 't', 't', 'p', '2',
-'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'S', 'e', 't', 't', 'i', 'n', 'g', 's', 'P',
-'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', ':', '-', '\232', '\305', '\210', '\036', '(', '\n', '&', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p',
-'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 't', 't', 'p', '2', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p',
-'t', 'i', 'o', 'n', 's', '\"', '\245', '\001', '\n', '\023', 'G', 'r', 'p', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't',
-'i', 'o', 'n', 's', '\022', '`', '\n', '\026', 'h', 't', 't', 'p', '2', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '_', 'o', 'p',
-'t', 'i', 'o', 'n', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
-'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 't', 't', 'p', '2', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p',
-'t', 'i', 'o', 'n', 's', 'R', '\024', 'h', 't', 't', 'p', '2', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o',
-'n', 's', ':', ',', '\232', '\305', '\210', '\036', '\'', '\n', '%', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c',
-'o', 'r', 'e', '.', 'G', 'r', 'p', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\"', '\261',
-'\002', '\n', '\024', 'H', 't', 't', 'p', '3', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', ']',
-'\n', '\025', 'q', 'u', 'i', 'c', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '_', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\001',
-' ', '\001', '(', '\013', '2', ')', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.',
-'v', '3', '.', 'Q', 'u', 'i', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\023', 'q',
-'u', 'i', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'z', '\n', '-', 'o', 'v', 'e',
-'r', 'r', 'i', 'd', 'e', '_', 's', 't', 'r', 'e', 'a', 'm', '_', 'e', 'r', 'r', 'o', 'r', '_', 'o', 'n', '_', 'i', 'n', 'v',
-'a', 'l', 'i', 'd', '_', 'h', 't', 't', 'p', '_', 'm', 'e', 's', 's', 'a', 'g', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032',
-'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u',
-'e', 'R', '\'', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', 'S', 't', 'r', 'e', 'a', 'm', 'E', 'r', 'r', 'o', 'r', 'O', 'n', 'I',
-'n', 'v', 'a', 'l', 'i', 'd', 'H', 't', 't', 'p', 'M', 'e', 's', 's', 'a', 'g', 'e', '\022', '>', '\n', '\026', 'a', 'l', 'l', 'o',
-'w', '_', 'e', 'x', 't', 'e', 'n', 'd', 'e', 'd', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', '\030', '\005', ' ', '\001', '(', '\010', 'B',
-'\010', '\322', '\306', '\244', '\341', '\006', '\002', '\010', '\001', 'R', '\024', 'a', 'l', 'l', 'o', 'w', 'E', 'x', 't', 'e', 'n', 'd', 'e', 'd', 'C',
-'o', 'n', 'n', 'e', 'c', 't', '\"', 't', '\n', '\032', 'S', 'c', 'h', 'e', 'm', 'e', 'H', 'e', 'a', 'd', 'e', 'r', 'T', 'r', 'a',
-'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\022', 'D', '\n', '\023', 's', 'c', 'h', 'e', 'm', 'e', '_', 't', 'o', '_',
-'o', 'v', 'e', 'r', 'w', 'r', 'i', 't', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\022', '\372', 'B', '\017', 'r', '\r', 'R', '\004', 'h',
-'t', 't', 'p', 'R', '\005', 'h', 't', 't', 'p', 's', 'H', '\000', 'R', '\021', 's', 'c', 'h', 'e', 'm', 'e', 'T', 'o', 'O', 'v', 'e',
-'r', 'w', 'r', 'i', 't', 'e', 'B', '\020', '\n', '\016', 't', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', 'B',
-'\201', '\001', '\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c',
-'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\r', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'P', 'r',
-'o', 't', 'o', 'P', '\001', 'Z', 'B', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r',
-'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o',
-'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', ';', 'c', 'o', 'r', 'e', 'v', '3', '\272', '\200',
-'\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
+'e', 'B', '\017', '\372', 'B', '\014', '*', '\n', '\030', '\377', '\377', '\377', '\377', '\007', '(', '\377', '\377', '\003', 'R', '\027', 'i', 'n', 'i', 't', 'i',
+'a', 'l', 'S', 't', 'r', 'e', 'a', 'm', 'W', 'i', 'n', 'd', 'o', 'w', 'S', 'i', 'z', 'e', '\022', 'r', '\n', '\036', 'i', 'n', 'i',
+'t', 'i', 'a', 'l', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'w', 'i', 'n', 'd', 'o', 'w', '_', 's', 'i',
+'z', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u',
+'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\017', '\372', 'B', '\014', '*', '\n', '\030', '\377', '\377', '\377', '\377',
+'\007', '(', '\377', '\377', '\003', 'R', '\033', 'i', 'n', 'i', 't', 'i', 'a', 'l', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'W',
+'i', 'n', 'd', 'o', 'w', 'S', 'i', 'z', 'e', '\022', '#', '\n', '\r', 'a', 'l', 'l', 'o', 'w', '_', 'c', 'o', 'n', 'n', 'e', 'c',
+'t', '\030', '\005', ' ', '\001', '(', '\010', 'R', '\014', 'a', 'l', 'l', 'o', 'w', 'C', 'o', 'n', 'n', 'e', 'c', 't', '\022', '%', '\n', '\016',
+'a', 'l', 'l', 'o', 'w', '_', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\r', 'a', 'l', 'l',
+'o', 'w', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', 'U', '\n', '\023', 'm', 'a', 'x', '_', 'o', 'u', 't', 'b', 'o', 'u', 'n',
+'d', '_', 'f', 'r', 'a', 'm', 'e', 's', '\030', '\007', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p',
+'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*',
+'\002', '(', '\001', 'R', '\021', 'm', 'a', 'x', 'O', 'u', 't', 'b', 'o', 'u', 'n', 'd', 'F', 'r', 'a', 'm', 'e', 's', '\022', 'd', '\n',
+'\033', 'm', 'a', 'x', '_', 'o', 'u', 't', 'b', 'o', 'u', 'n', 'd', '_', 'c', 'o', 'n', 't', 'r', 'o', 'l', '_', 'f', 'r', 'a',
+'m', 'e', 's', '\030', '\010', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b',
+'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\001', 'R', '\030',
+'m', 'a', 'x', 'O', 'u', 't', 'b', 'o', 'u', 'n', 'd', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'F', 'r', 'a', 'm', 'e', 's', '\022',
+'\204', '\001', '\n', '1', 'm', 'a', 'x', '_', 'c', 'o', 'n', 's', 'e', 'c', 'u', 't', 'i', 'v', 'e', '_', 'i', 'n', 'b', 'o', 'u',
+'n', 'd', '_', 'f', 'r', 'a', 'm', 'e', 's', '_', 'w', 'i', 't', 'h', '_', 'e', 'm', 'p', 't', 'y', '_', 'p', 'a', 'y', 'l',
+'o', 'a', 'd', '\030', '\t', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b',
+'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '+', 'm', 'a', 'x', 'C', 'o', 'n', 's', 'e', 'c',
+'u', 't', 'i', 'v', 'e', 'I', 'n', 'b', 'o', 'u', 'n', 'd', 'F', 'r', 'a', 'm', 'e', 's', 'W', 'i', 't', 'h', 'E', 'm', 'p',
+'t', 'y', 'P', 'a', 'y', 'l', 'o', 'a', 'd', '\022', 'o', '\n', '&', 'm', 'a', 'x', '_', 'i', 'n', 'b', 'o', 'u', 'n', 'd', '_',
+'p', 'r', 'i', 'o', 'r', 'i', 't', 'y', '_', 'f', 'r', 'a', 'm', 'e', 's', '_', 'p', 'e', 'r', '_', 's', 't', 'r', 'e', 'a',
+'m', '\030', '\n', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f',
+'.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '!', 'm', 'a', 'x', 'I', 'n', 'b', 'o', 'u', 'n', 'd', 'P',
+'r', 'i', 'o', 'r', 'i', 't', 'y', 'F', 'r', 'a', 'm', 'e', 's', 'P', 'e', 'r', 'S', 't', 'r', 'e', 'a', 'm', '\022', '\221', '\001',
+'\n', '4', 'm', 'a', 'x', '_', 'i', 'n', 'b', 'o', 'u', 'n', 'd', '_', 'w', 'i', 'n', 'd', 'o', 'w', '_', 'u', 'p', 'd', 'a',
+'t', 'e', '_', 'f', 'r', 'a', 'm', 'e', 's', '_', 'p', 'e', 'r', '_', 'd', 'a', 't', 'a', '_', 'f', 'r', 'a', 'm', 'e', '_',
+'s', 'e', 'n', 't', '\030', '\013', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o',
+'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\001', 'R',
+',', 'm', 'a', 'x', 'I', 'n', 'b', 'o', 'u', 'n', 'd', 'W', 'i', 'n', 'd', 'o', 'w', 'U', 'p', 'd', 'a', 't', 'e', 'F', 'r',
+'a', 'm', 'e', 's', 'P', 'e', 'r', 'D', 'a', 't', 'a', 'F', 'r', 'a', 'm', 'e', 'S', 'e', 'n', 't', '\022', '^', '\n', '&', 's',
+'t', 'r', 'e', 'a', 'm', '_', 'e', 'r', 'r', 'o', 'r', '_', 'o', 'n', '_', 'i', 'n', 'v', 'a', 'l', 'i', 'd', '_', 'h', 't',
+'t', 'p', '_', 'm', 'e', 's', 's', 'a', 'g', 'i', 'n', 'g', '\030', '\014', ' ', '\001', '(', '\010', 'B', '\013', '\030', '\001', '\222', '\307', '\206',
+'\330', '\004', '\003', '3', '.', '0', 'R', '!', 's', 't', 'r', 'e', 'a', 'm', 'E', 'r', 'r', 'o', 'r', 'O', 'n', 'I', 'n', 'v', 'a',
+'l', 'i', 'd', 'H', 't', 't', 'p', 'M', 'e', 's', 's', 'a', 'g', 'i', 'n', 'g', '\022', 'z', '\n', '-', 'o', 'v', 'e', 'r', 'r',
+'i', 'd', 'e', '_', 's', 't', 'r', 'e', 'a', 'm', '_', 'e', 'r', 'r', 'o', 'r', '_', 'o', 'n', '_', 'i', 'n', 'v', 'a', 'l',
+'i', 'd', '_', 'h', 't', 't', 'p', '_', 'm', 'e', 's', 's', 'a', 'g', 'e', '\030', '\016', ' ', '\001', '(', '\013', '2', '\032', '.', 'g',
+'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R',
+'\'', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', 'S', 't', 'r', 'e', 'a', 'm', 'E', 'r', 'r', 'o', 'r', 'O', 'n', 'I', 'n', 'v',
+'a', 'l', 'i', 'd', 'H', 't', 't', 'p', 'M', 'e', 's', 's', 'a', 'g', 'e', '\022', 'z', '\n', '\032', 'c', 'u', 's', 't', 'o', 'm',
+'_', 's', 'e', 't', 't', 'i', 'n', 'g', 's', '_', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 's', '\030', '\r', ' ', '\003', '(',
+'\013', '2', '<', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.',
+'H', 't', 't', 'p', '2', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'S', 'e', 't', 't',
+'i', 'n', 'g', 's', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 'R', '\030', 'c', 'u', 's', 't', 'o', 'm', 'S', 'e', 't', 't',
+'i', 'n', 'g', 's', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 's', '\022', 'Z', '\n', '\024', 'c', 'o', 'n', 'n', 'e', 'c', 't',
+'i', 'o', 'n', '_', 'k', 'e', 'e', 'p', 'a', 'l', 'i', 'v', 'e', '\030', '\017', ' ', '\001', '(', '\013', '2', '\'', '.', 'e', 'n', 'v',
+'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'K', 'e', 'e', 'p', 'a', 'l', 'i',
+'v', 'e', 'S', 'e', 't', 't', 'i', 'n', 'g', 's', 'R', '\023', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'K', 'e', 'e',
+'p', 'a', 'l', 'i', 'v', 'e', '\032', '\345', '\001', '\n', '\021', 'S', 'e', 't', 't', 'i', 'n', 'g', 's', 'P', 'a', 'r', 'a', 'm', 'e',
+'t', 'e', 'r', '\022', 'Q', '\n', '\n', 'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034',
+'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a',
+'l', 'u', 'e', 'B', '\023', '\372', 'B', '\010', '*', '\006', '\030', '\377', '\377', '\003', '(', '\000', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R',
+'\n', 'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', '\022', '<', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(',
+'\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3',
+'2', 'V', 'a', 'l', 'u', 'e', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '?',
+'\232', '\305', '\210', '\036', ':', '\n', '8', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.',
+'H', 't', 't', 'p', '2', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'S', 'e', 't', 't',
+'i', 'n', 'g', 's', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', ':', '-', '\232', '\305', '\210', '\036', '(', '\n', '&', 'e', 'n', 'v',
+'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'H', 't', 't', 'p', '2', 'P', 'r', 'o', 't', 'o',
+'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\"', '\245', '\001', '\n', '\023', 'G', 'r', 'p', 'c', 'P', 'r', 'o', 't', 'o', 'c',
+'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '`', '\n', '\026', 'h', 't', 't', 'p', '2', '_', 'p', 'r', 'o', 't', 'o', 'c',
+'o', 'l', '_', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.',
+'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 't', 't', 'p', '2', 'P', 'r', 'o', 't', 'o',
+'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\024', 'h', 't', 't', 'p', '2', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l',
+'O', 'p', 't', 'i', 'o', 'n', 's', ':', ',', '\232', '\305', '\210', '\036', '\'', '\n', '%', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i',
+'.', 'v', '2', '.', 'c', 'o', 'r', 'e', '.', 'G', 'r', 'p', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i',
+'o', 'n', 's', '\"', '\261', '\002', '\n', '\024', 'H', 't', 't', 'p', '3', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i',
+'o', 'n', 's', '\022', ']', '\n', '\025', 'q', 'u', 'i', 'c', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '_', 'o', 'p', 't', 'i',
+'o', 'n', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', ')', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.',
+'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'Q', 'u', 'i', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o',
+'n', 's', 'R', '\023', 'q', 'u', 'i', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'z',
+'\n', '-', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '_', 's', 't', 'r', 'e', 'a', 'm', '_', 'e', 'r', 'r', 'o', 'r', '_', 'o',
+'n', '_', 'i', 'n', 'v', 'a', 'l', 'i', 'd', '_', 'h', 't', 't', 'p', '_', 'm', 'e', 's', 's', 'a', 'g', 'e', '\030', '\002', ' ',
+'\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o',
+'l', 'V', 'a', 'l', 'u', 'e', 'R', '\'', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', 'S', 't', 'r', 'e', 'a', 'm', 'E', 'r', 'r',
+'o', 'r', 'O', 'n', 'I', 'n', 'v', 'a', 'l', 'i', 'd', 'H', 't', 't', 'p', 'M', 'e', 's', 's', 'a', 'g', 'e', '\022', '>', '\n',
+'\026', 'a', 'l', 'l', 'o', 'w', '_', 'e', 'x', 't', 'e', 'n', 'd', 'e', 'd', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', '\030', '\005',
+' ', '\001', '(', '\010', 'B', '\010', '\322', '\306', '\244', '\341', '\006', '\002', '\010', '\001', 'R', '\024', 'a', 'l', 'l', 'o', 'w', 'E', 'x', 't', 'e',
+'n', 'd', 'e', 'd', 'C', 'o', 'n', 'n', 'e', 'c', 't', '\"', 't', '\n', '\032', 'S', 'c', 'h', 'e', 'm', 'e', 'H', 'e', 'a', 'd',
+'e', 'r', 'T', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\022', 'D', '\n', '\023', 's', 'c', 'h', 'e', 'm',
+'e', '_', 't', 'o', '_', 'o', 'v', 'e', 'r', 'w', 'r', 'i', 't', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\022', '\372', 'B', '\017',
+'r', '\r', 'R', '\004', 'h', 't', 't', 'p', 'R', '\005', 'h', 't', 't', 'p', 's', 'H', '\000', 'R', '\021', 's', 'c', 'h', 'e', 'm', 'e',
+'T', 'o', 'O', 'v', 'e', 'r', 'w', 'r', 'i', 't', 'e', 'B', '\020', '\n', '\016', 't', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a',
+'t', 'i', 'o', 'n', 'B', '\201', '\001', '\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n',
+'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\r', 'P', 'r', 'o', 't', 'o',
+'c', 'o', 'l', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'B', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e', 'n',
+'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n', 'e',
+'/', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', ';', 'c', 'o', 'r',
+'e', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
};
static _upb_DefPool_Init *deps[10] = {
@@ -298,5 +301,5 @@ _upb_DefPool_Init envoy_config_core_v3_protocol_proto_upbdefinit = {
deps,
&envoy_config_core_v3_protocol_proto_upb_file_layout,
"envoy/config/core/v3/protocol.proto",
- UPB_STRINGVIEW_INIT(descriptor, 6489)
+ UPB_STRINGVIEW_INIT(descriptor, 6569)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/proxy_protocol.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/proxy_protocol.upbdefs.c
index 878bc54228..c6b552a197 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/proxy_protocol.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/proxy_protocol.upbdefs.c
@@ -11,25 +11,41 @@
#include "envoy/config/core/v3/proxy_protocol.upb.h"
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
-static const char descriptor[368] = {'\n', ')', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'p', 'r',
+extern _upb_DefPool_Init validate_validate_proto_upbdefinit;
+static const char descriptor[717] = {'\n', ')', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'p', 'r',
'o', 'x', 'y', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '.', 'p', 'r', 'o', 't', 'o', '\022', '\024', 'e', 'n', 'v', 'o', 'y',
'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n',
-'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\"', '}', '\n', '\023',
-'P', 'r', 'o', 'x', 'y', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'K', '\n', '\007', 'v', 'e',
-'r', 's', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\016', '2', '1', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
-'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'P', 'r', 'o', 'x', 'y', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'C', 'o',
-'n', 'f', 'i', 'g', '.', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'R', '\007', 'v', 'e', 'r', 's', 'i', 'o', 'n', '\"', '\031', '\n', '\007',
-'V', 'e', 'r', 's', 'i', 'o', 'n', '\022', '\006', '\n', '\002', 'V', '1', '\020', '\000', '\022', '\006', '\n', '\002', 'V', '2', '\020', '\001', 'B', '\206',
-'\001', '\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o',
-'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\022', 'P', 'r', 'o', 'x', 'y', 'P', 'r', 'o', 't', 'o', 'c',
-'o', 'l', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'B', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e', 'n', 'v',
-'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n', 'e', '/',
-'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', ';', 'c', 'o', 'r', 'e',
-'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
+'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a',
+'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\340', '\001', '\n',
+'\034', 'P', 'r', 'o', 'x', 'y', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'P', 'a', 's', 's', 'T', 'h', 'r', 'o', 'u', 'g', 'h',
+'T', 'L', 'V', 's', '\022', 'c', '\n', '\n', 'm', 'a', 't', 'c', 'h', '_', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2',
+'D', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'P', 'r',
+'o', 'x', 'y', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'P', 'a', 's', 's', 'T', 'h', 'r', 'o', 'u', 'g', 'h', 'T', 'L', 'V',
+'s', '.', 'P', 'a', 's', 's', 'T', 'L', 'V', 's', 'M', 'a', 't', 'c', 'h', 'T', 'y', 'p', 'e', 'R', '\t', 'm', 'a', 't', 'c',
+'h', 'T', 'y', 'p', 'e', '\022', '(', '\n', '\010', 't', 'l', 'v', '_', 't', 'y', 'p', 'e', '\030', '\002', ' ', '\003', '(', '\r', 'B', '\r',
+'\372', 'B', '\n', '\222', '\001', '\007', '\"', '\005', '*', '\003', '\020', '\200', '\002', 'R', '\007', 't', 'l', 'v', 'T', 'y', 'p', 'e', '\"', '1', '\n',
+'\021', 'P', 'a', 's', 's', 'T', 'L', 'V', 's', 'M', 'a', 't', 'c', 'h', 'T', 'y', 'p', 'e', '\022', '\017', '\n', '\013', 'I', 'N', 'C',
+'L', 'U', 'D', 'E', '_', 'A', 'L', 'L', '\020', '\000', '\022', '\013', '\n', '\007', 'I', 'N', 'C', 'L', 'U', 'D', 'E', '\020', '\001', '\"', '\335',
+'\001', '\n', '\023', 'P', 'r', 'o', 'x', 'y', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'K', '\n',
+'\007', 'v', 'e', 'r', 's', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\016', '2', '1', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o',
+'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'P', 'r', 'o', 'x', 'y', 'P', 'r', 'o', 't', 'o', 'c', 'o',
+'l', 'C', 'o', 'n', 'f', 'i', 'g', '.', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'R', '\007', 'v', 'e', 'r', 's', 'i', 'o', 'n', '\022',
+'^', '\n', '\021', 'p', 'a', 's', 's', '_', 't', 'h', 'r', 'o', 'u', 'g', 'h', '_', 't', 'l', 'v', 's', '\030', '\002', ' ', '\001', '(',
+'\013', '2', '2', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.',
+'P', 'r', 'o', 'x', 'y', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'P', 'a', 's', 's', 'T', 'h', 'r', 'o', 'u', 'g', 'h', 'T',
+'L', 'V', 's', 'R', '\017', 'p', 'a', 's', 's', 'T', 'h', 'r', 'o', 'u', 'g', 'h', 'T', 'l', 'v', 's', '\"', '\031', '\n', '\007', 'V',
+'e', 'r', 's', 'i', 'o', 'n', '\022', '\006', '\n', '\002', 'V', '1', '\020', '\000', '\022', '\006', '\n', '\002', 'V', '2', '\020', '\001', 'B', '\206', '\001',
+'\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n',
+'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', 'B', '\022', 'P', 'r', 'o', 'x', 'y', 'P', 'r', 'o', 't', 'o', 'c', 'o',
+'l', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'B', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e', 'n', 'v', 'o',
+'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n', 'e', '/', 'e',
+'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', ';', 'c', 'o', 'r', 'e', 'v',
+'3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
};
-static _upb_DefPool_Init *deps[2] = {
+static _upb_DefPool_Init *deps[3] = {
&udpa_annotations_status_proto_upbdefinit,
+ &validate_validate_proto_upbdefinit,
NULL
};
@@ -37,5 +53,5 @@ _upb_DefPool_Init envoy_config_core_v3_proxy_protocol_proto_upbdefinit = {
deps,
&envoy_config_core_v3_proxy_protocol_proto_upb_file_layout,
"envoy/config/core/v3/proxy_protocol.proto",
- UPB_STRINGVIEW_INIT(descriptor, 368)
+ UPB_STRINGVIEW_INIT(descriptor, 717)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/proxy_protocol.upbdefs.h b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/proxy_protocol.upbdefs.h
index cf152946ed..6eab65d603 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/proxy_protocol.upbdefs.h
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/core/v3/proxy_protocol.upbdefs.h
@@ -21,6 +21,11 @@ extern "C" {
extern _upb_DefPool_Init envoy_config_core_v3_proxy_protocol_proto_upbdefinit;
+UPB_INLINE const upb_MessageDef *envoy_config_core_v3_ProxyProtocolPassThroughTLVs_getmsgdef(upb_DefPool *s) {
+ _upb_DefPool_LoadDefInit(s, &envoy_config_core_v3_proxy_protocol_proto_upbdefinit);
+ return upb_DefPool_FindMessageByName(s, "envoy.config.core.v3.ProxyProtocolPassThroughTLVs");
+}
+
UPB_INLINE const upb_MessageDef *envoy_config_core_v3_ProxyProtocolConfig_getmsgdef(upb_DefPool *s) {
_upb_DefPool_LoadDefInit(s, &envoy_config_core_v3_proxy_protocol_proto_upbdefinit);
return upb_DefPool_FindMessageByName(s, "envoy.config.core.v3.ProxyProtocolConfig");
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c
index bdf37d4b21..6a566a4d04 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c
@@ -28,7 +28,7 @@ extern _upb_DefPool_Init udpa_annotations_security_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_versioning_proto_upbdefinit;
extern _upb_DefPool_Init validate_validate_proto_upbdefinit;
-static const char descriptor[4082] = {'\n', '\'', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '/', 'v',
+static const char descriptor[4152] = {'\n', '\'', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '/', 'v',
'3', '/', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', '\030', 'e', 'n', 'v', 'o', 'y', '.', 'c',
'o', 'n', 'f', 'i', 'g', '.', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '.', 'v', '3', '\032', ')', 'e', 'n', 'v', 'o', 'y', '/',
'c', 'o', 'n', 'f', 'i', 'g', '/', 'a', 'c', 'c', 'e', 's', 's', 'l', 'o', 'g', '/', 'v', '3', '/', 'a', 'c', 'c', 'e', 's',
@@ -185,13 +185,16 @@ static const char descriptor[4082] = {'\n', '\'', 'e', 'n', 'v', 'o', 'y', '/',
'\017', '\n', '\013', 'M', 'O', 'D', 'I', 'F', 'Y', '_', 'O', 'N', 'L', 'Y', '\020', '\001', ':', '\034', '\232', '\305', '\210', '\036', '\027', '\n', '\025',
'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'B', '\024', '\n', '\022',
'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'J', '\004', '\010', '\016', '\020', '\017', 'J',
-'\004', '\010', '\027', '\020', '\030', 'B', '\215', '\001', '\n', '&', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e',
-'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '.', 'v', '3', 'B', '\r',
-'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'J', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c',
-'o', 'm', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-',
-'p', 'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'l', 'i', 's', 't', 'e', 'n',
-'e', 'r', '/', 'v', '3', ';', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b',
-'\006', 'p', 'r', 'o', 't', 'o', '3',
+'\004', '\010', '\027', '\020', '\030', '\"', '\021', '\n', '\017', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '\"',
+'\033', '\n', '\031', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'M', 'a', 'n', 'a',
+'g', 'e', 'r', '\"', '\024', '\n', '\022', 'A', 'p', 'i', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'M', 'a', 'n', 'a', 'g', 'e', 'r',
+'B', '\215', '\001', '\n', '&', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.',
+'c', 'o', 'n', 'f', 'i', 'g', '.', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '.', 'v', '3', 'B', '\r', 'L', 'i', 's', 't', 'e',
+'n', 'e', 'r', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'J', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e', 'n',
+'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n', 'e',
+'/', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '/', 'v', '3',
+';', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't',
+'o', '3',
};
static _upb_DefPool_Init *deps[19] = {
@@ -220,5 +223,5 @@ _upb_DefPool_Init envoy_config_listener_v3_listener_proto_upbdefinit = {
deps,
&envoy_config_listener_v3_listener_proto_upb_file_layout,
"envoy/config/listener/v3/listener.proto",
- UPB_STRINGVIEW_INIT(descriptor, 4082)
+ UPB_STRINGVIEW_INIT(descriptor, 4152)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.h b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.h
index 4174b8e3ef..69aadd7284 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.h
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.h
@@ -56,6 +56,21 @@ UPB_INLINE const upb_MessageDef *envoy_config_listener_v3_Listener_InternalListe
return upb_DefPool_FindMessageByName(s, "envoy.config.listener.v3.Listener.InternalListenerConfig");
}
+UPB_INLINE const upb_MessageDef *envoy_config_listener_v3_ListenerManager_getmsgdef(upb_DefPool *s) {
+ _upb_DefPool_LoadDefInit(s, &envoy_config_listener_v3_listener_proto_upbdefinit);
+ return upb_DefPool_FindMessageByName(s, "envoy.config.listener.v3.ListenerManager");
+}
+
+UPB_INLINE const upb_MessageDef *envoy_config_listener_v3_ValidationListenerManager_getmsgdef(upb_DefPool *s) {
+ _upb_DefPool_LoadDefInit(s, &envoy_config_listener_v3_listener_proto_upbdefinit);
+ return upb_DefPool_FindMessageByName(s, "envoy.config.listener.v3.ValidationListenerManager");
+}
+
+UPB_INLINE const upb_MessageDef *envoy_config_listener_v3_ApiListenerManager_getmsgdef(upb_DefPool *s) {
+ _upb_DefPool_LoadDefInit(s, &envoy_config_listener_v3_listener_proto_upbdefinit);
+ return upb_DefPool_FindMessageByName(s, "envoy.config.listener.v3.ApiListenerManager");
+}
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/quic_config.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/quic_config.upbdefs.c
index a69aab674e..53d5cf085f 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/quic_config.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/quic_config.upbdefs.c
@@ -15,10 +15,11 @@ extern _upb_DefPool_Init envoy_config_core_v3_extension_proto_upbdefinit;
extern _upb_DefPool_Init envoy_config_core_v3_protocol_proto_upbdefinit;
extern _upb_DefPool_Init google_protobuf_duration_proto_upbdefinit;
extern _upb_DefPool_Init google_protobuf_wrappers_proto_upbdefinit;
+extern _upb_DefPool_Init xds_annotations_v3_status_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_versioning_proto_upbdefinit;
extern _upb_DefPool_Init validate_validate_proto_upbdefinit;
-static const char descriptor[1297] = {'\n', '*', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '/', 'v',
+static const char descriptor[1455] = {'\n', '*', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '/', 'v',
'3', '/', 'q', 'u', 'i', 'c', '_', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'p', 'r', 'o', 't', 'o', '\022', '\030', 'e', 'n', 'v', 'o',
'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '.', 'v', '3', '\032', '\037', 'e', 'n', 'v',
'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'b', 'a', 's', 'e', '.', 'p', 'r',
@@ -27,57 +28,65 @@ static const char descriptor[1297] = {'\n', '*', 'e', 'n', 'v', 'o', 'y', '/', '
'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '.', 'p', 'r',
'o', 't', 'o', '\032', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'u', 'r', 'a',
't', 'i', 'o', 'n', '.', 'p', 'r', 'o', 't', 'o', '\032', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b',
-'u', 'f', '/', 'w', 'r', 'a', 'p', 'p', 'e', 'r', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a',
-'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '!',
-'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i',
-'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a',
-'t', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\247', '\006', '\n', '\023', 'Q', 'u', 'i', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l',
-'O', 'p', 't', 'i', 'o', 'n', 's', '\022', ']', '\n', '\025', 'q', 'u', 'i', 'c', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', '_',
-'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', ')', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n',
-'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'Q', 'u', 'i', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O',
-'p', 't', 'i', 'o', 'n', 's', 'R', '\023', 'q', 'u', 'i', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o',
-'n', 's', '\022', '<', '\n', '\014', 'i', 'd', 'l', 'e', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\002', ' ', '\001', '(', '\013', '2',
-'\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o',
-'n', 'R', '\013', 'i', 'd', 'l', 'e', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'S', '\n', '\030', 'c', 'r', 'y', 'p', 't', 'o', '_',
-'h', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\003', ' ', '\001', '(', '\013', '2', '\031',
-'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n',
-'R', '\026', 'c', 'r', 'y', 'p', 't', 'o', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022',
-'B', '\n', '\007', 'e', 'n', 'a', 'b', 'l', 'e', 'd', '\030', '\004', ' ', '\001', '(', '\013', '2', '(', '.', 'e', 'n', 'v', 'o', 'y', '.',
-'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'F', 'e', 'a',
-'t', 'u', 'r', 'e', 'F', 'l', 'a', 'g', 'R', '\007', 'e', 'n', 'a', 'b', 'l', 'e', 'd', '\022', '}', '\n', ')', 'p', 'a', 'c', 'k',
-'e', 't', 's', '_', 't', 'o', '_', 'r', 'e', 'a', 'd', '_', 't', 'o', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n',
-'_', 'c', 'o', 'u', 'n', 't', '_', 'r', 'a', 't', 'i', 'o', '\030', '\005', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g',
-'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007',
-'\372', 'B', '\004', '*', '\002', '(', '\001', 'R', '#', 'p', 'a', 'c', 'k', 'e', 't', 's', 'T', 'o', 'R', 'e', 'a', 'd', 'T', 'o', 'C',
-'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'C', 'o', 'u', 'n', 't', 'R', 'a', 't', 'i', 'o', '\022', '\\', '\n', '\024', 'c', 'r',
-'y', 'p', 't', 'o', '_', 's', 't', 'r', 'e', 'a', 'm', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\006', ' ', '\001', '(', '\013', '2',
-'*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y',
-'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\022', 'c', 'r', 'y', 'p', 't',
-'o', 'S', 't', 'r', 'e', 'a', 'm', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'Z', '\n', '\023', 'p', 'r', 'o', 'o', 'f', '_', 's', 'o',
-'u', 'r', 'c', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\007', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y',
+'u', 'f', '/', 'w', 'r', 'a', 'p', 'p', 'e', 'r', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\037', 'x', 'd', 's', '/', 'a', 'n',
+'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', '3', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o',
+'\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's',
+'.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/',
+'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't',
+'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\244', '\007', '\n', '\023', 'Q', 'u', 'i', 'c',
+'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', ']', '\n', '\025', 'q', 'u', 'i', 'c', '_', 'p',
+'r', 'o', 't', 'o', 'c', 'o', 'l', '_', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', ')', '.', 'e',
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'Q', 'u', 'i', 'c', 'P',
+'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\023', 'q', 'u', 'i', 'c', 'P', 'r', 'o', 't', 'o',
+'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '<', '\n', '\014', 'i', 'd', 'l', 'e', '_', 't', 'i', 'm', 'e', 'o', 'u',
+'t', '\030', '\002', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f',
+'.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\013', 'i', 'd', 'l', 'e', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'S', '\n',
+'\030', 'c', 'r', 'y', 'p', 't', 'o', '_', 'h', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', '_', 't', 'i', 'm', 'e', 'o', 'u', 't',
+'\030', '\003', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.',
+'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\026', 'c', 'r', 'y', 'p', 't', 'o', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e',
+'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'B', '\n', '\007', 'e', 'n', 'a', 'b', 'l', 'e', 'd', '\030', '\004', ' ', '\001', '(', '\013', '2',
+'(', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'R', 'u',
+'n', 't', 'i', 'm', 'e', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'F', 'l', 'a', 'g', 'R', '\007', 'e', 'n', 'a', 'b', 'l', 'e', 'd',
+'\022', '}', '\n', ')', 'p', 'a', 'c', 'k', 'e', 't', 's', '_', 't', 'o', '_', 'r', 'e', 'a', 'd', '_', 't', 'o', '_', 'c', 'o',
+'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'c', 'o', 'u', 'n', 't', '_', 'r', 'a', 't', 'i', 'o', '\030', '\005', ' ', '\001', '(',
+'\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3',
+'2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '(', '\001', 'R', '#', 'p', 'a', 'c', 'k', 'e', 't', 's', 'T',
+'o', 'R', 'e', 'a', 'd', 'T', 'o', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'C', 'o', 'u', 'n', 't', 'R', 'a', 't',
+'i', 'o', '\022', '\\', '\n', '\024', 'c', 'r', 'y', 'p', 't', 'o', '_', 's', 't', 'r', 'e', 'a', 'm', '_', 'c', 'o', 'n', 'f', 'i',
+'g', '\030', '\006', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o',
+'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i',
+'g', 'R', '\022', 'c', 'r', 'y', 'p', 't', 'o', 'S', 't', 'r', 'e', 'a', 'm', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'Z', '\n', '\023',
+'p', 'r', 'o', 'o', 'f', '_', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\007', ' ', '\001', '(', '\013',
+'2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T',
+'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\021', 'p', 'r', 'o', 'o',
+'f', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'o', '\n', '\036', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i',
+'o', 'n', '_', 'i', 'd', '_', 'g', 'e', 'n', 'e', 'r', 'a', 't', 'o', 'r', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\010', ' ',
+'\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v',
+'3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\033', 'c',
+'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'I', 'd', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'o', 'r', 'C', 'o', 'n', 'f', 'i',
+'g', '\022', '{', '\n', '\037', 's', 'e', 'r', 'v', 'e', 'r', '_', 'p', 'r', 'e', 'f', 'e', 'r', 'r', 'e', 'd', '_', 'a', 'd', 'd',
+'r', 'e', 's', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\t', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y',
'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e',
-'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\021', 'p', 'r', 'o', 'o', 'f', 'S', 'o', 'u', 'r', 'c', 'e', 'C',
-'o', 'n', 'f', 'i', 'g', '\022', 'o', '\n', '\036', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'i', 'd', '_', 'g', 'e',
-'n', 'e', 'r', 'a', 't', 'o', 'r', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\010', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n',
-'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E',
-'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\033', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o',
-'n', 'I', 'd', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'o', 'r', 'C', 'o', 'n', 'f', 'i', 'g', ':', '0', '\232', '\305', '\210', '\036', '+',
-'\n', ')', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '.', 'Q',
-'u', 'i', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n', 's', 'B', '\217', '\001', '\n', '&', 'i', 'o',
-'.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.',
-'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '.', 'v', '3', 'B', '\017', 'Q', 'u', 'i', 'c', 'C', 'o', 'n', 'f', 'i', 'g', 'P', 'r',
-'o', 't', 'o', 'P', '\001', 'Z', 'J', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r',
-'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o',
-'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '/', 'v', '3', ';', 'l', 'i', 's', 't',
-'e', 'n', 'e', 'r', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
+'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'B', '\010', '\322', '\306', '\244', '\341', '\006', '\002', '\010', '\001', 'R', '\034', 's', 'e',
+'r', 'v', 'e', 'r', 'P', 'r', 'e', 'f', 'e', 'r', 'r', 'e', 'd', 'A', 'd', 'd', 'r', 'e', 's', 's', 'C', 'o', 'n', 'f', 'i',
+'g', ':', '0', '\232', '\305', '\210', '\036', '+', '\n', ')', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'l', 'i',
+'s', 't', 'e', 'n', 'e', 'r', '.', 'Q', 'u', 'i', 'c', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'O', 'p', 't', 'i', 'o', 'n',
+'s', 'B', '\217', '\001', '\n', '&', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y',
+'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '.', 'v', '3', 'B', '\017', 'Q', 'u', 'i', 'c',
+'C', 'o', 'n', 'f', 'i', 'g', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'J', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm',
+'/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l',
+'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r',
+'/', 'v', '3', ';', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p',
+'r', 'o', 't', 'o', '3',
};
-static _upb_DefPool_Init *deps[9] = {
+static _upb_DefPool_Init *deps[10] = {
&envoy_config_core_v3_base_proto_upbdefinit,
&envoy_config_core_v3_extension_proto_upbdefinit,
&envoy_config_core_v3_protocol_proto_upbdefinit,
&google_protobuf_duration_proto_upbdefinit,
&google_protobuf_wrappers_proto_upbdefinit,
+ &xds_annotations_v3_status_proto_upbdefinit,
&udpa_annotations_status_proto_upbdefinit,
&udpa_annotations_versioning_proto_upbdefinit,
&validate_validate_proto_upbdefinit,
@@ -88,5 +97,5 @@ _upb_DefPool_Init envoy_config_listener_v3_quic_config_proto_upbdefinit = {
deps,
&envoy_config_listener_v3_quic_config_proto_upb_file_layout,
"envoy/config/listener/v3/quic_config.proto",
- UPB_STRINGVIEW_INIT(descriptor, 1297)
+ UPB_STRINGVIEW_INIT(descriptor, 1455)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c
index 4ce1c5f259..6b00fb7f28 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c
@@ -25,7 +25,7 @@ extern _upb_DefPool_Init udpa_annotations_migrate_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_versioning_proto_upbdefinit;
extern _upb_DefPool_Init validate_validate_proto_upbdefinit;
-static const char descriptor[3666] = {'\n', '\037', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'b', 'a', 'c', '/', 'v', '3', '/', 'r', 'b',
+static const char descriptor[4073] = {'\n', '\037', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'b', 'a', 'c', '/', 'v', '3', '/', 'r', 'b',
'a', 'c', '.', 'p', 'r', 'o', 't', 'o', '\022', '\024', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b',
'a', 'c', '.', 'v', '3', '\032', '\"', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/',
'v', '3', '/', 'a', 'd', 'd', 'r', 'e', 's', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '$', 'e', 'n', 'v', 'o', 'y', '/', 'c',
@@ -48,130 +48,146 @@ static const char descriptor[3666] = {'\n', '\037', 'e', 'n', 'v', 'o', 'y', '/'
'\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's',
'.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/',
'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't',
-'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\266', '\002', '\n', '\004', 'R', 'B', 'A', 'C',
+'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\315', '\005', '\n', '\004', 'R', 'B', 'A', 'C',
'\022', 'C', '\n', '\006', 'a', 'c', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\016', '2', '!', '.', 'e', 'n', 'v', 'o', 'y', '.',
'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', '.', 'A', 'c', 't', 'i', 'o',
'n', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\006', 'a', 'c', 't', 'i', 'o', 'n', '\022', 'D', '\n', '\010', 'p', 'o',
'l', 'i', 'c', 'i', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '(', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f',
'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', '.', 'P', 'o', 'l', 'i', 'c', 'i', 'e', 's', 'E',
-'n', 't', 'r', 'y', 'R', '\010', 'p', 'o', 'l', 'i', 'c', 'i', 'e', 's', '\032', 'Y', '\n', '\r', 'P', 'o', 'l', 'i', 'c', 'i', 'e',
-'s', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022',
-'2', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o',
-'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'o', 'l', 'i', 'c', 'y', 'R', '\005', 'v', 'a', 'l', 'u',
-'e', ':', '\002', '8', '\001', '\"', '&', '\n', '\006', 'A', 'c', 't', 'i', 'o', 'n', '\022', '\t', '\n', '\005', 'A', 'L', 'L', 'O', 'W', '\020',
-'\000', '\022', '\010', '\n', '\004', 'D', 'E', 'N', 'Y', '\020', '\001', '\022', '\007', '\n', '\003', 'L', 'O', 'G', '\020', '\002', ':', ' ', '\232', '\305', '\210',
-'\036', '\033', '\n', '\031', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.',
-'R', 'B', 'A', 'C', '\"', '\223', '\003', '\n', '\006', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'L', '\n', '\013', 'p', 'e', 'r', 'm', 'i', 's',
-'s', 'i', 'o', 'n', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
-'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005',
-'\222', '\001', '\002', '\010', '\001', 'R', '\013', 'p', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 's', '\022', 'I', '\n', '\n', 'p', 'r', 'i',
-'n', 'c', 'i', 'p', 'a', 'l', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n',
-'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'B', '\010', '\372', 'B',
-'\005', '\222', '\001', '\002', '\010', '\001', 'R', '\n', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 's', '\022', 'Z', '\n', '\t', 'c', 'o', 'n',
-'d', 'i', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i',
-'.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'B', '\034', '\362', '\230', '\376', '\217',
-'\005', '\026', '\022', '\024', 'e', 'x', 'p', 'r', 'e', 's', 's', 'i', 'o', 'n', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'R',
-'\t', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\022', 'p', '\n', '\021', 'c', 'h', 'e', 'c', 'k', 'e', 'd', '_', 'c', 'o', 'n',
-'d', 'i', 't', 'i', 'o', 'n', '\030', '\004', ' ', '\001', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i',
-'.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'h', 'e', 'c', 'k', 'e', 'd', 'E', 'x', 'p',
+'n', 't', 'r', 'y', 'R', '\010', 'p', 'o', 'l', 'i', 'c', 'i', 'e', 's', '\022', 'b', '\n', '\025', 'a', 'u', 'd', 'i', 't', '_', 'l',
+'o', 'g', 'g', 'i', 'n', 'g', '_', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '.', '.', 'e', 'n',
+'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', '.', 'A',
+'u', 'd', 'i', 't', 'L', 'o', 'g', 'g', 'i', 'n', 'g', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\023', 'a', 'u', 'd', 'i', 't',
+'L', 'o', 'g', 'g', 'i', 'n', 'g', 'O', 'p', 't', 'i', 'o', 'n', 's', '\032', '\260', '\002', '\n', '\023', 'A', 'u', 'd', 'i', 't', 'L',
+'o', 'g', 'g', 'i', 'n', 'g', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'p', '\n', '\017', 'a', 'u', 'd', 'i', 't', '_', 'c', 'o',
+'n', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\016', '2', '=', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n',
+'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', '.', 'A', 'u', 'd', 'i', 't', 'L', 'o', 'g',
+'g', 'i', 'n', 'g', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'A', 'u', 'd', 'i', 't', 'C', 'o', 'n', 'd', 'i', 't', 'i', 'o',
+'n', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\016', 'a', 'u', 'd', 'i', 't', 'C', 'o', 'n', 'd', 'i', 't', 'i',
+'o', 'n', '\022', 'Y', '\n', '\r', 'a', 'u', 'd', 'i', 't', '_', 'l', 'o', 'g', 'g', 'e', 'r', 's', '\030', '\002', ' ', '\003', '(', '\013',
+'2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T',
+'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'B', '\010', '\372', 'B', '\005', '\222',
+'\001', '\002', '\010', '\001', 'R', '\014', 'a', 'u', 'd', 'i', 't', 'L', 'o', 'g', 'g', 'e', 'r', 's', '\"', 'L', '\n', '\016', 'A', 'u', 'd',
+'i', 't', 'C', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\022', '\010', '\n', '\004', 'N', 'O', 'N', 'E', '\020', '\000', '\022', '\013', '\n', '\007',
+'O', 'N', '_', 'D', 'E', 'N', 'Y', '\020', '\001', '\022', '\014', '\n', '\010', 'O', 'N', '_', 'A', 'L', 'L', 'O', 'W', '\020', '\002', '\022', '\025',
+'\n', '\021', 'O', 'N', '_', 'D', 'E', 'N', 'Y', '_', 'A', 'N', 'D', '_', 'A', 'L', 'L', 'O', 'W', '\020', '\003', '\032', 'Y', '\n', '\r',
+'P', 'o', 'l', 'i', 'c', 'i', 'e', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(',
+'\t', 'R', '\003', 'k', 'e', 'y', '\022', '2', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'e',
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'o', 'l', 'i', 'c',
+'y', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', '\"', '&', '\n', '\006', 'A', 'c', 't', 'i', 'o', 'n', '\022', '\t', '\n',
+'\005', 'A', 'L', 'L', 'O', 'W', '\020', '\000', '\022', '\010', '\n', '\004', 'D', 'E', 'N', 'Y', '\020', '\001', '\022', '\007', '\n', '\003', 'L', 'O', 'G',
+'\020', '\002', ':', ' ', '\232', '\305', '\210', '\036', '\033', '\n', '\031', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r',
+'b', 'a', 'c', '.', 'v', '2', '.', 'R', 'B', 'A', 'C', '\"', '\223', '\003', '\n', '\006', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'L', '\n',
+'\013', 'p', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o',
+'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i',
+'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\013', 'p', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 's',
+'\022', 'I', '\n', '\n', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\037', '.', 'e', 'n',
+'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i',
+'p', 'a', 'l', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\n', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 's',
+'\022', 'Z', '\n', '\t', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o',
+'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p',
'r', 'B', '\034', '\362', '\230', '\376', '\217', '\005', '\026', '\022', '\024', 'e', 'x', 'p', 'r', 'e', 's', 's', 'i', 'o', 'n', '_', 's', 'p', 'e',
-'c', 'i', 'f', 'i', 'e', 'r', 'R', '\020', 'c', 'h', 'e', 'c', 'k', 'e', 'd', 'C', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', ':',
-'\"', '\232', '\305', '\210', '\036', '\035', '\n', '\033', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c',
-'.', 'v', '2', '.', 'P', 'o', 'l', 'i', 'c', 'y', '\"', '\332', '\007', '\n', '\n', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n',
-'\022', 'C', '\n', '\t', 'a', 'n', 'd', '_', 'r', 'u', 'l', 'e', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v',
+'c', 'i', 'f', 'i', 'e', 'r', 'R', '\t', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\022', 'p', '\n', '\021', 'c', 'h', 'e', 'c',
+'k', 'e', 'd', '_', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\004', ' ', '\001', '(', '\013', '2', '%', '.', 'g', 'o', 'o',
+'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'h', 'e',
+'c', 'k', 'e', 'd', 'E', 'x', 'p', 'r', 'B', '\034', '\362', '\230', '\376', '\217', '\005', '\026', '\022', '\024', 'e', 'x', 'p', 'r', 'e', 's', 's',
+'i', 'o', 'n', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'R', '\020', 'c', 'h', 'e', 'c', 'k', 'e', 'd', 'C', 'o', 'n',
+'d', 'i', 't', 'i', 'o', 'n', ':', '\"', '\232', '\305', '\210', '\036', '\035', '\n', '\033', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f',
+'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'o', 'l', 'i', 'c', 'y', '\"', '\332', '\007', '\n', '\n', 'P', 'e', 'r',
+'m', 'i', 's', 's', 'i', 'o', 'n', '\022', 'C', '\n', '\t', 'a', 'n', 'd', '_', 'r', 'u', 'l', 'e', 's', '\030', '\001', ' ', '\001', '(',
+'\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.',
+'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', '.', 'S', 'e', 't', 'H', '\000', 'R', '\010', 'a', 'n', 'd', 'R', 'u', 'l', 'e',
+'s', '\022', 'A', '\n', '\010', 'o', 'r', '_', 'r', 'u', 'l', 'e', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v',
'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's',
-'i', 'o', 'n', '.', 'S', 'e', 't', 'H', '\000', 'R', '\010', 'a', 'n', 'd', 'R', 'u', 'l', 'e', 's', '\022', 'A', '\n', '\010', 'o', 'r',
-'_', 'r', 'u', 'l', 'e', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f',
-'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', '.', 'S', 'e', 't',
-'H', '\000', 'R', '\007', 'o', 'r', 'R', 'u', 'l', 'e', 's', '\022', '\033', '\n', '\003', 'a', 'n', 'y', '\030', '\003', ' ', '\001', '(', '\010', 'B',
-'\007', '\372', 'B', '\004', 'j', '\002', '\010', '\001', 'H', '\000', 'R', '\003', 'a', 'n', 'y', '\022', '>', '\n', '\006', 'h', 'e', 'a', 'd', 'e', 'r',
-'\030', '\004', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u',
-'t', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\006', 'h', 'e',
-'a', 'd', 'e', 'r', '\022', '?', '\n', '\010', 'u', 'r', 'l', '_', 'p', 'a', 't', 'h', '\030', '\n', ' ', '\001', '(', '\013', '2', '\"', '.',
-'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'P', 'a', 't',
-'h', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\007', 'u', 'r', 'l', 'P', 'a', 't', 'h', '\022', 'H', '\n', '\016', 'd', 'e',
-'s', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'i', 'p', '\030', '\005', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o',
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g',
-'e', 'H', '\000', 'R', '\r', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'I', 'p', '\022', '6', '\n', '\020', 'd', 'e', 's',
-'t', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'p', 'o', 'r', 't', '\030', '\006', ' ', '\001', '(', '\r', 'B', '\t', '\372', 'B', '\006', '*',
-'\004', '\030', '\377', '\377', '\003', 'H', '\000', 'R', '\017', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'P', 'o', 'r', 't', '\022',
-'Q', '\n', '\026', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'p', 'o', 'r', 't', '_', 'r', 'a', 'n', 'g', 'e',
-'\030', '\013', ' ', '\001', '(', '\013', '2', '\031', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'I', 'n',
-'t', '3', '2', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\024', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'P', 'o',
-'r', 't', 'R', 'a', 'n', 'g', 'e', '\022', 'D', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\007', ' ', '\001', '(', '\013',
-'2', '&', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.',
-'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\010', 'm', 'e', 't', 'a', 'd', 'a',
-'t', 'a', '\022', '=', '\n', '\010', 'n', 'o', 't', '_', 'r', 'u', 'l', 'e', '\030', '\010', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n',
-'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's',
-'s', 'i', 'o', 'n', 'H', '\000', 'R', '\007', 'n', 'o', 't', 'R', 'u', 'l', 'e', '\022', 'Z', '\n', '\025', 'r', 'e', 'q', 'u', 'e', 's',
-'t', 'e', 'd', '_', 's', 'e', 'r', 'v', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030', '\t', ' ', '\001', '(', '\013', '2', '$', '.', 'e',
-'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i',
-'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\023', 'r', 'e', 'q', 'u', 'e', 's', 't', 'e', 'd', 'S', 'e', 'r',
-'v', 'e', 'r', 'N', 'a', 'm', 'e', '\022', 'F', '\n', '\007', 'm', 'a', 't', 'c', 'h', 'e', 'r', '\030', '\014', ' ', '\001', '(', '\013', '2',
-'*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y',
-'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', '\007', 'm', 'a', 't',
-'c', 'h', 'e', 'r', '\032', 's', '\n', '\003', 'S', 'e', 't', '\022', '@', '\n', '\005', 'r', 'u', 'l', 'e', 's', '\030', '\001', ' ', '\003', '(',
-'\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.',
-'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\005', 'r', 'u', 'l',
-'e', 's', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r',
-'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', '.', 'S', 'e', 't', ':', '&', '\232', '\305',
-'\210', '\036', '!', '\n', '\037', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2',
-'.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'B', '\013', '\n', '\004', 'r', 'u', 'l', 'e', '\022', '\003', '\370', 'B', '\001', '\"',
-'\353', '\010', '\n', '\t', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '\022', '>', '\n', '\007', 'a', 'n', 'd', '_', 'i', 'd', 's', '\030',
-'\001', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c',
-'.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'S', 'e', 't', 'H', '\000', 'R', '\006', 'a', 'n', 'd', 'I',
-'d', 's', '\022', '<', '\n', '\006', 'o', 'r', '_', 'i', 'd', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o',
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a',
-'l', '.', 'S', 'e', 't', 'H', '\000', 'R', '\005', 'o', 'r', 'I', 'd', 's', '\022', '\033', '\n', '\003', 'a', 'n', 'y', '\030', '\003', ' ', '\001',
-'(', '\010', 'B', '\007', '\372', 'B', '\004', 'j', '\002', '\010', '\001', 'H', '\000', 'R', '\003', 'a', 'n', 'y', '\022', 'U', '\n', '\r', 'a', 'u', 't',
-'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', '\030', '\004', ' ', '\001', '(', '\013', '2', '-', '.', 'e', 'n', 'v', 'o', 'y', '.',
-'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.',
-'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', 'H', '\000', 'R', '\r', 'a', 'u', 't', 'h', 'e', 'n', 't', 'i',
-'c', 'a', 't', 'e', 'd', '\022', 'K', '\n', '\t', 's', 'o', 'u', 'r', 'c', 'e', '_', 'i', 'p', '\030', '\005', ' ', '\001', '(', '\013', '2',
-'\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i',
-'d', 'r', 'R', 'a', 'n', 'g', 'e', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\010', 's',
-'o', 'u', 'r', 'c', 'e', 'I', 'p', '\022', 'K', '\n', '\020', 'd', 'i', 'r', 'e', 'c', 't', '_', 'r', 'e', 'm', 'o', 't', 'e', '_',
-'i', 'p', '\030', '\n', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c',
-'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\016', 'd', 'i', 'r', 'e', 'c',
-'t', 'R', 'e', 'm', 'o', 't', 'e', 'I', 'p', '\022', '>', '\n', '\t', 'r', 'e', 'm', 'o', 't', 'e', '_', 'i', 'p', '\030', '\013', ' ',
-'\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v',
-'3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\010', 'r', 'e', 'm', 'o', 't', 'e', 'I', 'p', '\022', '>',
-'\n', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\030', '\006', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o',
-'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h',
-'e', 'r', 'H', '\000', 'R', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\022', '?', '\n', '\010', 'u', 'r', 'l', '_', 'p', 'a', 't', 'h', '\030',
-'\t', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e',
-'r', '.', 'v', '3', '.', 'P', 'a', 't', 'h', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\007', 'u', 'r', 'l', 'P', 'a',
-'t', 'h', '\022', 'D', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\007', ' ', '\001', '(', '\013', '2', '&', '.', 'e', 'n',
-'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd',
-'a', 't', 'a', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', 'N', '\n',
-'\014', 'f', 'i', 'l', 't', 'e', 'r', '_', 's', 't', 'a', 't', 'e', '\030', '\014', ' ', '\001', '(', '\013', '2', ')', '.', 'e', 'n', 'v',
-'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'F', 'i', 'l', 't', 'e', 'r',
-'S', 't', 'a', 't', 'e', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\013', 'f', 'i', 'l', 't', 'e', 'r', 'S', 't', 'a',
-'t', 'e', '\022', '8', '\n', '\006', 'n', 'o', 't', '_', 'i', 'd', '\030', '\010', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o',
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a',
-'l', 'H', '\000', 'R', '\005', 'n', 'o', 't', 'I', 'd', '\032', 'm', '\n', '\003', 'S', 'e', 't', '\022', ';', '\n', '\003', 'i', 'd', 's', '\030',
-'\001', ' ', '\003', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c',
-'.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\003',
-'i', 'd', 's', ':', ')', '\232', '\305', '\210', '\036', '$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.',
-'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'S', 'e', 't', '\032', '\227', '\001', '\n',
-'\r', 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', '\022', 'K', '\n', '\016', 'p', 'r', 'i', 'n', 'c', 'i', 'p',
-'a', 'l', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p',
-'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e',
-'r', 'R', '\r', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'N', 'a', 'm', 'e', ':', '3', '\232', '\305', '\210', '\036', '.', '\n', ',',
-'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'r', 'i', 'n',
-'c', 'i', 'p', 'a', 'l', '.', 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', 'J', '\004', '\010', '\001', '\020', '\002',
-':', '%', '\232', '\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a',
-'c', '.', 'v', '2', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'B', '\021', '\n', '\n', 'i', 'd', 'e', 'n', 't', 'i', 'f',
-'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', '\"', '`', '\n', '\006', 'A', 'c', 't', 'i', 'o', 'n', '\022', '\033', '\n', '\004', 'n', 'a', 'm',
-'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '9', '\n',
-'\006', 'a', 'c', 't', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\016', '2', '!', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n',
-'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', '.', 'A', 'c', 't', 'i', 'o', 'n', 'R', '\006',
-'a', 'c', 't', 'i', 'o', 'n', 'B', '}', '\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e',
-'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', 'B', '\t', 'R', 'b', 'a', 'c',
-'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'B', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y',
-'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n',
-'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'b', 'a', 'c', '/', 'v', '3', ';', 'r', 'b', 'a', 'c', 'v', '3',
-'\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
+'i', 'o', 'n', '.', 'S', 'e', 't', 'H', '\000', 'R', '\007', 'o', 'r', 'R', 'u', 'l', 'e', 's', '\022', '\033', '\n', '\003', 'a', 'n', 'y',
+'\030', '\003', ' ', '\001', '(', '\010', 'B', '\007', '\372', 'B', '\004', 'j', '\002', '\010', '\001', 'H', '\000', 'R', '\003', 'a', 'n', 'y', '\022', '>', '\n',
+'\006', 'h', 'e', 'a', 'd', 'e', 'r', '\030', '\004', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n',
+'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e',
+'r', 'H', '\000', 'R', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\022', '?', '\n', '\010', 'u', 'r', 'l', '_', 'p', 'a', 't', 'h', '\030', '\n',
+' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r',
+'.', 'v', '3', '.', 'P', 'a', 't', 'h', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\007', 'u', 'r', 'l', 'P', 'a', 't',
+'h', '\022', 'H', '\n', '\016', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'i', 'p', '\030', '\005', ' ', '\001', '(', '\013',
+'2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C',
+'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\r', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'I', 'p',
+'\022', '6', '\n', '\020', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'p', 'o', 'r', 't', '\030', '\006', ' ', '\001', '(',
+'\r', 'B', '\t', '\372', 'B', '\006', '*', '\004', '\030', '\377', '\377', '\003', 'H', '\000', 'R', '\017', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i',
+'o', 'n', 'P', 'o', 'r', 't', '\022', 'Q', '\n', '\026', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'p', 'o', 'r',
+'t', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\013', ' ', '\001', '(', '\013', '2', '\031', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p',
+'e', '.', 'v', '3', '.', 'I', 'n', 't', '3', '2', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\024', 'd', 'e', 's', 't', 'i', 'n',
+'a', 't', 'i', 'o', 'n', 'P', 'o', 'r', 't', 'R', 'a', 'n', 'g', 'e', '\022', 'D', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't',
+'a', '\030', '\007', ' ', '\001', '(', '\013', '2', '&', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c',
+'h', 'e', 'r', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R',
+'\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', '=', '\n', '\010', 'n', 'o', 't', '_', 'r', 'u', 'l', 'e', '\030', '\010', ' ', '\001',
+'(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3',
+'.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'H', '\000', 'R', '\007', 'n', 'o', 't', 'R', 'u', 'l', 'e', '\022', 'Z', '\n',
+'\025', 'r', 'e', 'q', 'u', 'e', 's', 't', 'e', 'd', '_', 's', 'e', 'r', 'v', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030', '\t', ' ',
+'\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.',
+'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\023', 'r', 'e', 'q', 'u', 'e',
+'s', 't', 'e', 'd', 'S', 'e', 'r', 'v', 'e', 'r', 'N', 'a', 'm', 'e', '\022', 'F', '\n', '\007', 'm', 'a', 't', 'c', 'h', 'e', 'r',
+'\030', '\014', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r',
+'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g',
+'H', '\000', 'R', '\007', 'm', 'a', 't', 'c', 'h', 'e', 'r', '\032', 's', '\n', '\003', 'S', 'e', 't', '\022', '@', '\n', '\005', 'r', 'u', 'l',
+'e', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r',
+'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002',
+'\010', '\001', 'R', '\005', 'r', 'u', 'l', 'e', 's', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'c',
+'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', '.',
+'S', 'e', 't', ':', '&', '\232', '\305', '\210', '\036', '!', '\n', '\037', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.',
+'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'B', '\013', '\n', '\004', 'r', 'u', 'l',
+'e', '\022', '\003', '\370', 'B', '\001', '\"', '\353', '\010', '\n', '\t', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '\022', '>', '\n', '\007', 'a',
+'n', 'd', '_', 'i', 'd', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f',
+'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'S', 'e', 't', 'H',
+'\000', 'R', '\006', 'a', 'n', 'd', 'I', 'd', 's', '\022', '<', '\n', '\006', 'o', 'r', '_', 'i', 'd', 's', '\030', '\002', ' ', '\001', '(', '\013',
+'2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P',
+'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'S', 'e', 't', 'H', '\000', 'R', '\005', 'o', 'r', 'I', 'd', 's', '\022', '\033', '\n', '\003',
+'a', 'n', 'y', '\030', '\003', ' ', '\001', '(', '\010', 'B', '\007', '\372', 'B', '\004', 'j', '\002', '\010', '\001', 'H', '\000', 'R', '\003', 'a', 'n', 'y',
+'\022', 'U', '\n', '\r', 'a', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', '\030', '\004', ' ', '\001', '(', '\013', '2', '-',
+'.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i',
+'n', 'c', 'i', 'p', 'a', 'l', '.', 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', 'H', '\000', 'R', '\r', 'a',
+'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', '\022', 'K', '\n', '\t', 's', 'o', 'u', 'r', 'c', 'e', '_', 'i', 'p',
+'\030', '\005', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r',
+'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3',
+'.', '0', 'H', '\000', 'R', '\010', 's', 'o', 'u', 'r', 'c', 'e', 'I', 'p', '\022', 'K', '\n', '\020', 'd', 'i', 'r', 'e', 'c', 't', '_',
+'r', 'e', 'm', 'o', 't', 'e', '_', 'i', 'p', '\030', '\n', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c',
+'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', '\000',
+'R', '\016', 'd', 'i', 'r', 'e', 'c', 't', 'R', 'e', 'm', 'o', 't', 'e', 'I', 'p', '\022', '>', '\n', '\t', 'r', 'e', 'm', 'o', 't',
+'e', '_', 'i', 'p', '\030', '\013', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g',
+'.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\010', 'r', 'e', 'm',
+'o', 't', 'e', 'I', 'p', '\022', '>', '\n', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\030', '\006', ' ', '\001', '(', '\013', '2', '$', '.', 'e',
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd',
+'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\022', '?', '\n', '\010', 'u', 'r',
+'l', '_', 'p', 'a', 't', 'h', '\030', '\t', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e',
+'.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'P', 'a', 't', 'h', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000',
+'R', '\007', 'u', 'r', 'l', 'P', 'a', 't', 'h', '\022', 'D', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\007', ' ', '\001',
+'(', '\013', '2', '&', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v',
+'3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\010', 'm', 'e', 't', 'a',
+'d', 'a', 't', 'a', '\022', 'N', '\n', '\014', 'f', 'i', 'l', 't', 'e', 'r', '_', 's', 't', 'a', 't', 'e', '\030', '\014', ' ', '\001', '(',
+'\013', '2', ')', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3',
+'.', 'F', 'i', 'l', 't', 'e', 'r', 'S', 't', 'a', 't', 'e', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\013', 'f', 'i',
+'l', 't', 'e', 'r', 'S', 't', 'a', 't', 'e', '\022', '8', '\n', '\006', 'n', 'o', 't', '_', 'i', 'd', '\030', '\010', ' ', '\001', '(', '\013',
+'2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P',
+'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'H', '\000', 'R', '\005', 'n', 'o', 't', 'I', 'd', '\032', 'm', '\n', '\003', 'S', 'e', 't', '\022',
+';', '\n', '\003', 'i', 'd', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f',
+'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'B', '\010', '\372', 'B', '\005',
+'\222', '\001', '\002', '\010', '\001', 'R', '\003', 'i', 'd', 's', ':', ')', '\232', '\305', '\210', '\036', '$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', '.',
+'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.',
+'S', 'e', 't', '\032', '\227', '\001', '\n', '\r', 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', '\022', 'K', '\n', '\016',
+'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n',
+'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n',
+'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\r', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'N', 'a', 'm', 'e', ':', '3',
+'\232', '\305', '\210', '\036', '.', '\n', ',', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.',
+'v', '2', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e',
+'d', 'J', '\004', '\010', '\001', '\020', '\002', ':', '%', '\232', '\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n',
+'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'B', '\021', '\n', '\n',
+'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', '\"', '`', '\n', '\006', 'A', 'c', 't', 'i', 'o', 'n',
+'\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004',
+'n', 'a', 'm', 'e', '\022', '9', '\n', '\006', 'a', 'c', 't', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\016', '2', '!', '.', 'e', 'n',
+'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', '.', 'A',
+'c', 't', 'i', 'o', 'n', 'R', '\006', 'a', 'c', 't', 'i', 'o', 'n', 'B', '}', '\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y',
+'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v',
+'3', 'B', '\t', 'R', 'b', 'a', 'c', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'B', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o',
+'m', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p',
+'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'b', 'a', 'c', '/', 'v', '3',
+';', 'r', 'b', 'a', 'c', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
};
static _upb_DefPool_Init *deps[16] = {
@@ -197,5 +213,5 @@ _upb_DefPool_Init envoy_config_rbac_v3_rbac_proto_upbdefinit = {
deps,
&envoy_config_rbac_v3_rbac_proto_upb_file_layout,
"envoy/config/rbac/v3/rbac.proto",
- UPB_STRINGVIEW_INIT(descriptor, 3666)
+ UPB_STRINGVIEW_INIT(descriptor, 4073)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.h b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.h
index 53a846ebc8..e49d8175f1 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.h
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.h
@@ -26,6 +26,11 @@ UPB_INLINE const upb_MessageDef *envoy_config_rbac_v3_RBAC_getmsgdef(upb_DefPool
return upb_DefPool_FindMessageByName(s, "envoy.config.rbac.v3.RBAC");
}
+UPB_INLINE const upb_MessageDef *envoy_config_rbac_v3_RBAC_AuditLoggingOptions_getmsgdef(upb_DefPool *s) {
+ _upb_DefPool_LoadDefInit(s, &envoy_config_rbac_v3_rbac_proto_upbdefinit);
+ return upb_DefPool_FindMessageByName(s, "envoy.config.rbac.v3.RBAC.AuditLoggingOptions");
+}
+
UPB_INLINE const upb_MessageDef *envoy_config_rbac_v3_RBAC_PoliciesEntry_getmsgdef(upb_DefPool *s) {
_upb_DefPool_LoadDefInit(s, &envoy_config_rbac_v3_rbac_proto_upbdefinit);
return upb_DefPool_FindMessageByName(s, "envoy.config.rbac.v3.RBAC.PoliciesEntry");
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c
index 94f77ec49e..f05036fca9 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c
@@ -30,7 +30,7 @@ extern _upb_DefPool_Init udpa_annotations_migrate_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_versioning_proto_upbdefinit;
extern _upb_DefPool_Init validate_validate_proto_upbdefinit;
-static const char descriptor[22618] = {'\n', ',', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'o', 'u', 't', 'e', '/', 'v', '3', '/', 'r',
+static const char descriptor[22684] = {'\n', ',', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'o', 'u', 't', 'e', '/', 'v', '3', '/', 'r',
'o', 'u', 't', 'e', '_', 'c', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', 's', '.', 'p', 'r', 'o', 't', 'o', '\022', '\025', 'e', 'n',
'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '\032', '\037', 'e', 'n', 'v', 'o',
'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'b', 'a', 's', 'e', '.', 'p', 'r', 'o',
@@ -725,7 +725,7 @@ static const char descriptor[22618] = {'\n', ',', 'e', 'n', 'v', 'o', 'y', '/',
'\n', '\004', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a',
'm', 'e', ':', '(', '\232', '\305', '\210', '\036', '#', '\n', '!', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r',
'o', 'u', 't', 'e', '.', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'C', 'l', 'u', 's', 't', 'e', 'r', 'J', '\004', '\010', '\001', '\020', '\002',
-'J', '\004', '\010', '\003', '\020', '\004', 'R', '\007', 'p', 'a', 't', 't', 'e', 'r', 'n', 'R', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\"', '\243',
+'J', '\004', '\010', '\003', '\020', '\004', 'R', '\007', 'p', 'a', 't', 't', 'e', 'r', 'n', 'R', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\"', '\311',
'\034', '\n', '\t', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '\022', ';', '\n', '\005', 's', 't', 'a', 'g', 'e', '\030', '\001', ' ', '\001',
'(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't',
'3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '*', '\002', '\030', '\n', 'R', '\005', 's', 't', 'a', 'g', 'e', '\022', '\037',
@@ -735,7 +735,7 @@ static const char descriptor[22618] = {'\n', ',', 'e', 'n', 'v', 'o', 'y', '/',
't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R',
'\007', 'a', 'c', 't', 'i', 'o', 'n', 's', '\022', '?', '\n', '\005', 'l', 'i', 'm', 'i', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', ')',
'.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a',
-'t', 'e', 'L', 'i', 'm', 'i', 't', '.', 'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', 'R', '\005', 'l', 'i', 'm', 'i', 't', '\032', '\217',
+'t', 'e', 'L', 'i', 'm', 'i', 't', '.', 'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', 'R', '\005', 'l', 'i', 'm', 'i', 't', '\032', '\265',
'\030', '\n', '\006', 'A', 'c', 't', 'i', 'o', 'n', '\022', '^', '\n', '\016', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'l', 'u', 's', 't',
'e', 'r', '\030', '\001', ' ', '\001', '(', '\013', '2', '5', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r',
'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.',
@@ -833,7 +833,7 @@ static const char descriptor[22618] = {'\n', ',', 'e', 'n', 'v', 'o', 'y', '/',
'a', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020',
'\001', 'R', '\013', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', '\022', '#', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't',
'_', 'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\014', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'u',
-'e', '\032', '\264', '\002', '\n', '\010', 'M', 'e', 't', 'a', 'D', 'a', 't', 'a', '\022', '.', '\n', '\016', 'd', 'e', 's', 'c', 'r', 'i', 'p',
+'e', '\032', '\332', '\002', '\n', '\010', 'M', 'e', 't', 'a', 'D', 'a', 't', 'a', '\022', '.', '\n', '\016', 'd', 'e', 's', 'c', 'r', 'i', 'p',
't', 'o', 'r', '_', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\r', 'd',
'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'K', 'e', 'y', '\022', 'P', '\n', '\014', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_',
'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'e',
@@ -843,98 +843,101 @@ static const char descriptor[22618] = {'\n', ',', 'e', 'n', 'v', 'o', 'y', '/',
't', 'V', 'a', 'l', 'u', 'e', '\022', 'Y', '\n', '\006', 's', 'o', 'u', 'r', 'c', 'e', '\030', '\004', ' ', '\001', '(', '\016', '2', '7', '.',
'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't',
'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', '.', 'M', 'e', 't', 'a', 'D', 'a', 't', 'a', '.', 'S', 'o',
-'u', 'r', 'c', 'e', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\006', 's', 'o', 'u', 'r', 'c', 'e', '\"', '&', '\n',
-'\006', 'S', 'o', 'u', 'r', 'c', 'e', '\022', '\013', '\n', '\007', 'D', 'Y', 'N', 'A', 'M', 'I', 'C', '\020', '\000', '\022', '\017', '\n', '\013', 'R',
-'O', 'U', 'T', 'E', '_', 'E', 'N', 'T', 'R', 'Y', '\020', '\001', '\032', '\227', '\002', '\n', '\030', 'Q', 'u', 'e', 'r', 'y', 'P', 'a', 'r',
-'a', 'm', 'e', 't', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'M', 'a', 't', 'c', 'h', '\022', '%', '\n', '\016', 'd', 'e', 's', 'c', 'r',
-'i', 'p', 't', 'o', 'r', '_', 'k', 'e', 'y', '\030', '\004', ' ', '\001', '(', '\t', 'R', '\r', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't',
-'o', 'r', 'K', 'e', 'y', '\022', '2', '\n', '\020', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'v', 'a', 'l', 'u', 'e',
-'\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\017', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't',
-'o', 'r', 'V', 'a', 'l', 'u', 'e', '\022', '=', '\n', '\014', 'e', 'x', 'p', 'e', 'c', 't', '_', 'm', 'a', 't', 'c', 'h', '\030', '\002',
-' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o',
-'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', '\013', 'e', 'x', 'p', 'e', 'c', 't', 'M', 'a', 't', 'c', 'h', '\022', 'a', '\n', '\020', 'q',
-'u', 'e', 'r', 'y', '_', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', ',', '.', 'e',
-'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'Q', 'u', 'e', 'r',
-'y', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002',
-'\010', '\001', 'R', '\017', 'q', 'u', 'e', 'r', 'y', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 's', ':', '*', '\232', '\305', '\210', '\036',
-'%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't',
-'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o', 'n', 'B', '\027', '\n', '\020', 'a', 'c', 't', 'i', 'o', 'n', '_', 's',
-'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', '\032', '\362', '\001', '\n', '\010', 'O', 'v', 'e', 'r', 'r', 'i', 'd',
-'e', '\022', 'f', '\n', '\020', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '_', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\001', ' ', '\001',
-'(', '\013', '2', '9', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v',
-'3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '.', 'D', 'y', 'n', 'a',
-'m', 'i', 'c', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'H', '\000', 'R', '\017', 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'M', 'e', 't',
-'a', 'd', 'a', 't', 'a', '\032', 'c', '\n', '\017', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022',
-'P', '\n', '\014', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\013', '2', '#', '.', 'e',
-'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '.', 'v', '3', '.', 'M', 'e', 't',
-'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\013', 'm', 'e', 't', 'a', 'd',
-'a', 't', 'a', 'K', 'e', 'y', 'B', '\031', '\n', '\022', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '_', 's', 'p', 'e', 'c', 'i', 'f',
-'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', ':', '#', '\232', '\305', '\210', '\036', '\036', '\n', '\034', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p',
-'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '\"', '\346', '\005', '\n', '\r',
-'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', '\022', '!', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001',
-'(', '\t', 'B', '\r', '\372', 'B', '\n', 'r', '\010', '\020', '\001', '\300', '\001', '\001', '\310', '\001', '\000', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '.',
-'\n', '\013', 'e', 'x', 'a', 'c', 't', '_', 'm', 'a', 't', 'c', 'h', '\030', '\004', ' ', '\001', '(', '\t', 'B', '\013', '\030', '\001', '\222', '\307',
-'\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\n', 'e', 'x', 'a', 'c', 't', 'M', 'a', 't', 'c', 'h', '\022', '\\', '\n', '\020',
-'s', 'a', 'f', 'e', '_', 'r', 'e', 'g', 'e', 'x', '_', 'm', 'a', 't', 'c', 'h', '\030', '\013', ' ', '\001', '(', '\013', '2', '#', '.',
-'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'R', 'e', 'g',
-'e', 'x', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R',
-'\016', 's', 'a', 'f', 'e', 'R', 'e', 'g', 'e', 'x', 'M', 'a', 't', 'c', 'h', '\022', '<', '\n', '\013', 'r', 'a', 'n', 'g', 'e', '_',
-'m', 'a', 't', 'c', 'h', '\030', '\006', ' ', '\001', '(', '\013', '2', '\031', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.',
-'v', '3', '.', 'I', 'n', 't', '6', '4', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\n', 'r', 'a', 'n', 'g', 'e', 'M', 'a', 't',
-'c', 'h', '\022', '%', '\n', '\r', 'p', 'r', 'e', 's', 'e', 'n', 't', '_', 'm', 'a', 't', 'c', 'h', '\030', '\007', ' ', '\001', '(', '\010',
-'H', '\000', 'R', '\014', 'p', 'r', 'e', 's', 'e', 'n', 't', 'M', 'a', 't', 'c', 'h', '\022', '7', '\n', '\014', 'p', 'r', 'e', 'f', 'i',
-'x', '_', 'm', 'a', 't', 'c', 'h', '\030', '\t', ' ', '\001', '(', '\t', 'B', '\022', '\030', '\001', '\372', 'B', '\004', 'r', '\002', '\020', '\001', '\222',
-'\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\013', 'p', 'r', 'e', 'f', 'i', 'x', 'M', 'a', 't', 'c', 'h', '\022', '7',
-'\n', '\014', 's', 'u', 'f', 'f', 'i', 'x', '_', 'm', 'a', 't', 'c', 'h', '\030', '\n', ' ', '\001', '(', '\t', 'B', '\022', '\030', '\001', '\372',
-'B', '\004', 'r', '\002', '\020', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\013', 's', 'u', 'f', 'f', 'i', 'x',
-'M', 'a', 't', 'c', 'h', '\022', ';', '\n', '\016', 'c', 'o', 'n', 't', 'a', 'i', 'n', 's', '_', 'm', 'a', 't', 'c', 'h', '\030', '\014',
-' ', '\001', '(', '\t', 'B', '\022', '\030', '\001', '\372', 'B', '\004', 'r', '\002', '\020', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H',
-'\000', 'R', '\r', 'c', 'o', 'n', 't', 'a', 'i', 'n', 's', 'M', 'a', 't', 'c', 'h', '\022', 'I', '\n', '\014', 's', 't', 'r', 'i', 'n',
-'g', '_', 'm', 'a', 't', 'c', 'h', '\030', '\r', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p',
-'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e',
-'r', 'H', '\000', 'R', '\013', 's', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', '\022', '!', '\n', '\014', 'i', 'n', 'v', 'e', 'r',
-'t', '_', 'm', 'a', 't', 'c', 'h', '\030', '\010', ' ', '\001', '(', '\010', 'R', '\013', 'i', 'n', 'v', 'e', 'r', 't', 'M', 'a', 't', 'c',
-'h', '\022', '@', '\n', '\035', 't', 'r', 'e', 'a', 't', '_', 'm', 'i', 's', 's', 'i', 'n', 'g', '_', 'h', 'e', 'a', 'd', 'e', 'r',
-'_', 'a', 's', '_', 'e', 'm', 'p', 't', 'y', '\030', '\016', ' ', '\001', '(', '\010', 'R', '\031', 't', 'r', 'e', 'a', 't', 'M', 'i', 's',
-'s', 'i', 'n', 'g', 'H', 'e', 'a', 'd', 'e', 'r', 'A', 's', 'E', 'm', 'p', 't', 'y', ':', '\'', '\232', '\305', '\210', '\036', '\"', '\n',
-' ', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'H', 'e', 'a', 'd', 'e',
-'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '\030', '\n', '\026', 'h', 'e', 'a', 'd', 'e', 'r', '_', 'm', 'a', 't', 'c', 'h', '_',
-'s', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'J', '\004', '\010', '\002', '\020', '\003', 'J', '\004', '\010', '\003', '\020', '\004', 'J', '\004', '\010', '\005',
-'\020', '\006', 'R', '\013', 'r', 'e', 'g', 'e', 'x', '_', 'm', 'a', 't', 'c', 'h', '\"', '\241', '\002', '\n', '\025', 'Q', 'u', 'e', 'r', 'y',
-'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', '\022', '\036', '\n', '\004', 'n', 'a', 'm', 'e', '\030',
-'\001', ' ', '\001', '(', '\t', 'B', '\n', '\372', 'B', '\007', 'r', '\005', '\020', '\001', '(', '\200', '\010', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'S',
-'\n', '\014', 's', 't', 'r', 'i', 'n', 'g', '_', 'm', 'a', 't', 'c', 'h', '\030', '\005', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n',
-'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n',
-'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'H', '\000', 'R', '\013', 's', 't', 'r',
-'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', '\022', '%', '\n', '\r', 'p', 'r', 'e', 's', 'e', 'n', 't', '_', 'm', 'a', 't', 'c', 'h',
-'\030', '\006', ' ', '\001', '(', '\010', 'H', '\000', 'R', '\014', 'p', 'r', 'e', 's', 'e', 'n', 't', 'M', 'a', 't', 'c', 'h', ':', '/', '\232',
-'\305', '\210', '\036', '*', '\n', '(', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.',
-'Q', 'u', 'e', 'r', 'y', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '!', '\n', '\037',
-'q', 'u', 'e', 'r', 'y', '_', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', '_', 'm', 'a', 't', 'c', 'h', '_', 's', 'p', 'e',
-'c', 'i', 'f', 'i', 'e', 'r', 'J', '\004', '\010', '\003', '\020', '\004', 'J', '\004', '\010', '\004', '\020', '\005', 'R', '\005', 'v', 'a', 'l', 'u', 'e',
-'R', '\005', 'r', 'e', 'g', 'e', 'x', '\"', '\271', '\002', '\n', '\026', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'R', 'e', 'd', 'i', 'r',
-'e', 'c', 't', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'R', '\n', '\026', 'm', 'a', 'x', '_', 'i', 'n', 't', 'e', 'r', 'n', 'a', 'l',
-'_', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e',
-'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '\024', 'm', 'a',
-'x', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 's', '\022', '@', '\n', '\027', 'r', 'e', 'd',
-'i', 'r', 'e', 'c', 't', '_', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 'c', 'o', 'd', 'e', 's', '\030', '\002', ' ', '\003', '(',
-'\r', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\020', '\005', 'R', '\025', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'R', 'e', 's', 'p',
-'o', 'n', 's', 'e', 'C', 'o', 'd', 'e', 's', '\022', 'J', '\n', '\n', 'p', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', 's', '\030', '\003',
-' ', '\003', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.',
-'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\n',
-'p', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', 's', '\022', '=', '\n', '\033', 'a', 'l', 'l', 'o', 'w', '_', 'c', 'r', 'o', 's', 's',
-'_', 's', 'c', 'h', 'e', 'm', 'e', '_', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\030', '\004', ' ', '\001', '(', '\010', 'R', '\030', 'a',
-'l', 'l', 'o', 'w', 'C', 'r', 'o', 's', 's', 'S', 'c', 'h', 'e', 'm', 'e', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\"', ']',
-'\n', '\014', 'F', 'i', 'l', 't', 'e', 'r', 'C', 'o', 'n', 'f', 'i', 'g', '\022', ',', '\n', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\030',
-'\001', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A',
-'n', 'y', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\022', '\037', '\n', '\013', 'i', 's', '_', 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l',
-'\030', '\002', ' ', '\001', '(', '\010', 'R', '\n', 'i', 's', 'O', 'p', 't', 'i', 'o', 'n', 'a', 'l', 'B', '\213', '\001', '\n', '#', 'i', 'o',
-'.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.',
-'r', 'o', 'u', 't', 'e', '.', 'v', '3', 'B', '\024', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', 's',
-'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'D', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y',
-'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n',
-'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'o', 'u', 't', 'e', '/', 'v', '3', ';', 'r', 'o', 'u', 't', 'e',
-'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
+'u', 'r', 'c', 'e', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\006', 's', 'o', 'u', 'r', 'c', 'e', '\022', '$', '\n',
+'\016', 's', 'k', 'i', 'p', '_', 'i', 'f', '_', 'a', 'b', 's', 'e', 'n', 't', '\030', '\005', ' ', '\001', '(', '\010', 'R', '\014', 's', 'k',
+'i', 'p', 'I', 'f', 'A', 'b', 's', 'e', 'n', 't', '\"', '&', '\n', '\006', 'S', 'o', 'u', 'r', 'c', 'e', '\022', '\013', '\n', '\007', 'D',
+'Y', 'N', 'A', 'M', 'I', 'C', '\020', '\000', '\022', '\017', '\n', '\013', 'R', 'O', 'U', 'T', 'E', '_', 'E', 'N', 'T', 'R', 'Y', '\020', '\001',
+'\032', '\227', '\002', '\n', '\030', 'Q', 'u', 'e', 'r', 'y', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'M',
+'a', 't', 'c', 'h', '\022', '%', '\n', '\016', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'k', 'e', 'y', '\030', '\004', ' ',
+'\001', '(', '\t', 'R', '\r', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'K', 'e', 'y', '\022', '2', '\n', '\020', 'd', 'e', 's',
+'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r',
+'\002', '\020', '\001', 'R', '\017', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'V', 'a', 'l', 'u', 'e', '\022', '=', '\n', '\014', 'e',
+'x', 'p', 'e', 'c', 't', '_', 'm', 'a', 't', 'c', 'h', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l',
+'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', '\013', 'e', 'x', 'p',
+'e', 'c', 't', 'M', 'a', 't', 'c', 'h', '\022', 'a', '\n', '\020', 'q', 'u', 'e', 'r', 'y', '_', 'p', 'a', 'r', 'a', 'm', 'e', 't',
+'e', 'r', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', ',', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.',
+'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'Q', 'u', 'e', 'r', 'y', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 'M', 'a',
+'t', 'c', 'h', 'e', 'r', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\017', 'q', 'u', 'e', 'r', 'y', 'P', 'a', 'r',
+'a', 'm', 'e', 't', 'e', 'r', 's', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i',
+'.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'A', 'c', 't', 'i', 'o',
+'n', 'B', '\027', '\n', '\020', 'a', 'c', 't', 'i', 'o', 'n', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B',
+'\001', '\032', '\362', '\001', '\n', '\010', 'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '\022', 'f', '\n', '\020', 'd', 'y', 'n', 'a', 'm', 'i', 'c',
+'_', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\001', ' ', '\001', '(', '\013', '2', '9', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c',
+'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.',
+'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'H',
+'\000', 'R', '\017', 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', '\032', 'c', '\n', '\017', 'D', 'y', 'n',
+'a', 'm', 'i', 'c', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', 'P', '\n', '\014', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_',
+'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'e',
+'t', 'a', 'd', 'a', 't', 'a', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', 'B', '\010', '\372', 'B',
+'\005', '\212', '\001', '\002', '\020', '\001', 'R', '\013', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', 'K', 'e', 'y', 'B', '\031', '\n', '\022', 'o', 'v',
+'e', 'r', 'r', 'i', 'd', 'e', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', ':', '#', '\232', '\305',
+'\210', '\036', '\036', '\n', '\034', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'R',
+'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '\"', '\346', '\005', '\n', '\r', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e',
+'r', '\022', '!', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\r', '\372', 'B', '\n', 'r', '\010', '\020', '\001', '\300',
+'\001', '\001', '\310', '\001', '\000', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '.', '\n', '\013', 'e', 'x', 'a', 'c', 't', '_', 'm', 'a', 't', 'c',
+'h', '\030', '\004', ' ', '\001', '(', '\t', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\n', 'e',
+'x', 'a', 'c', 't', 'M', 'a', 't', 'c', 'h', '\022', '\\', '\n', '\020', 's', 'a', 'f', 'e', '_', 'r', 'e', 'g', 'e', 'x', '_', 'm',
+'a', 't', 'c', 'h', '\030', '\013', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm',
+'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'R', 'e', 'g', 'e', 'x', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '\013', '\030',
+'\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\016', 's', 'a', 'f', 'e', 'R', 'e', 'g', 'e', 'x', 'M', 'a',
+'t', 'c', 'h', '\022', '<', '\n', '\013', 'r', 'a', 'n', 'g', 'e', '_', 'm', 'a', 't', 'c', 'h', '\030', '\006', ' ', '\001', '(', '\013', '2',
+'\031', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'I', 'n', 't', '6', '4', 'R', 'a', 'n', 'g',
+'e', 'H', '\000', 'R', '\n', 'r', 'a', 'n', 'g', 'e', 'M', 'a', 't', 'c', 'h', '\022', '%', '\n', '\r', 'p', 'r', 'e', 's', 'e', 'n',
+'t', '_', 'm', 'a', 't', 'c', 'h', '\030', '\007', ' ', '\001', '(', '\010', 'H', '\000', 'R', '\014', 'p', 'r', 'e', 's', 'e', 'n', 't', 'M',
+'a', 't', 'c', 'h', '\022', '7', '\n', '\014', 'p', 'r', 'e', 'f', 'i', 'x', '_', 'm', 'a', 't', 'c', 'h', '\030', '\t', ' ', '\001', '(',
+'\t', 'B', '\022', '\030', '\001', '\372', 'B', '\004', 'r', '\002', '\020', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\013',
+'p', 'r', 'e', 'f', 'i', 'x', 'M', 'a', 't', 'c', 'h', '\022', '7', '\n', '\014', 's', 'u', 'f', 'f', 'i', 'x', '_', 'm', 'a', 't',
+'c', 'h', '\030', '\n', ' ', '\001', '(', '\t', 'B', '\022', '\030', '\001', '\372', 'B', '\004', 'r', '\002', '\020', '\001', '\222', '\307', '\206', '\330', '\004', '\003',
+'3', '.', '0', 'H', '\000', 'R', '\013', 's', 'u', 'f', 'f', 'i', 'x', 'M', 'a', 't', 'c', 'h', '\022', ';', '\n', '\016', 'c', 'o', 'n',
+'t', 'a', 'i', 'n', 's', '_', 'm', 'a', 't', 'c', 'h', '\030', '\014', ' ', '\001', '(', '\t', 'B', '\022', '\030', '\001', '\372', 'B', '\004', 'r',
+'\002', '\020', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '\r', 'c', 'o', 'n', 't', 'a', 'i', 'n', 's', 'M',
+'a', 't', 'c', 'h', '\022', 'I', '\n', '\014', 's', 't', 'r', 'i', 'n', 'g', '_', 'm', 'a', 't', 'c', 'h', '\030', '\r', ' ', '\001', '(',
+'\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3',
+'.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\013', 's', 't', 'r', 'i', 'n', 'g', 'M',
+'a', 't', 'c', 'h', '\022', '!', '\n', '\014', 'i', 'n', 'v', 'e', 'r', 't', '_', 'm', 'a', 't', 'c', 'h', '\030', '\010', ' ', '\001', '(',
+'\010', 'R', '\013', 'i', 'n', 'v', 'e', 'r', 't', 'M', 'a', 't', 'c', 'h', '\022', '@', '\n', '\035', 't', 'r', 'e', 'a', 't', '_', 'm',
+'i', 's', 's', 'i', 'n', 'g', '_', 'h', 'e', 'a', 'd', 'e', 'r', '_', 'a', 's', '_', 'e', 'm', 'p', 't', 'y', '\030', '\016', ' ',
+'\001', '(', '\010', 'R', '\031', 't', 'r', 'e', 'a', 't', 'M', 'i', 's', 's', 'i', 'n', 'g', 'H', 'e', 'a', 'd', 'e', 'r', 'A', 's',
+'E', 'm', 'p', 't', 'y', ':', '\'', '\232', '\305', '\210', '\036', '\"', '\n', ' ', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v',
+'2', '.', 'r', 'o', 'u', 't', 'e', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '\030', '\n', '\026',
+'h', 'e', 'a', 'd', 'e', 'r', '_', 'm', 'a', 't', 'c', 'h', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'J', '\004', '\010',
+'\002', '\020', '\003', 'J', '\004', '\010', '\003', '\020', '\004', 'J', '\004', '\010', '\005', '\020', '\006', 'R', '\013', 'r', 'e', 'g', 'e', 'x', '_', 'm', 'a',
+'t', 'c', 'h', '\"', '\241', '\002', '\n', '\025', 'Q', 'u', 'e', 'r', 'y', 'P', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', 'M', 'a', 't',
+'c', 'h', 'e', 'r', '\022', '\036', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\n', '\372', 'B', '\007', 'r', '\005',
+'\020', '\001', '(', '\200', '\010', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'S', '\n', '\014', 's', 't', 'r', 'i', 'n', 'g', '_', 'm', 'a', 't',
+'c', 'h', '\030', '\005', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't',
+'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '\010', '\372', 'B',
+'\005', '\212', '\001', '\002', '\020', '\001', 'H', '\000', 'R', '\013', 's', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', '\022', '%', '\n', '\r',
+'p', 'r', 'e', 's', 'e', 'n', 't', '_', 'm', 'a', 't', 'c', 'h', '\030', '\006', ' ', '\001', '(', '\010', 'H', '\000', 'R', '\014', 'p', 'r',
+'e', 's', 'e', 'n', 't', 'M', 'a', 't', 'c', 'h', ':', '/', '\232', '\305', '\210', '\036', '*', '\n', '(', 'e', 'n', 'v', 'o', 'y', '.',
+'a', 'p', 'i', '.', 'v', '2', '.', 'r', 'o', 'u', 't', 'e', '.', 'Q', 'u', 'e', 'r', 'y', 'P', 'a', 'r', 'a', 'm', 'e', 't',
+'e', 'r', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '!', '\n', '\037', 'q', 'u', 'e', 'r', 'y', '_', 'p', 'a', 'r', 'a', 'm', 'e',
+'t', 'e', 'r', '_', 'm', 'a', 't', 'c', 'h', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'J', '\004', '\010', '\003', '\020', '\004',
+'J', '\004', '\010', '\004', '\020', '\005', 'R', '\005', 'v', 'a', 'l', 'u', 'e', 'R', '\005', 'r', 'e', 'g', 'e', 'x', '\"', '\271', '\002', '\n', '\026',
+'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'R', '\n',
+'\026', 'm', 'a', 'x', '_', 'i', 'n', 't', 'e', 'r', 'n', 'a', 'l', '_', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', 's', '\030', '\001',
+' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I',
+'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '\024', 'm', 'a', 'x', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'R', 'e', 'd',
+'i', 'r', 'e', 'c', 't', 's', '\022', '@', '\n', '\027', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', '_', 'r', 'e', 's', 'p', 'o', 'n',
+'s', 'e', '_', 'c', 'o', 'd', 'e', 's', '\030', '\002', ' ', '\003', '(', '\r', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\020', '\005', 'R',
+'\025', 'r', 'e', 'd', 'i', 'r', 'e', 'c', 't', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'C', 'o', 'd', 'e', 's', '\022', 'J', '\n',
+'\n', 'p', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y',
+'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e',
+'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\n', 'p', 'r', 'e', 'd', 'i', 'c', 'a', 't', 'e', 's', '\022', '=',
+'\n', '\033', 'a', 'l', 'l', 'o', 'w', '_', 'c', 'r', 'o', 's', 's', '_', 's', 'c', 'h', 'e', 'm', 'e', '_', 'r', 'e', 'd', 'i',
+'r', 'e', 'c', 't', '\030', '\004', ' ', '\001', '(', '\010', 'R', '\030', 'a', 'l', 'l', 'o', 'w', 'C', 'r', 'o', 's', 's', 'S', 'c', 'h',
+'e', 'm', 'e', 'R', 'e', 'd', 'i', 'r', 'e', 'c', 't', '\"', 'y', '\n', '\014', 'F', 'i', 'l', 't', 'e', 'r', 'C', 'o', 'n', 'f',
+'i', 'g', '\022', ',', '\n', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g',
+'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\022', '\037',
+'\n', '\013', 'i', 's', '_', 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\n', 'i', 's', 'O', 'p',
+'t', 'i', 'o', 'n', 'a', 'l', '\022', '\032', '\n', '\010', 'd', 'i', 's', 'a', 'b', 'l', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\010', 'R',
+'\010', 'd', 'i', 's', 'a', 'b', 'l', 'e', 'd', 'B', '\213', '\001', '\n', '#', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o',
+'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', 'B',
+'\024', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', 's', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'D',
+'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-',
+'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i',
+'g', '/', 'r', 'o', 'u', 't', 'e', '/', 'v', '3', ';', 'r', 'o', 'u', 't', 'e', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020',
+'\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
};
static _upb_DefPool_Init *deps[21] = {
@@ -965,5 +968,5 @@ _upb_DefPool_Init envoy_config_route_v3_route_components_proto_upbdefinit = {
deps,
&envoy_config_route_v3_route_components_proto_upb_file_layout,
"envoy/config/route/v3/route_components.proto",
- UPB_STRINGVIEW_INIT(descriptor, 22618)
+ UPB_STRINGVIEW_INIT(descriptor, 22684)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/trace/v3/opentelemetry.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/trace/v3/opentelemetry.upbdefs.c
index 6c97587b4e..e94bf8f845 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/trace/v3/opentelemetry.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/trace/v3/opentelemetry.upbdefs.c
@@ -12,31 +12,28 @@
extern _upb_DefPool_Init envoy_config_core_v3_grpc_service_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
-extern _upb_DefPool_Init validate_validate_proto_upbdefinit;
-static const char descriptor[450] = {'\n', ')', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 't', 'r', 'a', 'c', 'e', '/', 'v', '3', '/', 'o',
+static const char descriptor[414] = {'\n', ')', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 't', 'r', 'a', 'c', 'e', '/', 'v', '3', '/', 'o',
'p', 'e', 'n', 't', 'e', 'l', 'e', 'm', 'e', 't', 'r', 'y', '.', 'p', 'r', 'o', 't', 'o', '\022', '\025', 'e', 'n', 'v', 'o', 'y',
'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 't', 'r', 'a', 'c', 'e', '.', 'v', '3', '\032', '\'', 'e', 'n', 'v', 'o', 'y', '/', 'c',
'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'g', 'r', 'p', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c',
'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's',
-'/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v',
-'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\210', '\001', '\n', '\023', 'O', 'p', 'e', 'n', 'T', 'e', 'l',
-'e', 'm', 'e', 't', 'r', 'y', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'N', '\n', '\014', 'g', 'r', 'p', 'c', '_', 's', 'e', 'r', 'v',
-'i', 'c', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '!', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.',
-'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'G', 'r', 'p', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'B', '\010', '\372', 'B', '\005', '\212',
-'\001', '\002', '\020', '\001', 'R', '\013', 'g', 'r', 'p', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', '\022', '!', '\n', '\014', 's', 'e', 'r', 'v',
-'i', 'c', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\013', 's', 'e', 'r', 'v', 'i', 'c', 'e', 'N', 'a',
-'m', 'e', 'B', '\211', '\001', '\n', '#', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o',
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 't', 'r', 'a', 'c', 'e', '.', 'v', '3', 'B', '\022', 'O', 'p', 'e', 'n', 't', 'e',
-'l', 'e', 'm', 'e', 't', 'r', 'y', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'D', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o',
-'m', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p',
-'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 't', 'r', 'a', 'c', 'e', '/', 'v',
-'3', ';', 't', 'r', 'a', 'c', 'e', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
+'/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\"', '~', '\n', '\023', 'O', 'p', 'e', 'n', 'T', 'e', 'l', 'e',
+'m', 'e', 't', 'r', 'y', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'D', '\n', '\014', 'g', 'r', 'p', 'c', '_', 's', 'e', 'r', 'v', 'i',
+'c', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '!', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c',
+'o', 'r', 'e', '.', 'v', '3', '.', 'G', 'r', 'p', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'R', '\013', 'g', 'r', 'p', 'c', 'S',
+'e', 'r', 'v', 'i', 'c', 'e', '\022', '!', '\n', '\014', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ',
+'\001', '(', '\t', 'R', '\013', 's', 'e', 'r', 'v', 'i', 'c', 'e', 'N', 'a', 'm', 'e', 'B', '\211', '\001', '\n', '#', 'i', 'o', '.', 'e',
+'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 't', 'r',
+'a', 'c', 'e', '.', 'v', '3', 'B', '\022', 'O', 'p', 'e', 'n', 't', 'e', 'l', 'e', 'm', 'e', 't', 'r', 'y', 'P', 'r', 'o', 't',
+'o', 'P', '\001', 'Z', 'D', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x',
+'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/',
+'c', 'o', 'n', 'f', 'i', 'g', '/', 't', 'r', 'a', 'c', 'e', '/', 'v', '3', ';', 't', 'r', 'a', 'c', 'e', 'v', '3', '\272', '\200',
+'\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
};
-static _upb_DefPool_Init *deps[4] = {
+static _upb_DefPool_Init *deps[3] = {
&envoy_config_core_v3_grpc_service_proto_upbdefinit,
&udpa_annotations_status_proto_upbdefinit,
- &validate_validate_proto_upbdefinit,
NULL
};
@@ -44,5 +41,5 @@ _upb_DefPool_Init envoy_config_trace_v3_opentelemetry_proto_upbdefinit = {
deps,
&envoy_config_trace_v3_opentelemetry_proto_upb_file_layout,
"envoy/config/trace/v3/opentelemetry.proto",
- UPB_STRINGVIEW_INIT(descriptor, 450)
+ UPB_STRINGVIEW_INIT(descriptor, 414)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c
index 3b587c2580..01f01caf9e 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c
@@ -31,7 +31,7 @@ extern _upb_DefPool_Init udpa_annotations_security_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_versioning_proto_upbdefinit;
extern _upb_DefPool_Init validate_validate_proto_upbdefinit;
-static const char descriptor[12553] = {'\n', 'Y', 'e', 'n', 'v', 'o', 'y', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '/', 'f', 'i', 'l', 't', 'e', 'r',
+static const char descriptor[12759] = {'\n', 'Y', 'e', 'n', 'v', 'o', 'y', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '/', 'f', 'i', 'l', 't', 'e', 'r',
's', '/', 'n', 'e', 't', 'w', 'o', 'r', 'k', '/', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n',
'_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '/', 'v', '3', '/', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i',
'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', ';', 'e', 'n', 'v', 'o', 'y', '.', 'e',
@@ -67,7 +67,7 @@ static const char descriptor[12553] = {'\n', 'Y', 'e', 'n', 'v', 'o', 'y', '/',
'\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's',
'.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/',
'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't',
-'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\360', ':', '\n', '\025', 'H', 't', 't', 'p',
+'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\276', '<', '\n', '\025', 'H', 't', 't', 'p',
'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '\022', '\205', '\001', '\n', '\n', 'c', 'o', 'd',
'e', 'c', '_', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', '\\', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't',
'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h',
@@ -152,7 +152,11 @@ static const char descriptor[12553] = {'\n', 'Y', 'e', 'n', 'v', 'o', 'y', '/',
's', 'e', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'C', '\n', '\n', 'a', 'c', 'c', 'e', 's', 's', '_', 'l', 'o', 'g', '\030', '\r',
' ', '\003', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'a', 'c', 'c', 'e', 's',
's', 'l', 'o', 'g', '.', 'v', '3', '.', 'A', 'c', 'c', 'e', 's', 's', 'L', 'o', 'g', 'R', '\t', 'a', 'c', 'c', 'e', 's', 's',
-'L', 'o', 'g', '\022', 'Q', '\n', '\022', 'u', 's', 'e', '_', 'r', 'e', 'm', 'o', 't', 'e', '_', 'a', 'd', 'd', 'r', 'e', 's', 's',
+'L', 'o', 'g', '\022', 'b', '\n', '\031', 'a', 'c', 'c', 'e', 's', 's', '_', 'l', 'o', 'g', '_', 'f', 'l', 'u', 's', 'h', '_', 'i',
+'n', 't', 'e', 'r', 'v', 'a', 'l', '\030', '6', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r',
+'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\014', '\372', 'B', '\t', '\252', '\001', '\006', '2', '\004',
+'\020', '\300', '\204', '=', 'R', '\026', 'a', 'c', 'c', 'e', 's', 's', 'L', 'o', 'g', 'F', 'l', 'u', 's', 'h', 'I', 'n', 't', 'e', 'r',
+'v', 'a', 'l', '\022', 'Q', '\n', '\022', 'u', 's', 'e', '_', 'r', 'e', 'm', 'o', 't', 'e', '_', 'a', 'd', 'd', 'r', 'e', 's', 's',
'\030', '\016', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.',
'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\212', '\223', '\267', '*', '\002', '\010', '\001', 'R', '\020', 'u', 's', 'e', 'R', 'e',
'm', 'o', 't', 'e', 'A', 'd', 'd', 'r', 'e', 's', 's', '\022', '/', '\n', '\024', 'x', 'f', 'f', '_', 'n', 'u', 'm', '_', 't', 'r',
@@ -264,276 +268,280 @@ static const char descriptor[12553] = {'\n', 'Y', 'e', 'n', 'v', 'o', 'y', '/',
'd', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '5',
'\n', '\027', 'a', 'p', 'p', 'e', 'n', 'd', '_', 'x', '_', 'f', 'o', 'r', 'w', 'a', 'r', 'd', 'e', 'd', '_', 'p', 'o', 'r', 't',
'\030', '3', ' ', '\001', '(', '\010', 'R', '\024', 'a', 'p', 'p', 'e', 'n', 'd', 'X', 'F', 'o', 'r', 'w', 'a', 'r', 'd', 'e', 'd', 'P',
-'o', 'r', 't', '\032', '\366', '\004', '\n', '\007', 'T', 'r', 'a', 'c', 'i', 'n', 'g', '\022', '?', '\n', '\017', 'c', 'l', 'i', 'e', 'n', 't',
-'_', 's', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '\026', '.', 'e', 'n', 'v', 'o', 'y', '.', 't',
-'y', 'p', 'e', '.', 'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\016', 'c', 'l', 'i', 'e', 'n', 't', 'S', 'a', 'm',
-'p', 'l', 'i', 'n', 'g', '\022', '?', '\n', '\017', 'r', 'a', 'n', 'd', 'o', 'm', '_', 's', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\030',
-'\004', ' ', '\001', '(', '\013', '2', '\026', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'P', 'e', 'r',
-'c', 'e', 'n', 't', 'R', '\016', 'r', 'a', 'n', 'd', 'o', 'm', 'S', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\022', 'A', '\n', '\020', 'o',
-'v', 'e', 'r', 'a', 'l', 'l', '_', 's', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\030', '\005', ' ', '\001', '(', '\013', '2', '\026', '.', 'e',
-'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\017', 'o', 'v', 'e',
-'r', 'a', 'l', 'l', 'S', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\022', '\030', '\n', '\007', 'v', 'e', 'r', 'b', 'o', 's', 'e', '\030', '\006',
-' ', '\001', '(', '\010', 'R', '\007', 'v', 'e', 'r', 'b', 'o', 's', 'e', '\022', 'K', '\n', '\023', 'm', 'a', 'x', '_', 'p', 'a', 't', 'h',
-'_', 't', 'a', 'g', '_', 'l', 'e', 'n', 'g', 't', 'h', '\030', '\007', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l',
-'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '\020', 'm',
-'a', 'x', 'P', 'a', 't', 'h', 'T', 'a', 'g', 'L', 'e', 'n', 'g', 't', 'h', '\022', 'A', '\n', '\013', 'c', 'u', 's', 't', 'o', 'm',
-'_', 't', 'a', 'g', 's', '\030', '\010', ' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.',
-'t', 'r', 'a', 'c', 'i', 'n', 'g', '.', 'v', '3', '.', 'C', 'u', 's', 't', 'o', 'm', 'T', 'a', 'g', 'R', '\n', 'c', 'u', 's',
-'t', 'o', 'm', 'T', 'a', 'g', 's', '\022', '?', '\n', '\010', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\030', '\t', ' ', '\001', '(', '\013',
-'2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 't', 'r', 'a', 'c', 'e', '.', 'v', '3', '.',
-'T', 'r', 'a', 'c', 'i', 'n', 'g', '.', 'H', 't', 't', 'p', 'R', '\010', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\"', '(', '\n',
-'\r', 'O', 'p', 'e', 'r', 'a', 't', 'i', 'o', 'n', 'N', 'a', 'm', 'e', '\022', '\013', '\n', '\007', 'I', 'N', 'G', 'R', 'E', 'S', 'S',
-'\020', '\000', '\022', '\n', '\n', '\006', 'E', 'G', 'R', 'E', 'S', 'S', '\020', '\001', ':', '[', '\232', '\305', '\210', '\036', 'V', '\n', 'T', 'e', 'n',
-'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k',
-'.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.',
-'v', '2', '.', 'H', 't', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '.',
-'T', 'r', 'a', 'c', 'i', 'n', 'g', 'J', '\004', '\010', '\001', '\020', '\002', 'J', '\004', '\010', '\002', '\020', '\003', 'R', '\016', 'o', 'p', 'e', 'r',
-'a', 't', 'i', 'o', 'n', '_', 'n', 'a', 'm', 'e', 'R', '\030', 'r', 'e', 'q', 'u', 'e', 's', 't', '_', 'h', 'e', 'a', 'd', 'e',
-'r', 's', '_', 'f', 'o', 'r', '_', 't', 'a', 'g', 's', '\032', '\347', '\001', '\n', '\025', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'A',
-'d', 'd', 'r', 'e', 's', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '!', '\n', '\014', 'u', 'n', 'i', 'x', '_', 's', 'o', 'c', 'k',
-'e', 't', 's', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\013', 'u', 'n', 'i', 'x', 'S', 'o', 'c', 'k', 'e', 't', 's', '\022', '@', '\n',
-'\013', 'c', 'i', 'd', 'r', '_', 'r', 'a', 'n', 'g', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o',
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g',
-'e', 'R', '\n', 'c', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 's', ':', 'i', '\232', '\305', '\210', '\036', 'd', '\n', 'b', 'e', 'n', 'v',
-'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.',
-'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v',
-'2', '.', 'H', 't', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'I',
-'n', 't', 'e', 'r', 'n', 'a', 'l', 'A', 'd', 'd', 'r', 'e', 's', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\230', '\002', '\n', '\033',
-'S', 'e', 't', 'C', 'u', 'r', 'r', 'e', 'n', 't', 'C', 'l', 'i', 'e', 'n', 't', 'C', 'e', 'r', 't', 'D', 'e', 't', 'a', 'i',
-'l', 's', '\022', '4', '\n', '\007', 's', 'u', 'b', 'j', 'e', 'c', 't', '\030', '\001', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o',
-'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', '\007', 's',
-'u', 'b', 'j', 'e', 'c', 't', '\022', '\022', '\n', '\004', 'c', 'e', 'r', 't', '\030', '\003', ' ', '\001', '(', '\010', 'R', '\004', 'c', 'e', 'r',
-'t', '\022', '\024', '\n', '\005', 'c', 'h', 'a', 'i', 'n', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\005', 'c', 'h', 'a', 'i', 'n', '\022', '\020',
-'\n', '\003', 'd', 'n', 's', '\030', '\004', ' ', '\001', '(', '\010', 'R', '\003', 'd', 'n', 's', '\022', '\020', '\n', '\003', 'u', 'r', 'i', '\030', '\005',
-' ', '\001', '(', '\010', 'R', '\003', 'u', 'r', 'i', ':', 'o', '\232', '\305', '\210', '\036', 'j', '\n', 'h', 'e', 'n', 'v', 'o', 'y', '.', 'c',
-'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p',
-'_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'H', 't',
-'t', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'S', 'e', 't', 'C', 'u',
-'r', 'r', 'e', 'n', 't', 'C', 'l', 'i', 'e', 'n', 't', 'C', 'e', 'r', 't', 'D', 'e', 't', 'a', 'i', 'l', 's', 'J', '\004', '\010',
-'\002', '\020', '\003', '\032', '\256', '\002', '\n', '\r', 'U', 'p', 'g', 'r', 'a', 'd', 'e', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '!', '\n', '\014',
-'u', 'p', 'g', 'r', 'a', 'd', 'e', '_', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 'u', 'p', 'g', 'r', 'a',
-'d', 'e', 'T', 'y', 'p', 'e', '\022', 'a', '\n', '\007', 'f', 'i', 'l', 't', 'e', 'r', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', 'G',
+'o', 'r', 't', '\022', 'h', '\n', '#', 'a', 'd', 'd', '_', 'p', 'r', 'o', 'x', 'y', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l',
+'_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 's', 't', 'a', 't', 'e', '\030', '5', ' ', '\001', '(', '\013', '2', '\032',
+'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u',
+'e', 'R', '\037', 'a', 'd', 'd', 'P', 'r', 'o', 'x', 'y', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 'C', 'o', 'n', 'n', 'e', 'c',
+'t', 'i', 'o', 'n', 'S', 't', 'a', 't', 'e', '\032', '\366', '\004', '\n', '\007', 'T', 'r', 'a', 'c', 'i', 'n', 'g', '\022', '?', '\n', '\017',
+'c', 'l', 'i', 'e', 'n', 't', '_', 's', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '\026', '.', 'e',
+'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\016', 'c', 'l', 'i',
+'e', 'n', 't', 'S', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\022', '?', '\n', '\017', 'r', 'a', 'n', 'd', 'o', 'm', '_', 's', 'a', 'm',
+'p', 'l', 'i', 'n', 'g', '\030', '\004', ' ', '\001', '(', '\013', '2', '\026', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.',
+'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\016', 'r', 'a', 'n', 'd', 'o', 'm', 'S', 'a', 'm', 'p', 'l', 'i', 'n',
+'g', '\022', 'A', '\n', '\020', 'o', 'v', 'e', 'r', 'a', 'l', 'l', '_', 's', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\030', '\005', ' ', '\001',
+'(', '\013', '2', '\026', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n',
+'t', 'R', '\017', 'o', 'v', 'e', 'r', 'a', 'l', 'l', 'S', 'a', 'm', 'p', 'l', 'i', 'n', 'g', '\022', '\030', '\n', '\007', 'v', 'e', 'r',
+'b', 'o', 's', 'e', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\007', 'v', 'e', 'r', 'b', 'o', 's', 'e', '\022', 'K', '\n', '\023', 'm', 'a',
+'x', '_', 'p', 'a', 't', 'h', '_', 't', 'a', 'g', '_', 'l', 'e', 'n', 'g', 't', 'h', '\030', '\007', ' ', '\001', '(', '\013', '2', '\034',
+'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a',
+'l', 'u', 'e', 'R', '\020', 'm', 'a', 'x', 'P', 'a', 't', 'h', 'T', 'a', 'g', 'L', 'e', 'n', 'g', 't', 'h', '\022', 'A', '\n', '\013',
+'c', 'u', 's', 't', 'o', 'm', '_', 't', 'a', 'g', 's', '\030', '\010', ' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y',
+'.', 't', 'y', 'p', 'e', '.', 't', 'r', 'a', 'c', 'i', 'n', 'g', '.', 'v', '3', '.', 'C', 'u', 's', 't', 'o', 'm', 'T', 'a',
+'g', 'R', '\n', 'c', 'u', 's', 't', 'o', 'm', 'T', 'a', 'g', 's', '\022', '?', '\n', '\010', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r',
+'\030', '\t', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 't', 'r', 'a',
+'c', 'e', '.', 'v', '3', '.', 'T', 'r', 'a', 'c', 'i', 'n', 'g', '.', 'H', 't', 't', 'p', 'R', '\010', 'p', 'r', 'o', 'v', 'i',
+'d', 'e', 'r', '\"', '(', '\n', '\r', 'O', 'p', 'e', 'r', 'a', 't', 'i', 'o', 'n', 'N', 'a', 'm', 'e', '\022', '\013', '\n', '\007', 'I',
+'N', 'G', 'R', 'E', 'S', 'S', '\020', '\000', '\022', '\n', '\n', '\006', 'E', 'G', 'R', 'E', 'S', 'S', '\020', '\001', ':', '[', '\232', '\305', '\210',
+'\036', 'V', '\n', 'T', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n',
+'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a',
+'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'H', 't', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a',
+'n', 'a', 'g', 'e', 'r', '.', 'T', 'r', 'a', 'c', 'i', 'n', 'g', 'J', '\004', '\010', '\001', '\020', '\002', 'J', '\004', '\010', '\002', '\020', '\003',
+'R', '\016', 'o', 'p', 'e', 'r', 'a', 't', 'i', 'o', 'n', '_', 'n', 'a', 'm', 'e', 'R', '\030', 'r', 'e', 'q', 'u', 'e', 's', 't',
+'_', 'h', 'e', 'a', 'd', 'e', 'r', 's', '_', 'f', 'o', 'r', '_', 't', 'a', 'g', 's', '\032', '\347', '\001', '\n', '\025', 'I', 'n', 't',
+'e', 'r', 'n', 'a', 'l', 'A', 'd', 'd', 'r', 'e', 's', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '!', '\n', '\014', 'u', 'n', 'i',
+'x', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\013', 'u', 'n', 'i', 'x', 'S', 'o', 'c', 'k',
+'e', 't', 's', '\022', '@', '\n', '\013', 'c', 'i', 'd', 'r', '_', 'r', 'a', 'n', 'g', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2',
+'\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i',
+'d', 'r', 'R', 'a', 'n', 'g', 'e', 'R', '\n', 'c', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 's', ':', 'i', '\232', '\305', '\210', '\036',
+'d', '\n', 'b', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e',
+'t', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n',
+'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'H', 't', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n',
+'a', 'g', 'e', 'r', '.', 'I', 'n', 't', 'e', 'r', 'n', 'a', 'l', 'A', 'd', 'd', 'r', 'e', 's', 's', 'C', 'o', 'n', 'f', 'i',
+'g', '\032', '\230', '\002', '\n', '\033', 'S', 'e', 't', 'C', 'u', 'r', 'r', 'e', 'n', 't', 'C', 'l', 'i', 'e', 'n', 't', 'C', 'e', 'r',
+'t', 'D', 'e', 't', 'a', 'i', 'l', 's', '\022', '4', '\n', '\007', 's', 'u', 'b', 'j', 'e', 'c', 't', '\030', '\001', ' ', '\001', '(', '\013',
+'2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a',
+'l', 'u', 'e', 'R', '\007', 's', 'u', 'b', 'j', 'e', 'c', 't', '\022', '\022', '\n', '\004', 'c', 'e', 'r', 't', '\030', '\003', ' ', '\001', '(',
+'\010', 'R', '\004', 'c', 'e', 'r', 't', '\022', '\024', '\n', '\005', 'c', 'h', 'a', 'i', 'n', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\005', 'c',
+'h', 'a', 'i', 'n', '\022', '\020', '\n', '\003', 'd', 'n', 's', '\030', '\004', ' ', '\001', '(', '\010', 'R', '\003', 'd', 'n', 's', '\022', '\020', '\n',
+'\003', 'u', 'r', 'i', '\030', '\005', ' ', '\001', '(', '\010', 'R', '\003', 'u', 'r', 'i', ':', 'o', '\232', '\305', '\210', '\036', 'j', '\n', 'h', 'e',
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r',
+'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r',
+'.', 'v', '2', '.', 'H', 't', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e', 'r',
+'.', 'S', 'e', 't', 'C', 'u', 'r', 'r', 'e', 'n', 't', 'C', 'l', 'i', 'e', 'n', 't', 'C', 'e', 'r', 't', 'D', 'e', 't', 'a',
+'i', 'l', 's', 'J', '\004', '\010', '\002', '\020', '\003', '\032', '\256', '\002', '\n', '\r', 'U', 'p', 'g', 'r', 'a', 'd', 'e', 'C', 'o', 'n', 'f',
+'i', 'g', '\022', '!', '\n', '\014', 'u', 'p', 'g', 'r', 'a', 'd', 'e', '_', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R',
+'\013', 'u', 'p', 'g', 'r', 'a', 'd', 'e', 'T', 'y', 'p', 'e', '\022', 'a', '\n', '\007', 'f', 'i', 'l', 't', 'e', 'r', 's', '\030', '\002',
+' ', '\003', '(', '\013', '2', 'G', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f',
+'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e',
+'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '3', '.', 'H', 't', 't', 'p', 'F', 'i', 'l', 't',
+'e', 'r', 'R', '\007', 'f', 'i', 'l', 't', 'e', 'r', 's', '\022', '4', '\n', '\007', 'e', 'n', 'a', 'b', 'l', 'e', 'd', '\030', '\003', ' ',
+'\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o',
+'l', 'V', 'a', 'l', 'u', 'e', 'R', '\007', 'e', 'n', 'a', 'b', 'l', 'e', 'd', ':', 'a', '\232', '\305', '\210', '\036', '\\', '\n', 'Z', 'e',
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r',
+'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r',
+'.', 'v', '2', '.', 'H', 't', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e', 'r',
+'.', 'U', 'p', 'g', 'r', 'a', 'd', 'e', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\345', '\001', '\n', '\030', 'P', 'a', 't', 'h', 'N', 'o',
+'r', 'm', 'a', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'c', '\n', '\031', 'f', 'o', 'r',
+'w', 'a', 'r', 'd', 'i', 'n', 'g', '_', 't', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\030', '\001', ' ',
+'\001', '(', '\013', '2', '&', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'h', 't', 't', 'p', '.', 'v', '3', '.',
+'P', 'a', 't', 'h', 'T', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', 'R', '\030', 'f', 'o', 'r', 'w', 'a',
+'r', 'd', 'i', 'n', 'g', 'T', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\022', 'd', '\n', '\032', 'h', 't',
+'t', 'p', '_', 'f', 'i', 'l', 't', 'e', 'r', '_', 't', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\030',
+'\002', ' ', '\001', '(', '\013', '2', '&', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'h', 't', 't', 'p', '.', 'v',
+'3', '.', 'P', 'a', 't', 'h', 'T', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', 'R', '\030', 'h', 't', 't',
+'p', 'F', 'i', 'l', 't', 'e', 'r', 'T', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\032', '\344', '\002', '\n',
+'\021', 'P', 'r', 'o', 'x', 'y', 'S', 't', 'a', 't', 'u', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '%', '\n', '\016', 'r', 'e', 'm',
+'o', 'v', 'e', '_', 'd', 'e', 't', 'a', 'i', 'l', 's', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\r', 'r', 'e', 'm', 'o', 'v', 'e',
+'D', 'e', 't', 'a', 'i', 'l', 's', '\022', 'Q', '\n', '%', 'r', 'e', 'm', 'o', 'v', 'e', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't',
+'i', 'o', 'n', '_', 't', 'e', 'r', 'm', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'd', 'e', 't', 'a', 'i', 'l', 's', '\030', '\002',
+' ', '\001', '(', '\010', 'R', '\"', 'r', 'e', 'm', 'o', 'v', 'e', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'T', 'e', 'r',
+'m', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'D', 'e', 't', 'a', 'i', 'l', 's', '\022', '2', '\n', '\025', 'r', 'e', 'm', 'o', 'v', 'e',
+'_', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 'f', 'l', 'a', 'g', 's', '\030', '\003', ' ', '\001', '(', '\010', 'R', '\023', 'r', 'e',
+'m', 'o', 'v', 'e', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'F', 'l', 'a', 'g', 's', '\022', 'A', '\n', '\035', 's', 'e', 't', '_',
+'r', 'e', 'c', 'o', 'm', 'm', 'e', 'n', 'd', 'e', 'd', '_', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 'c', 'o', 'd', 'e',
+'\030', '\004', ' ', '\001', '(', '\010', 'R', '\032', 's', 'e', 't', 'R', 'e', 'c', 'o', 'm', 'm', 'e', 'n', 'd', 'e', 'd', 'R', 'e', 's',
+'p', 'o', 'n', 's', 'e', 'C', 'o', 'd', 'e', '\022', ' ', '\n', '\013', 'u', 's', 'e', '_', 'n', 'o', 'd', 'e', '_', 'i', 'd', '\030',
+'\005', ' ', '\001', '(', '\010', 'H', '\000', 'R', '\t', 'u', 's', 'e', 'N', 'o', 'd', 'e', 'I', 'd', '\022', '.', '\n', '\022', 'l', 'i', 't',
+'e', 'r', 'a', 'l', '_', 'p', 'r', 'o', 'x', 'y', '_', 'n', 'a', 'm', 'e', '\030', '\006', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\020',
+'l', 'i', 't', 'e', 'r', 'a', 'l', 'P', 'r', 'o', 'x', 'y', 'N', 'a', 'm', 'e', 'B', '\014', '\n', '\n', 'p', 'r', 'o', 'x', 'y',
+'_', 'n', 'a', 'm', 'e', '\"', '6', '\n', '\t', 'C', 'o', 'd', 'e', 'c', 'T', 'y', 'p', 'e', '\022', '\010', '\n', '\004', 'A', 'U', 'T',
+'O', '\020', '\000', '\022', '\t', '\n', '\005', 'H', 'T', 'T', 'P', '1', '\020', '\001', '\022', '\t', '\n', '\005', 'H', 'T', 'T', 'P', '2', '\020', '\002',
+'\022', '\t', '\n', '\005', 'H', 'T', 'T', 'P', '3', '\020', '\003', '\"', 'S', '\n', '\032', 'S', 'e', 'r', 'v', 'e', 'r', 'H', 'e', 'a', 'd',
+'e', 'r', 'T', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\022', '\r', '\n', '\t', 'O', 'V', 'E', 'R', 'W',
+'R', 'I', 'T', 'E', '\020', '\000', '\022', '\024', '\n', '\020', 'A', 'P', 'P', 'E', 'N', 'D', '_', 'I', 'F', '_', 'A', 'B', 'S', 'E', 'N',
+'T', '\020', '\001', '\022', '\020', '\n', '\014', 'P', 'A', 'S', 'S', '_', 'T', 'H', 'R', 'O', 'U', 'G', 'H', '\020', '\002', '\"', 'y', '\n', '\030',
+'F', 'o', 'r', 'w', 'a', 'r', 'd', 'C', 'l', 'i', 'e', 'n', 't', 'C', 'e', 'r', 't', 'D', 'e', 't', 'a', 'i', 'l', 's', '\022',
+'\014', '\n', '\010', 'S', 'A', 'N', 'I', 'T', 'I', 'Z', 'E', '\020', '\000', '\022', '\020', '\n', '\014', 'F', 'O', 'R', 'W', 'A', 'R', 'D', '_',
+'O', 'N', 'L', 'Y', '\020', '\001', '\022', '\022', '\n', '\016', 'A', 'P', 'P', 'E', 'N', 'D', '_', 'F', 'O', 'R', 'W', 'A', 'R', 'D', '\020',
+'\002', '\022', '\020', '\n', '\014', 'S', 'A', 'N', 'I', 'T', 'I', 'Z', 'E', '_', 'S', 'E', 'T', '\020', '\003', '\022', '\027', '\n', '\023', 'A', 'L',
+'W', 'A', 'Y', 'S', '_', 'F', 'O', 'R', 'W', 'A', 'R', 'D', '_', 'O', 'N', 'L', 'Y', '\020', '\004', '\"', '\240', '\001', '\n', '\034', 'P',
+'a', 't', 'h', 'W', 'i', 't', 'h', 'E', 's', 'c', 'a', 'p', 'e', 'd', 'S', 'l', 'a', 's', 'h', 'e', 's', 'A', 'c', 't', 'i',
+'o', 'n', '\022', '#', '\n', '\037', 'I', 'M', 'P', 'L', 'E', 'M', 'E', 'N', 'T', 'A', 'T', 'I', 'O', 'N', '_', 'S', 'P', 'E', 'C',
+'I', 'F', 'I', 'C', '_', 'D', 'E', 'F', 'A', 'U', 'L', 'T', '\020', '\000', '\022', '\022', '\n', '\016', 'K', 'E', 'E', 'P', '_', 'U', 'N',
+'C', 'H', 'A', 'N', 'G', 'E', 'D', '\020', '\001', '\022', '\022', '\n', '\016', 'R', 'E', 'J', 'E', 'C', 'T', '_', 'R', 'E', 'Q', 'U', 'E',
+'S', 'T', '\020', '\002', '\022', '\031', '\n', '\025', 'U', 'N', 'E', 'S', 'C', 'A', 'P', 'E', '_', 'A', 'N', 'D', '_', 'R', 'E', 'D', 'I',
+'R', 'E', 'C', 'T', '\020', '\003', '\022', '\030', '\n', '\024', 'U', 'N', 'E', 'S', 'C', 'A', 'P', 'E', '_', 'A', 'N', 'D', '_', 'F', 'O',
+'R', 'W', 'A', 'R', 'D', '\020', '\004', ':', 'S', '\232', '\305', '\210', '\036', 'N', '\n', 'L', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n',
+'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c',
+'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'H', 't', 't', 'p',
+'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e', 'r', 'B', '\026', '\n', '\017', 'r', 'o', 'u', 't',
+'e', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', 'B', '\021', '\n', '\017', 's', 't', 'r', 'i', 'p',
+'_', 'p', 'o', 'r', 't', '_', 'm', 'o', 'd', 'e', 'J', '\004', '\010', '\033', '\020', '\034', 'J', '\004', '\010', '\013', '\020', '\014', 'R', '\014', 'i',
+'d', 'l', 'e', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\"', '\312', '\001', '\n', '\020', 'L', 'o', 'c', 'a', 'l', 'R', 'e', 'p', 'l',
+'y', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'e', '\n', '\007', 'm', 'a', 'p', 'p', 'e', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2',
+'K', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r',
+'s', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n',
+'_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '3', '.', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'M', 'a', 'p', 'p', 'e',
+'r', 'R', '\007', 'm', 'a', 'p', 'p', 'e', 'r', 's', '\022', 'O', '\n', '\013', 'b', 'o', 'd', 'y', '_', 'f', 'o', 'r', 'm', 'a', 't',
+'\030', '\002', ' ', '\001', '(', '\013', '2', '.', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r',
+'e', '.', 'v', '3', '.', 'S', 'u', 'b', 's', 't', 'i', 't', 'u', 't', 'i', 'o', 'n', 'F', 'o', 'r', 'm', 'a', 't', 'S', 't',
+'r', 'i', 'n', 'g', 'R', '\n', 'b', 'o', 'd', 'y', 'F', 'o', 'r', 'm', 'a', 't', '\"', '\234', '\003', '\n', '\016', 'R', 'e', 's', 'p',
+'o', 'n', 's', 'e', 'M', 'a', 'p', 'p', 'e', 'r', '\022', 'L', '\n', '\006', 'f', 'i', 'l', 't', 'e', 'r', '\030', '\001', ' ', '\001', '(',
+'\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'a', 'c', 'c', 'e', 's', 's', 'l', 'o',
+'g', '.', 'v', '3', '.', 'A', 'c', 'c', 'e', 's', 's', 'L', 'o', 'g', 'F', 'i', 'l', 't', 'e', 'r', 'B', '\010', '\372', 'B', '\005',
+'\212', '\001', '\002', '\020', '\001', 'R', '\006', 'f', 'i', 'l', 't', 'e', 'r', '\022', 'J', '\n', '\013', 's', 't', 'a', 't', 'u', 's', '_', 'c',
+'o', 'd', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b',
+'u', 'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\013', '\372', 'B', '\010', '*', '\006', '\020', '\330', '\004', '(',
+'\310', '\001', 'R', '\n', 's', 't', 'a', 't', 'u', 's', 'C', 'o', 'd', 'e', '\022', '4', '\n', '\004', 'b', 'o', 'd', 'y', '\030', '\003', ' ',
+'\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v',
+'3', '.', 'D', 'a', 't', 'a', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\004', 'b', 'o', 'd', 'y', '\022', '`', '\n', '\024', 'b', 'o', 'd',
+'y', '_', 'f', 'o', 'r', 'm', 'a', 't', '_', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '.',
+'.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'S', 'u', 'b',
+'s', 't', 'i', 't', 'u', 't', 'i', 'o', 'n', 'F', 'o', 'r', 'm', 'a', 't', 'S', 't', 'r', 'i', 'n', 'g', 'R', '\022', 'b', 'o',
+'d', 'y', 'F', 'o', 'r', 'm', 'a', 't', 'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '\022', 'X', '\n', '\016', 'h', 'e', 'a', 'd', 'e',
+'r', 's', '_', 't', 'o', '_', 'a', 'd', 'd', '\030', '\005', ' ', '\003', '(', '\013', '2', '\'', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c',
+'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e',
+'O', 'p', 't', 'i', 'o', 'n', 'B', '\t', '\372', 'B', '\006', '\222', '\001', '\003', '\020', '\350', '\007', 'R', '\014', 'h', 'e', 'a', 'd', 'e', 'r',
+'s', 'T', 'o', 'A', 'd', 'd', '\"', '\307', '\001', '\n', '\003', 'R', 'd', 's', '\022', 'Q', '\n', '\r', 'c', 'o', 'n', 'f', 'i', 'g', '_',
+'s', 'o', 'u', 'r', 'c', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f',
+'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'B', '\010',
+'\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\014', 'c', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', '\022', '*', '\n',
+'\021', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R',
+'\017', 'r', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 'N', 'a', 'm', 'e', ':', 'A', '\232', '\305', '\210', '\036', '<', '\n', ':',
+'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o',
+'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e',
+'r', '.', 'v', '2', '.', 'R', 'd', 's', '\"', '\367', '\001', '\n', '\035', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C',
+'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', 's', 'L', 'i', 's', 't', '\022', 'y', '\n', '\033', 's', 'c', 'o', 'p',
+'e', 'd', '_', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', 's', '\030', '\001',
+' ', '\003', '(', '\013', '2', '/', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e',
+'.', 'v', '3', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a', 't',
+'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\031', 's', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't',
+'e', 'C', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', 's', ':', '[', '\232', '\305', '\210', '\036', 'V', '\n', 'T', 'e',
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r',
+'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r',
+'.', 'v', '2', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a', 't',
+'i', 'o', 'n', 's', 'L', 'i', 's', 't', '\"', '\337', '\016', '\n', '\014', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's',
+'\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004',
+'n', 'a', 'm', 'e', '\022', '\217', '\001', '\n', '\021', 's', 'c', 'o', 'p', 'e', '_', 'k', 'e', 'y', '_', 'b', 'u', 'i', 'l', 'd', 'e',
+'r', '\030', '\002', ' ', '\001', '(', '\013', '2', 'Y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n',
+'s', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o',
+'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '3', '.', 'S', 'c', 'o', 'p', 'e',
+'d', 'R', 'o', 'u', 't', 'e', 's', '.', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', 'B', '\010',
+'\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\017', 's', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r',
+'\022', 'N', '\n', '\021', 'r', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '_', 's', 'o', 'u', 'r', 'c', 'e', '\030', '\003', ' ', '\001',
+'(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3',
+'.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\017', 'r', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'S',
+'o', 'u', 'r', 'c', 'e', '\022', '\245', '\001', '\n', ' ', 's', 'c', 'o', 'p', 'e', 'd', '_', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o',
+'n', 'f', 'i', 'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', 's', '_', 'l', 'i', 's', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', 'Z',
'.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's',
'.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_',
-'m', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '3', '.', 'H', 't', 't', 'p', 'F', 'i', 'l', 't', 'e', 'r', 'R', '\007', 'f', 'i',
-'l', 't', 'e', 'r', 's', '\022', '4', '\n', '\007', 'e', 'n', 'a', 'b', 'l', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\013', '2', '\032', '.',
-'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e',
-'R', '\007', 'e', 'n', 'a', 'b', 'l', 'e', 'd', ':', 'a', '\232', '\305', '\210', '\036', '\\', '\n', 'Z', 'e', 'n', 'v', 'o', 'y', '.', 'c',
-'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p',
-'_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'H', 't',
-'t', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'U', 'p', 'g', 'r', 'a',
-'d', 'e', 'C', 'o', 'n', 'f', 'i', 'g', '\032', '\345', '\001', '\n', '\030', 'P', 'a', 't', 'h', 'N', 'o', 'r', 'm', 'a', 'l', 'i', 'z',
-'a', 't', 'i', 'o', 'n', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'c', '\n', '\031', 'f', 'o', 'r', 'w', 'a', 'r', 'd', 'i', 'n',
-'g', '_', 't', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\013', '2', '&', '.',
-'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'h', 't', 't', 'p', '.', 'v', '3', '.', 'P', 'a', 't', 'h', 'T', 'r',
-'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', 'R', '\030', 'f', 'o', 'r', 'w', 'a', 'r', 'd', 'i', 'n', 'g', 'T',
-'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\022', 'd', '\n', '\032', 'h', 't', 't', 'p', '_', 'f', 'i', 'l',
-'t', 'e', 'r', '_', 't', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\013', '2',
-'&', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'h', 't', 't', 'p', '.', 'v', '3', '.', 'P', 'a', 't', 'h',
-'T', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', 'R', '\030', 'h', 't', 't', 'p', 'F', 'i', 'l', 't', 'e',
-'r', 'T', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\032', '\344', '\002', '\n', '\021', 'P', 'r', 'o', 'x', 'y',
-'S', 't', 'a', 't', 'u', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '%', '\n', '\016', 'r', 'e', 'm', 'o', 'v', 'e', '_', 'd', 'e',
-'t', 'a', 'i', 'l', 's', '\030', '\001', ' ', '\001', '(', '\010', 'R', '\r', 'r', 'e', 'm', 'o', 'v', 'e', 'D', 'e', 't', 'a', 'i', 'l',
-'s', '\022', 'Q', '\n', '%', 'r', 'e', 'm', 'o', 'v', 'e', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 't', 'e',
-'r', 'm', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'd', 'e', 't', 'a', 'i', 'l', 's', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\"',
-'r', 'e', 'm', 'o', 'v', 'e', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'T', 'e', 'r', 'm', 'i', 'n', 'a', 't', 'i',
-'o', 'n', 'D', 'e', 't', 'a', 'i', 'l', 's', '\022', '2', '\n', '\025', 'r', 'e', 'm', 'o', 'v', 'e', '_', 'r', 'e', 's', 'p', 'o',
-'n', 's', 'e', '_', 'f', 'l', 'a', 'g', 's', '\030', '\003', ' ', '\001', '(', '\010', 'R', '\023', 'r', 'e', 'm', 'o', 'v', 'e', 'R', 'e',
-'s', 'p', 'o', 'n', 's', 'e', 'F', 'l', 'a', 'g', 's', '\022', 'A', '\n', '\035', 's', 'e', 't', '_', 'r', 'e', 'c', 'o', 'm', 'm',
-'e', 'n', 'd', 'e', 'd', '_', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 'c', 'o', 'd', 'e', '\030', '\004', ' ', '\001', '(', '\010',
-'R', '\032', 's', 'e', 't', 'R', 'e', 'c', 'o', 'm', 'm', 'e', 'n', 'd', 'e', 'd', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'C',
-'o', 'd', 'e', '\022', ' ', '\n', '\013', 'u', 's', 'e', '_', 'n', 'o', 'd', 'e', '_', 'i', 'd', '\030', '\005', ' ', '\001', '(', '\010', 'H',
-'\000', 'R', '\t', 'u', 's', 'e', 'N', 'o', 'd', 'e', 'I', 'd', '\022', '.', '\n', '\022', 'l', 'i', 't', 'e', 'r', 'a', 'l', '_', 'p',
-'r', 'o', 'x', 'y', '_', 'n', 'a', 'm', 'e', '\030', '\006', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\020', 'l', 'i', 't', 'e', 'r', 'a',
-'l', 'P', 'r', 'o', 'x', 'y', 'N', 'a', 'm', 'e', 'B', '\014', '\n', '\n', 'p', 'r', 'o', 'x', 'y', '_', 'n', 'a', 'm', 'e', '\"',
-'6', '\n', '\t', 'C', 'o', 'd', 'e', 'c', 'T', 'y', 'p', 'e', '\022', '\010', '\n', '\004', 'A', 'U', 'T', 'O', '\020', '\000', '\022', '\t', '\n',
-'\005', 'H', 'T', 'T', 'P', '1', '\020', '\001', '\022', '\t', '\n', '\005', 'H', 'T', 'T', 'P', '2', '\020', '\002', '\022', '\t', '\n', '\005', 'H', 'T',
-'T', 'P', '3', '\020', '\003', '\"', 'S', '\n', '\032', 'S', 'e', 'r', 'v', 'e', 'r', 'H', 'e', 'a', 'd', 'e', 'r', 'T', 'r', 'a', 'n',
-'s', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', '\022', '\r', '\n', '\t', 'O', 'V', 'E', 'R', 'W', 'R', 'I', 'T', 'E', '\020', '\000',
-'\022', '\024', '\n', '\020', 'A', 'P', 'P', 'E', 'N', 'D', '_', 'I', 'F', '_', 'A', 'B', 'S', 'E', 'N', 'T', '\020', '\001', '\022', '\020', '\n',
-'\014', 'P', 'A', 'S', 'S', '_', 'T', 'H', 'R', 'O', 'U', 'G', 'H', '\020', '\002', '\"', 'y', '\n', '\030', 'F', 'o', 'r', 'w', 'a', 'r',
-'d', 'C', 'l', 'i', 'e', 'n', 't', 'C', 'e', 'r', 't', 'D', 'e', 't', 'a', 'i', 'l', 's', '\022', '\014', '\n', '\010', 'S', 'A', 'N',
-'I', 'T', 'I', 'Z', 'E', '\020', '\000', '\022', '\020', '\n', '\014', 'F', 'O', 'R', 'W', 'A', 'R', 'D', '_', 'O', 'N', 'L', 'Y', '\020', '\001',
-'\022', '\022', '\n', '\016', 'A', 'P', 'P', 'E', 'N', 'D', '_', 'F', 'O', 'R', 'W', 'A', 'R', 'D', '\020', '\002', '\022', '\020', '\n', '\014', 'S',
-'A', 'N', 'I', 'T', 'I', 'Z', 'E', '_', 'S', 'E', 'T', '\020', '\003', '\022', '\027', '\n', '\023', 'A', 'L', 'W', 'A', 'Y', 'S', '_', 'F',
-'O', 'R', 'W', 'A', 'R', 'D', '_', 'O', 'N', 'L', 'Y', '\020', '\004', '\"', '\240', '\001', '\n', '\034', 'P', 'a', 't', 'h', 'W', 'i', 't',
-'h', 'E', 's', 'c', 'a', 'p', 'e', 'd', 'S', 'l', 'a', 's', 'h', 'e', 's', 'A', 'c', 't', 'i', 'o', 'n', '\022', '#', '\n', '\037',
-'I', 'M', 'P', 'L', 'E', 'M', 'E', 'N', 'T', 'A', 'T', 'I', 'O', 'N', '_', 'S', 'P', 'E', 'C', 'I', 'F', 'I', 'C', '_', 'D',
-'E', 'F', 'A', 'U', 'L', 'T', '\020', '\000', '\022', '\022', '\n', '\016', 'K', 'E', 'E', 'P', '_', 'U', 'N', 'C', 'H', 'A', 'N', 'G', 'E',
-'D', '\020', '\001', '\022', '\022', '\n', '\016', 'R', 'E', 'J', 'E', 'C', 'T', '_', 'R', 'E', 'Q', 'U', 'E', 'S', 'T', '\020', '\002', '\022', '\031',
-'\n', '\025', 'U', 'N', 'E', 'S', 'C', 'A', 'P', 'E', '_', 'A', 'N', 'D', '_', 'R', 'E', 'D', 'I', 'R', 'E', 'C', 'T', '\020', '\003',
-'\022', '\030', '\n', '\024', 'U', 'N', 'E', 'S', 'C', 'A', 'P', 'E', '_', 'A', 'N', 'D', '_', 'F', 'O', 'R', 'W', 'A', 'R', 'D', '\020',
-'\004', ':', 'S', '\232', '\305', '\210', '\036', 'N', '\n', 'L', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i',
-'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't',
-'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'H', 't', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c',
-'t', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e', 'r', 'B', '\026', '\n', '\017', 'r', 'o', 'u', 't', 'e', '_', 's', 'p', 'e', 'c',
-'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', 'B', '\021', '\n', '\017', 's', 't', 'r', 'i', 'p', '_', 'p', 'o', 'r', 't', '_',
-'m', 'o', 'd', 'e', 'J', '\004', '\010', '\033', '\020', '\034', 'J', '\004', '\010', '\013', '\020', '\014', 'R', '\014', 'i', 'd', 'l', 'e', '_', 't', 'i',
-'m', 'e', 'o', 'u', 't', '\"', '\312', '\001', '\n', '\020', 'L', 'o', 'c', 'a', 'l', 'R', 'e', 'p', 'l', 'y', 'C', 'o', 'n', 'f', 'i',
-'g', '\022', 'e', '\n', '\007', 'm', 'a', 'p', 'p', 'e', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', 'K', '.', 'e', 'n', 'v', 'o',
+'m', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '3', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n',
+'f', 'i', 'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', 's', 'L', 'i', 's', 't', 'H', '\000', 'R', '\035', 's', 'c', 'o', 'p', 'e', 'd',
+'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', 's', 'L', 'i', 's', 't', '\022', 'g',
+'\n', '\n', 's', 'c', 'o', 'p', 'e', 'd', '_', 'r', 'd', 's', '\030', '\005', ' ', '\001', '(', '\013', '2', 'F', '.', 'e', 'n', 'v', 'o',
'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't', 'w',
'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g',
-'e', 'r', '.', 'v', '3', '.', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'M', 'a', 'p', 'p', 'e', 'r', 'R', '\007', 'm', 'a', 'p',
-'p', 'e', 'r', 's', '\022', 'O', '\n', '\013', 'b', 'o', 'd', 'y', '_', 'f', 'o', 'r', 'm', 'a', 't', '\030', '\002', ' ', '\001', '(', '\013',
-'2', '.', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'S',
-'u', 'b', 's', 't', 'i', 't', 'u', 't', 'i', 'o', 'n', 'F', 'o', 'r', 'm', 'a', 't', 'S', 't', 'r', 'i', 'n', 'g', 'R', '\n',
-'b', 'o', 'd', 'y', 'F', 'o', 'r', 'm', 'a', 't', '\"', '\234', '\003', '\n', '\016', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'M', 'a',
-'p', 'p', 'e', 'r', '\022', 'L', '\n', '\006', 'f', 'i', 'l', 't', 'e', 'r', '\030', '\001', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n',
-'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'a', 'c', 'c', 'e', 's', 's', 'l', 'o', 'g', '.', 'v', '3', '.', 'A',
-'c', 'c', 'e', 's', 's', 'L', 'o', 'g', 'F', 'i', 'l', 't', 'e', 'r', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R',
-'\006', 'f', 'i', 'l', 't', 'e', 'r', '\022', 'J', '\n', '\013', 's', 't', 'a', 't', 'u', 's', '_', 'c', 'o', 'd', 'e', '\030', '\002', ' ',
-'\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n',
-'t', '3', '2', 'V', 'a', 'l', 'u', 'e', 'B', '\013', '\372', 'B', '\010', '*', '\006', '\020', '\330', '\004', '(', '\310', '\001', 'R', '\n', 's', 't',
-'a', 't', 'u', 's', 'C', 'o', 'd', 'e', '\022', '4', '\n', '\004', 'b', 'o', 'd', 'y', '\030', '\003', ' ', '\001', '(', '\013', '2', ' ', '.',
-'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'D', 'a', 't', 'a',
-'S', 'o', 'u', 'r', 'c', 'e', 'R', '\004', 'b', 'o', 'd', 'y', '\022', '`', '\n', '\024', 'b', 'o', 'd', 'y', '_', 'f', 'o', 'r', 'm',
-'a', 't', '_', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '.', '.', 'e', 'n', 'v', 'o', 'y',
-'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'S', 'u', 'b', 's', 't', 'i', 't', 'u', 't',
-'i', 'o', 'n', 'F', 'o', 'r', 'm', 'a', 't', 'S', 't', 'r', 'i', 'n', 'g', 'R', '\022', 'b', 'o', 'd', 'y', 'F', 'o', 'r', 'm',
-'a', 't', 'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '\022', 'X', '\n', '\016', 'h', 'e', 'a', 'd', 'e', 'r', 's', '_', 't', 'o', '_',
-'a', 'd', 'd', '\030', '\005', ' ', '\003', '(', '\013', '2', '\'', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.',
-'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n',
-'B', '\t', '\372', 'B', '\006', '\222', '\001', '\003', '\020', '\350', '\007', 'R', '\014', 'h', 'e', 'a', 'd', 'e', 'r', 's', 'T', 'o', 'A', 'd', 'd',
-'\"', '\307', '\001', '\n', '\003', 'R', 'd', 's', '\022', 'Q', '\n', '\r', 'c', 'o', 'n', 'f', 'i', 'g', '_', 's', 'o', 'u', 'r', 'c', 'e',
-'\030', '\001', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r',
-'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002',
-'\020', '\001', 'R', '\014', 'c', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', '\022', '*', '\n', '\021', 'r', 'o', 'u', 't', 'e',
-'_', 'c', 'o', 'n', 'f', 'i', 'g', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\017', 'r', 'o', 'u', 't', 'e',
-'C', 'o', 'n', 'f', 'i', 'g', 'N', 'a', 'm', 'e', ':', 'A', '\232', '\305', '\210', '\036', '<', '\n', ':', 'e', 'n', 'v', 'o', 'y', '.',
-'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't',
-'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'R',
-'d', 's', '\"', '\367', '\001', '\n', '\035', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 'u',
-'r', 'a', 't', 'i', 'o', 'n', 's', 'L', 'i', 's', 't', '\022', 'y', '\n', '\033', 's', 'c', 'o', 'p', 'e', 'd', '_', 'r', 'o', 'u',
-'t', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '/',
-'.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'S', 'c',
-'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\010', '\372',
-'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\031', 's', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i',
-'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', 's', ':', '[', '\232', '\305', '\210', '\036', 'V', '\n', 'T', 'e', 'n', 'v', 'o', 'y', '.', 'c',
-'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p',
-'_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'S', 'c',
-'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', 's', 'L', 'i',
-'s', 't', '\"', '\337', '\016', '\n', '\014', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', '\022', '\033', '\n', '\004', 'n', 'a',
-'m', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\217',
-'\001', '\n', '\021', 's', 'c', 'o', 'p', 'e', '_', 'k', 'e', 'y', '_', 'b', 'u', 'i', 'l', 'd', 'e', 'r', '\030', '\002', ' ', '\001', '(',
-'\013', '2', 'Y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't',
-'e', 'r', 's', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i',
-'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '3', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e',
-'s', '.', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002',
-'\020', '\001', 'R', '\017', 's', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '\022', 'N', '\n', '\021', 'r', 'd',
-'s', '_', 'c', 'o', 'n', 'f', 'i', 'g', '_', 's', 'o', 'u', 'r', 'c', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '\"', '.', 'e',
-'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i',
-'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\017', 'r', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', '\022',
-'\245', '\001', '\n', ' ', 's', 'c', 'o', 'p', 'e', 'd', '_', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', 'u', 'r',
-'a', 't', 'i', 'o', 'n', 's', '_', 'l', 'i', 's', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', 'Z', '.', 'e', 'n', 'v', 'o', 'y',
-'.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't', 'w', 'o',
-'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e',
-'r', '.', 'v', '3', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a',
-'t', 'i', 'o', 'n', 's', 'L', 'i', 's', 't', 'H', '\000', 'R', '\035', 's', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C',
-'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', 's', 'L', 'i', 's', 't', '\022', 'g', '\n', '\n', 's', 'c', 'o', 'p',
-'e', 'd', '_', 'r', 'd', 's', '\030', '\005', ' ', '\001', '(', '\013', '2', 'F', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e',
-'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't',
-'t', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '3', '.',
-'S', 'c', 'o', 'p', 'e', 'd', 'R', 'd', 's', 'H', '\000', 'R', '\t', 's', 'c', 'o', 'p', 'e', 'd', 'R', 'd', 's', '\032', '\331', '\t',
-'\n', '\017', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '\022', '\221', '\001', '\n', '\t', 'f', 'r', 'a',
-'g', 'm', 'e', 'n', 't', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', 'i', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e',
-'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't',
-'t', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '3', '.',
-'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', '.', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l',
-'d', 'e', 'r', '.', 'F', 'r', 'a', 'g', 'm', 'e', 'n', 't', 'B', 'u', 'i', 'l', 'd', 'e', 'r', 'B', '\010', '\372', 'B', '\005', '\222',
-'\001', '\002', '\010', '\001', 'R', '\t', 'f', 'r', 'a', 'g', 'm', 'e', 'n', 't', 's', '\032', '\325', '\007', '\n', '\017', 'F', 'r', 'a', 'g', 'm',
-'e', 'n', 't', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '\022', '\266', '\001', '\n', '\026', 'h', 'e', 'a', 'd', 'e', 'r', '_', 'v', 'a', 'l',
-'u', 'e', '_', 'e', 'x', 't', 'r', 'a', 'c', 't', 'o', 'r', '\030', '\001', ' ', '\001', '(', '\013', '2', '~', '.', 'e', 'n', 'v', 'o',
+'e', 'r', '.', 'v', '3', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'd', 's', 'H', '\000', 'R', '\t', 's', 'c', 'o', 'p', 'e', 'd',
+'R', 'd', 's', '\032', '\331', '\t', '\n', '\017', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '\022', '\221',
+'\001', '\n', '\t', 'f', 'r', 'a', 'g', 'm', 'e', 'n', 't', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', 'i', '.', 'e', 'n', 'v', 'o',
'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't', 'w',
'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g',
'e', 'r', '.', 'v', '3', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', '.', 'S', 'c', 'o', 'p', 'e', 'K',
'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'F', 'r', 'a', 'g', 'm', 'e', 'n', 't', 'B', 'u', 'i', 'l', 'd', 'e', 'r',
-'.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'E', 'x', 't', 'r', 'a', 'c', 't', 'o', 'r', 'H', '\000', 'R', '\024',
-'h', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'E', 'x', 't', 'r', 'a', 'c', 't', 'o', 'r', '\032', '\217', '\005', '\n', '\024',
-'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'E', 'x', 't', 'r', 'a', 'c', 't', 'o', 'r', '\022', '\033', '\n', '\004', 'n',
-'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022',
-'+', '\n', '\021', 'e', 'l', 'e', 'm', 'e', 'n', 't', '_', 's', 'e', 'p', 'a', 'r', 'a', 't', 'o', 'r', '\030', '\002', ' ', '\001', '(',
-'\t', 'R', '\020', 'e', 'l', 'e', 'm', 'e', 'n', 't', 'S', 'e', 'p', 'a', 'r', 'a', 't', 'o', 'r', '\022', '\026', '\n', '\005', 'i', 'n',
-'d', 'e', 'x', '\030', '\003', ' ', '\001', '(', '\r', 'H', '\000', 'R', '\005', 'i', 'n', 'd', 'e', 'x', '\022', '\245', '\001', '\n', '\007', 'e', 'l',
-'e', 'm', 'e', 'n', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\210', '\001', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e',
-'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't',
-'t', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '3', '.',
-'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', '.', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l',
-'d', 'e', 'r', '.', 'F', 'r', 'a', 'g', 'm', 'e', 'n', 't', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'H', 'e', 'a', 'd', 'e',
-'r', 'V', 'a', 'l', 'u', 'e', 'E', 'x', 't', 'r', 'a', 'c', 't', 'o', 'r', '.', 'K', 'v', 'E', 'l', 'e', 'm', 'e', 'n', 't',
-'H', '\000', 'R', '\007', 'e', 'l', 'e', 'm', 'e', 'n', 't', '\032', '\333', '\001', '\n', '\t', 'K', 'v', 'E', 'l', 'e', 'm', 'e', 'n', 't',
-'\022', '%', '\n', '\t', 's', 'e', 'p', 'a', 'r', 'a', 't', 'o', 'r', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r',
-'\002', '\020', '\001', 'R', '\t', 's', 'e', 'p', 'a', 'r', 'a', 't', 'o', 'r', '\022', '\031', '\n', '\003', 'k', 'e', 'y', '\030', '\002', ' ', '\001',
-'(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\003', 'k', 'e', 'y', ':', '\213', '\001', '\232', '\305', '\210', '\036', '\205', '\001',
-'\n', '\202', '\001', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e',
-'t', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n',
-'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', '.', 'S', 'c', 'o', 'p',
-'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'F', 'r', 'a', 'g', 'm', 'e', 'n', 't', 'B', 'u', 'i', 'l', 'd',
-'e', 'r', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'E', 'x', 't', 'r', 'a', 'c', 't', 'o', 'r', '.', 'K',
-'v', 'E', 'l', 'e', 'm', 'e', 'n', 't', ':', '\177', '\232', '\305', '\210', '\036', 'z', '\n', 'x', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o',
-'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_',
-'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'S', 'c', 'o',
-'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', '.', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r',
-'.', 'F', 'r', 'a', 'g', 'm', 'e', 'n', 't', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a',
-'l', 'u', 'e', 'E', 'x', 't', 'r', 'a', 'c', 't', 'o', 'r', 'B', '\016', '\n', '\014', 'e', 'x', 't', 'r', 'a', 'c', 't', '_', 't',
-'y', 'p', 'e', ':', 'j', '\232', '\305', '\210', '\036', 'e', '\n', 'c', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.',
-'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e',
-'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o',
-'u', 't', 'e', 's', '.', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'F', 'r', 'a', 'g',
-'m', 'e', 'n', 't', 'B', 'u', 'i', 'l', 'd', 'e', 'r', 'B', '\013', '\n', '\004', 't', 'y', 'p', 'e', '\022', '\003', '\370', 'B', '\001', ':',
-'Z', '\232', '\305', '\210', '\036', 'U', '\n', 'S', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't',
-'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o',
-'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's',
-'.', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', ':', 'J', '\232', '\305', '\210', '\036', 'E', '\n', 'C',
-'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o',
-'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e',
-'r', '.', 'v', '2', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', 'B', '\027', '\n', '\020', 'c', 'o', 'n', 'f',
-'i', 'g', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', '\"', '\361', '\001', '\n', '\t', 'S', 'c', 'o',
-'p', 'e', 'd', 'R', 'd', 's', '\022', 'e', '\n', '\030', 's', 'c', 'o', 'p', 'e', 'd', '_', 'r', 'd', 's', '_', 'c', 'o', 'n', 'f',
-'i', 'g', '_', 's', 'o', 'u', 'r', 'c', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c',
-'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c',
-'e', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\025', 's', 'c', 'o', 'p', 'e', 'd', 'R', 'd', 's', 'C', 'o', 'n',
-'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', '\022', '4', '\n', '\026', 's', 'r', 'd', 's', '_', 'r', 'e', 's', 'o', 'u', 'r', 'c',
-'e', 's', '_', 'l', 'o', 'c', 'a', 't', 'o', 'r', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\024', 's', 'r', 'd', 's', 'R', 'e', 's',
-'o', 'u', 'r', 'c', 'e', 's', 'L', 'o', 'c', 'a', 't', 'o', 'r', ':', 'G', '\232', '\305', '\210', '\036', 'B', '\n', '@', 'e', 'n', 'v',
-'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.',
-'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v',
-'2', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'd', 's', '\"', '\314', '\002', '\n', '\n', 'H', 't', 't', 'p', 'F', 'i', 'l', 't', 'e',
+'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\t', 'f', 'r', 'a', 'g', 'm', 'e', 'n', 't', 's', '\032', '\325', '\007', '\n',
+'\017', 'F', 'r', 'a', 'g', 'm', 'e', 'n', 't', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '\022', '\266', '\001', '\n', '\026', 'h', 'e', 'a', 'd',
+'e', 'r', '_', 'v', 'a', 'l', 'u', 'e', '_', 'e', 'x', 't', 'r', 'a', 'c', 't', 'o', 'r', '\030', '\001', ' ', '\001', '(', '\013', '2',
+'~', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r',
+'s', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n',
+'_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '3', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', '.',
+'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'F', 'r', 'a', 'g', 'm', 'e', 'n', 't', 'B',
+'u', 'i', 'l', 'd', 'e', 'r', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'E', 'x', 't', 'r', 'a', 'c', 't',
+'o', 'r', 'H', '\000', 'R', '\024', 'h', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'E', 'x', 't', 'r', 'a', 'c', 't', 'o',
+'r', '\032', '\217', '\005', '\n', '\024', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'E', 'x', 't', 'r', 'a', 'c', 't', 'o',
'r', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R',
-'\004', 'n', 'a', 'm', 'e', '\022', '9', '\n', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\004', ' ', '\001',
-'(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'H',
-'\000', 'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'X', '\n', '\020', 'c', 'o', 'n', 'f', 'i', 'g', '_',
-'d', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', '\030', '\005', ' ', '\001', '(', '\013', '2', '+', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c',
-'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o',
-'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'H', '\000', 'R', '\017', 'c', 'o', 'n', 'f', 'i', 'g', 'D', 'i', 's', 'c', 'o',
-'v', 'e', 'r', 'y', '\022', '\037', '\n', '\013', 'i', 's', '_', 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l', '\030', '\006', ' ', '\001', '(', '\010',
-'R', '\n', 'i', 's', 'O', 'p', 't', 'i', 'o', 'n', 'a', 'l', ':', 'H', '\232', '\305', '\210', '\036', 'C', '\n', 'A', 'e', 'n', 'v', 'o',
-'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h',
-'t', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2',
-'.', 'H', 't', 't', 'p', 'F', 'i', 'l', 't', 'e', 'r', 'B', '\r', '\n', '\013', 'c', 'o', 'n', 'f', 'i', 'g', '_', 't', 'y', 'p',
-'e', 'J', '\004', '\010', '\003', '\020', '\004', 'J', '\004', '\010', '\002', '\020', '\003', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\"', '\237', '\001', '\n',
-'\022', 'R', 'e', 'q', 'u', 'e', 's', 't', 'I', 'D', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\022', '7', '\n', '\014', 't', 'y',
-'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e',
-'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i',
-'g', ':', 'P', '\232', '\305', '\210', '\036', 'K', '\n', 'I', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i',
-'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't',
-'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'R', 'e', 'q', 'u', 'e', 's', 't', 'I', 'D', 'E',
-'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\"', '\216', '\001', '\n', ' ', 'E', 'n', 'v', 'o', 'y', 'M', 'o', 'b', 'i', 'l', 'e', 'H',
-'t', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '\022', 'j', '\n', '\006', 'c',
-'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', 'R', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n',
-'s', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't',
-'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '3', '.', 'H',
-'t', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e', 'r', 'R', '\006', 'c', 'o', 'n',
-'f', 'i', 'g', 'B', '\357', '\001', '\n', 'I', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v',
-'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't',
+'\004', 'n', 'a', 'm', 'e', '\022', '+', '\n', '\021', 'e', 'l', 'e', 'm', 'e', 'n', 't', '_', 's', 'e', 'p', 'a', 'r', 'a', 't', 'o',
+'r', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\020', 'e', 'l', 'e', 'm', 'e', 'n', 't', 'S', 'e', 'p', 'a', 'r', 'a', 't', 'o', 'r',
+'\022', '\026', '\n', '\005', 'i', 'n', 'd', 'e', 'x', '\030', '\003', ' ', '\001', '(', '\r', 'H', '\000', 'R', '\005', 'i', 'n', 'd', 'e', 'x', '\022',
+'\245', '\001', '\n', '\007', 'e', 'l', 'e', 'm', 'e', 'n', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\210', '\001', '.', 'e', 'n', 'v', 'o',
+'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't', 'w',
+'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g',
+'e', 'r', '.', 'v', '3', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', '.', 'S', 'c', 'o', 'p', 'e', 'K',
+'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'F', 'r', 'a', 'g', 'm', 'e', 'n', 't', 'B', 'u', 'i', 'l', 'd', 'e', 'r',
+'.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'E', 'x', 't', 'r', 'a', 'c', 't', 'o', 'r', '.', 'K', 'v', 'E',
+'l', 'e', 'm', 'e', 'n', 't', 'H', '\000', 'R', '\007', 'e', 'l', 'e', 'm', 'e', 'n', 't', '\032', '\333', '\001', '\n', '\t', 'K', 'v', 'E',
+'l', 'e', 'm', 'e', 'n', 't', '\022', '%', '\n', '\t', 's', 'e', 'p', 'a', 'r', 'a', 't', 'o', 'r', '\030', '\001', ' ', '\001', '(', '\t',
+'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\t', 's', 'e', 'p', 'a', 'r', 'a', 't', 'o', 'r', '\022', '\031', '\n', '\003', 'k',
+'e', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\003', 'k', 'e', 'y', ':', '\213', '\001',
+'\232', '\305', '\210', '\036', '\205', '\001', '\n', '\202', '\001', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l',
+'t', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i',
+'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e',
+'s', '.', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'F', 'r', 'a', 'g', 'm', 'e', 'n',
+'t', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'E', 'x', 't', 'r', 'a',
+'c', 't', 'o', 'r', '.', 'K', 'v', 'E', 'l', 'e', 'm', 'e', 'n', 't', ':', '\177', '\232', '\305', '\210', '\036', 'z', '\n', 'x', 'e', 'n',
+'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k',
+'.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.',
+'v', '2', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', '.', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B',
+'u', 'i', 'l', 'd', 'e', 'r', '.', 'F', 'r', 'a', 'g', 'm', 'e', 'n', 't', 'B', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'H', 'e',
+'a', 'd', 'e', 'r', 'V', 'a', 'l', 'u', 'e', 'E', 'x', 't', 'r', 'a', 'c', 't', 'o', 'r', 'B', '\016', '\n', '\014', 'e', 'x', 't',
+'r', 'a', 'c', 't', '_', 't', 'y', 'p', 'e', ':', 'j', '\232', '\305', '\210', '\036', 'e', '\n', 'c', 'e', 'n', 'v', 'o', 'y', '.', 'c',
+'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p',
+'_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'S', 'c',
+'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', '.', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e',
+'r', '.', 'F', 'r', 'a', 'g', 'm', 'e', 'n', 't', 'B', 'u', 'i', 'l', 'd', 'e', 'r', 'B', '\013', '\n', '\004', 't', 'y', 'p', 'e',
+'\022', '\003', '\370', 'B', '\001', ':', 'Z', '\232', '\305', '\210', '\036', 'U', '\n', 'S', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
+'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n',
+'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'S', 'c', 'o', 'p', 'e', 'd',
+'R', 'o', 'u', 't', 'e', 's', '.', 'S', 'c', 'o', 'p', 'e', 'K', 'e', 'y', 'B', 'u', 'i', 'l', 'd', 'e', 'r', ':', 'J', '\232',
+'\305', '\210', '\036', 'E', '\n', 'C', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r',
+'.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_',
+'m', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', 'B', '\027',
+'\n', '\020', 'c', 'o', 'n', 'f', 'i', 'g', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', '\"', '\361',
+'\001', '\n', '\t', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'd', 's', '\022', 'e', '\n', '\030', 's', 'c', 'o', 'p', 'e', 'd', '_', 'r', 'd',
+'s', '_', 'c', 'o', 'n', 'f', 'i', 'g', '_', 's', 'o', 'u', 'r', 'c', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\"', '.', 'e',
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i',
+'g', 'S', 'o', 'u', 'r', 'c', 'e', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\025', 's', 'c', 'o', 'p', 'e', 'd',
+'R', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', '\022', '4', '\n', '\026', 's', 'r', 'd', 's', '_', 'r',
+'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '_', 'l', 'o', 'c', 'a', 't', 'o', 'r', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\024', 's',
+'r', 'd', 's', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', 'L', 'o', 'c', 'a', 't', 'o', 'r', ':', 'G', '\232', '\305', '\210', '\036',
+'B', '\n', '@', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e',
+'t', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n',
+'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'd', 's', '\"', '\314', '\002', '\n', '\n', 'H', 't', 't',
+'p', 'F', 'i', 'l', 't', 'e', 'r', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B',
+'\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '9', '\n', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f',
+'i', 'g', '\030', '\004', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u',
+'f', '.', 'A', 'n', 'y', 'H', '\000', 'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'X', '\n', '\020', 'c',
+'o', 'n', 'f', 'i', 'g', '_', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', '\030', '\005', ' ', '\001', '(', '\013', '2', '+', '.', 'e',
+'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'E', 'x', 't', 'e', 'n',
+'s', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'H', '\000', 'R', '\017', 'c', 'o', 'n', 'f', 'i',
+'g', 'D', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', '\022', '\037', '\n', '\013', 'i', 's', '_', 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l',
+'\030', '\006', ' ', '\001', '(', '\010', 'R', '\n', 'i', 's', 'O', 'p', 't', 'i', 'o', 'n', 'a', 'l', ':', 'H', '\232', '\305', '\210', '\036', 'C',
+'\n', 'A', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't',
'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a',
-'g', 'e', 'r', '.', 'v', '3', 'B', '\032', 'H', 't', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n',
-'a', 'g', 'e', 'r', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '|', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e',
-'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n',
-'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '/', 'f', 'i', 'l', 't', 'e', 'r',
-'s', '/', 'n', 'e', 't', 'w', 'o', 'r', 'k', '/', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n',
-'_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '/', 'v', '3', ';', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i',
-'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o',
-'t', 'o', '3',
+'g', 'e', 'r', '.', 'v', '2', '.', 'H', 't', 't', 'p', 'F', 'i', 'l', 't', 'e', 'r', 'B', '\r', '\n', '\013', 'c', 'o', 'n', 'f',
+'i', 'g', '_', 't', 'y', 'p', 'e', 'J', '\004', '\010', '\003', '\020', '\004', 'J', '\004', '\010', '\002', '\020', '\003', 'R', '\006', 'c', 'o', 'n', 'f',
+'i', 'g', '\"', '\237', '\001', '\n', '\022', 'R', 'e', 'q', 'u', 'e', 's', 't', 'I', 'D', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n',
+'\022', '7', '\n', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '\024', '.',
+'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\013', 't', 'y', 'p', 'e',
+'d', 'C', 'o', 'n', 'f', 'i', 'g', ':', 'P', '\232', '\305', '\210', '\036', 'K', '\n', 'I', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n',
+'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c',
+'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '2', '.', 'R', 'e', 'q', 'u',
+'e', 's', 't', 'I', 'D', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\"', '\216', '\001', '\n', ' ', 'E', 'n', 'v', 'o', 'y', 'M',
+'o', 'b', 'i', 'l', 'e', 'H', 't', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e',
+'r', '\022', 'j', '\n', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', 'R', '.', 'e', 'n', 'v', 'o', 'y',
+'.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'n', 'e', 't', 'w', 'o',
+'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e',
+'r', '.', 'v', '3', '.', 'H', 't', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e',
+'r', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', 'B', '\357', '\001', '\n', 'I', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o',
+'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e',
+'r', 's', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o',
+'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'v', '3', 'B', '\032', 'H', 't', 't', 'p', 'C', 'o', 'n', 'n', 'e', 'c', 't',
+'i', 'o', 'n', 'M', 'a', 'n', 'a', 'g', 'e', 'r', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '|', 'g', 'i', 't', 'h', 'u', 'b',
+'.', 'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o',
+'l', '-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '/',
+'f', 'i', 'l', 't', 'e', 'r', 's', '/', 'n', 'e', 't', 'w', 'o', 'r', 'k', '/', 'h', 't', 't', 'p', '_', 'c', 'o', 'n', 'n',
+'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '/', 'v', '3', ';', 'h', 't', 't', 'p', '_', 'c', 'o',
+'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020',
+'\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
};
static _upb_DefPool_Init *deps[22] = {
@@ -565,5 +573,5 @@ _upb_DefPool_Init envoy_extensions_filters_network_http_connection_manager_v3_ht
deps,
&envoy_extensions_filters_network_http_connection_manager_v3_http_connection_manager_proto_upb_file_layout,
"envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto",
- UPB_STRINGVIEW_INIT(descriptor, 12553)
+ UPB_STRINGVIEW_INIT(descriptor, 12759)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.c
index 96ffb8af6f..715d54605d 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.c
@@ -20,7 +20,7 @@ extern _upb_DefPool_Init envoy_annotations_deprecation_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_versioning_proto_upbdefinit;
extern _upb_DefPool_Init validate_validate_proto_upbdefinit;
-static const char descriptor[5346] = {'\n', '3', 'e', 'n', 'v', 'o', 'y', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '/', 't', 'r', 'a', 'n', 's', 'p',
+static const char descriptor[5336] = {'\n', '3', 'e', 'n', 'v', 'o', 'y', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '/', 't', 'r', 'a', 'n', 's', 'p',
'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '/', 't', 'l', 's', '/', 'v', '3', '/', 't', 'l', 's', '.', 'p', 'r',
'o', 't', 'o', '\022', ')', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a',
'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '\032', '\"', 'e', 'n',
@@ -104,7 +104,7 @@ static const char descriptor[5346] = {'\n', '3', 'e', 'n', 'v', 'o', 'y', '/', '
'Q', '\n', '\024', 'r', 'e', 'm', 'o', 't', 'e', '_', 'a', 'd', 'd', 'r', 'e', 's', 's', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\003',
' ', '\003', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.',
'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'R', '\022', 'r', 'e', 'm', 'o', 't', 'e', 'A', 'd', 'd', 'r', 'e',
-'s', 's', 'R', 'a', 'n', 'g', 'e', '\"', '\364', '\027', '\n', '\020', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't',
+'s', 's', 'R', 'a', 'n', 'g', 'e', '\"', '\352', '\027', '\n', '\020', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't',
'e', 'x', 't', '\022', 'W', '\n', '\n', 't', 'l', 's', '_', 'p', 'a', 'r', 'a', 'm', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '8',
'.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o',
'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'T', 'l', 's', 'P', 'a', 'r', 'a',
@@ -112,128 +112,128 @@ static const char descriptor[5346] = {'\n', '3', 'e', 'n', 'v', 'o', 'y', '/', '
'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '9', '.', 'e', 'n', 'v', 'o',
'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o',
'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'T', 'l', 's', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a',
-'t', 'e', 'R', '\017', 't', 'l', 's', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 's', '\022', '\220', '\001', '\n', '\"', 't',
+'t', 'e', 'R', '\017', 't', 'l', 's', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 's', '\022', '\206', '\001', '\n', '\"', 't',
'l', 's', '_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 's', 'd', 's', '_', 's', 'e', 'c', 'r', 'e', 't',
'_', 'c', 'o', 'n', 'f', 'i', 'g', 's', '\030', '\006', ' ', '\003', '(', '\013', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x',
't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't',
-'s', '.', 't', 'l', 's', '.', 'v', '3', '.', 'S', 'd', 's', 'S', 'e', 'c', 'r', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', 'B',
-'\010', '\372', 'B', '\005', '\222', '\001', '\002', '\020', '\002', 'R', '\036', 't', 'l', 's', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e',
-'S', 'd', 's', 'S', 'e', 'c', 'r', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', 's', '\022', '\227', '\001', '\n', '!', 't', 'l', 's', '_',
-'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '_', 'i', 'n', 's', 't',
-'a', 'n', 'c', 'e', '\030', '\016', ' ', '\001', '(', '\013', '2', 'L', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's',
-'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l',
-'s', '.', 'v', '3', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'P',
-'l', 'u', 'g', 'i', 'n', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', '\036', 't', 'l', 's', 'C', 'e', 'r', 't', 'i', 'f', 'i',
-'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', '\022', '\255', '\001', '\n', '$',
-'t', 'l', 's', '_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a',
-'t', 'e', '_', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\030', '\t', ' ', '\001', '(', '\013', '2', 'O', '.', 'e', 'n', 'v', 'o', 'y',
+'s', '.', 't', 'l', 's', '.', 'v', '3', '.', 'S', 'd', 's', 'S', 'e', 'c', 'r', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', 'R',
+'\036', 't', 'l', 's', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'S', 'd', 's', 'S', 'e', 'c', 'r', 'e', 't', 'C',
+'o', 'n', 'f', 'i', 'g', 's', '\022', '\227', '\001', '\n', '!', 't', 'l', 's', '_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't',
+'e', '_', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '_', 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', '\030', '\016', ' ', '\001', '(', '\013',
+'2', 'L', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's',
+'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'e', 'r', 't', 'i',
+'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'P', 'l', 'u', 'g', 'i', 'n', 'I', 'n', 's', 't', 'a',
+'n', 'c', 'e', 'R', '\036', 't', 'l', 's', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd',
+'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', '\022', '\255', '\001', '\n', '$', 't', 'l', 's', '_', 'c', 'e', 'r', 't', 'i', 'f',
+'i', 'c', 'a', 't', 'e', '_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'p', 'r', 'o', 'v', 'i', 'd', 'e',
+'r', '\030', '\t', ' ', '\001', '(', '\013', '2', 'O', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n',
+'s', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v',
+'3', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e', 'x', 't', '.', 'C', 'e', 'r', 't', 'i', 'f',
+'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.',
+'0', 'R', '!', 't', 'l', 's', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c',
+'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\022', '\306', '\001', '\n', '-', 't', 'l', 's', '_', 'c', 'e', 'r', 't', 'i',
+'f', 'i', 'c', 'a', 't', 'e', '_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'p', 'r', 'o', 'v', 'i', 'd',
+'e', 'r', '_', 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', '\030', '\013', ' ', '\001', '(', '\013', '2', 'W', '.', 'e', 'n', 'v', 'o', 'y',
'.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c',
'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't',
-'e', 'x', 't', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'B', '\013',
-'\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'R', '!', 't', 'l', 's', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a',
-'t', 'e', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\022', '\306', '\001', '\n',
-'-', 't', 'l', 's', '_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c',
-'a', 't', 'e', '_', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '_', 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', '\030', '\013', ' ', '\001',
-'(', '\013', '2', 'W', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a',
-'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'o', 'm',
-'m', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e', 'x', 't', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e',
-'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004',
-'\003', '3', '.', '0', 'R', ')', 't', 'l', 's', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'C', 'e', 'r', 't', 'i',
-'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', '\022', 'x', '\n',
-'\022', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', '\003', ' ', '\001', '(', '\013',
-'2', 'G', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's',
-'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'e', 'r', 't', 'i',
-'f', 'i', 'c', 'a', 't', 'e', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'H', '\000',
-'R', '\021', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '\214', '\001', '\n', '$', 'v',
-'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 's', 'd', 's', '_', 's', 'e', 'c',
-'r', 'e', 't', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\007', ' ', '\001', '(', '\013', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.',
-'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k',
-'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'S', 'd', 's', 'S', 'e', 'c', 'r', 'e', 't', 'C', 'o', 'n', 'f', 'i',
-'g', 'H', '\000', 'R', ' ', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'S', 'd', 's',
-'S', 'e', 'c', 'r', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '\242', '\001', '\n', '\033', 'c', 'o', 'm', 'b', 'i', 'n', 'e', 'd',
-'_', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', '\010', ' ', '\001', '(', '\013',
-'2', '`', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's',
-'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'o', 'm', 'm', 'o',
-'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e', 'x', 't', '.', 'C', 'o', 'm', 'b', 'i', 'n', 'e', 'd', 'C', 'e', 'r', 't', 'i',
-'f', 'i', 'c', 'a', 't', 'e', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'H', '\000',
-'R', '\031', 'c', 'o', 'm', 'b', 'i', 'n', 'e', 'd', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e',
-'x', 't', '\022', '\265', '\001', '\n', '\'', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't',
-'_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\030', '\n', ' ', '\001',
-'(', '\013', '2', 'O', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a',
-'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'o', 'm',
-'m', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e', 'x', 't', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e',
-'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '$',
-'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c',
-'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\022', '\316', '\001', '\n', '0', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o',
-'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'p', 'r', 'o',
-'v', 'i', 'd', 'e', 'r', '_', 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', '\030', '\014', ' ', '\001', '(', '\013', '2', 'W', '.', 'e', 'n',
-'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_',
-'s', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C',
-'o', 'n', 't', 'e', 'x', 't', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e',
-'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R',
-',', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'C', 'e', 'r', 't', 'i', 'f', 'i',
-'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', '\022', '%', '\n', '\016', 'a',
-'l', 'p', 'n', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', '\030', '\004', ' ', '\003', '(', '\t', 'R', '\r', 'a', 'l', 'p', 'n',
-'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', '\022', 'W', '\n', '\021', 'c', 'u', 's', 't', 'o', 'm', '_', 'h', 'a', 'n', 'd', 's',
-'h', 'a', 'k', 'e', 'r', '\030', '\r', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i',
-'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C',
-'o', 'n', 'f', 'i', 'g', 'R', '\020', 'c', 'u', 's', 't', 'o', 'm', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'r', '\022', 'M',
-'\n', '\007', 'k', 'e', 'y', '_', 'l', 'o', 'g', '\030', '\017', ' ', '\001', '(', '\013', '2', '4', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e',
-'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e',
-'t', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'T', 'l', 's', 'K', 'e', 'y', 'L', 'o', 'g', 'R', '\006', 'k', 'e', 'y', 'L',
-'o', 'g', '\032', '\222', '\001', '\n', '\023', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e',
-'r', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R',
-'\004', 'n', 'a', 'm', 'e', '\022', 'O', '\n', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\001',
-'(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3',
-'.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', '\013',
-'t', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i', 'g', 'B', '\r', '\n', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\022', '\003', '\370', 'B',
-'\001', '\032', 'm', '\n', '\033', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I',
-'n', 's', 't', 'a', 'n', 'c', 'e', '\022', '#', '\n', '\r', 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', '_', 'n', 'a', 'm', 'e', '\030',
-'\001', ' ', '\001', '(', '\t', 'R', '\014', 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'N', 'a', 'm', 'e', '\022', ')', '\n', '\020', 'c', 'e',
-'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\017', 'c', 'e', 'r',
-'t', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'N', 'a', 'm', 'e', '\032', '\244', '\006', '\n', '$', 'C', 'o', 'm', 'b', 'i', 'n', 'e', 'd',
-'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't',
-'e', 'x', 't', '\022', '\217', '\001', '\n', '\032', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o',
-'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', '\001', ' ', '\001', '(', '\013', '2', 'G', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e',
+'e', 'x', 't', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n',
+'s', 't', 'a', 'n', 'c', 'e', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'R', ')', 't', 'l', 's', 'C',
+'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v',
+'i', 'd', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', '\022', 'x', '\n', '\022', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o',
+'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', '\003', ' ', '\001', '(', '\013', '2', 'G', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e',
'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e',
't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'V', 'a', 'l', 'i',
-'d', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\030',
-'d', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022',
-'\224', '\001', '\n', '$', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 's', 'd',
-'s', '_', 's', 'e', 'c', 'r', 'e', 't', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', ':', '.', 'e',
-'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't',
-'_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'S', 'd', 's', 'S', 'e', 'c', 'r', 'e', 't',
-'C', 'o', 'n', 'f', 'i', 'g', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', ' ', 'v', 'a', 'l', 'i', 'd', 'a', 't',
-'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'S', 'd', 's', 'S', 'e', 'c', 'r', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g',
-'\022', '\263', '\001', '\n', '\'', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 'c',
-'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\013',
-'2', 'O', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's',
-'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'o', 'm', 'm', 'o',
-'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e', 'x', 't', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r',
-'o', 'v', 'i', 'd', 'e', 'r', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'R', '$', 'v', 'a', 'l', 'i',
-'d', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P',
-'r', 'o', 'v', 'i', 'd', 'e', 'r', '\022', '\314', '\001', '\n', '0', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '_', 'c', 'o',
-'n', 't', 'e', 'x', 't', '_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'p', 'r', 'o', 'v', 'i', 'd', 'e',
-'r', '_', 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', 'W', '.', 'e', 'n', 'v', 'o', 'y', '.',
-'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k',
-'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e',
-'x', 't', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n', 's',
-'t', 'a', 'n', 'c', 'e', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'R', ',', 'v', 'a', 'l', 'i', 'd',
-'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r',
-'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', ':', 'N', '\232', '\305', '\210', '\036', 'I', '\n', 'G', 'e', 'n',
-'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'a', 'u', 't', 'h', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's',
-'C', 'o', 'n', 't', 'e', 'x', 't', '.', 'C', 'o', 'm', 'b', 'i', 'n', 'e', 'd', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a',
-'t', 'e', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', ':', ')', '\232', '\305', '\210', '\036',
-'$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2', '.', 'a', 'u', 't', 'h', '.', 'C', 'o', 'm', 'm',
-'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e', 'x', 't', 'B', '\031', '\n', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o',
-'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 't', 'y', 'p', 'e', 'J', '\004', '\010', '\005', '\020', '\006', 'B', '\245', '\001', '\n', '7',
-'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n',
+'d', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'H', '\000', 'R', '\021', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i',
+'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '\214', '\001', '\n', '$', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '_',
+'c', 'o', 'n', 't', 'e', 'x', 't', '_', 's', 'd', 's', '_', 's', 'e', 'c', 'r', 'e', 't', '_', 'c', 'o', 'n', 'f', 'i', 'g',
+'\030', '\007', ' ', '\001', '(', '\013', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's',
+'.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3',
+'.', 'S', 'd', 's', 'S', 'e', 'c', 'r', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', ' ', 'v', 'a', 'l', 'i', 'd',
+'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'S', 'd', 's', 'S', 'e', 'c', 'r', 'e', 't', 'C', 'o', 'n', 'f',
+'i', 'g', '\022', '\242', '\001', '\n', '\033', 'c', 'o', 'm', 'b', 'i', 'n', 'e', 'd', '_', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o',
+'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', '\010', ' ', '\001', '(', '\013', '2', '`', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e',
+'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e',
+'t', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e', 'x',
+'t', '.', 'C', 'o', 'm', 'b', 'i', 'n', 'e', 'd', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'V', 'a', 'l', 'i',
+'d', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'H', '\000', 'R', '\031', 'c', 'o', 'm', 'b', 'i', 'n', 'e', 'd',
+'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '\265', '\001', '\n', '\'', 'v', 'a', 'l',
+'i', 'd', 'a', 't', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a',
+'t', 'e', '_', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\030', '\n', ' ', '\001', '(', '\013', '2', 'O', '.', 'e', 'n', 'v', 'o', 'y',
+'.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c',
+'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't',
+'e', 'x', 't', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'B', '\013',
+'\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', '$', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n',
+'C', 'o', 'n', 't', 'e', 'x', 't', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e',
+'r', '\022', '\316', '\001', '\n', '0', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_',
+'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '_', 'i', 'n', 's', 't',
+'a', 'n', 'c', 'e', '\030', '\014', ' ', '\001', '(', '\013', '2', 'W', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's',
+'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l',
+'s', '.', 'v', '3', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e', 'x', 't', '.', 'C', 'e', 'r',
+'t', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 'B',
+'\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'H', '\000', 'R', ',', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o',
+'n', 'C', 'o', 'n', 't', 'e', 'x', 't', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd',
+'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', '\022', '%', '\n', '\016', 'a', 'l', 'p', 'n', '_', 'p', 'r', 'o', 't', 'o', 'c',
+'o', 'l', 's', '\030', '\004', ' ', '\003', '(', '\t', 'R', '\r', 'a', 'l', 'p', 'n', 'P', 'r', 'o', 't', 'o', 'c', 'o', 'l', 's', '\022',
+'W', '\n', '\021', 'c', 'u', 's', 't', 'o', 'm', '_', 'h', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'r', '\030', '\r', ' ', '\001', '(',
+'\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.',
+'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\020', 'c', 'u', 's',
+'t', 'o', 'm', 'H', 'a', 'n', 'd', 's', 'h', 'a', 'k', 'e', 'r', '\022', 'M', '\n', '\007', 'k', 'e', 'y', '_', 'l', 'o', 'g', '\030',
+'\017', ' ', '\001', '(', '\013', '2', '4', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.',
+'t', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.',
+'T', 'l', 's', 'K', 'e', 'y', 'L', 'o', 'g', 'R', '\006', 'k', 'e', 'y', 'L', 'o', 'g', '\032', '\222', '\001', '\n', '\023', 'C', 'e', 'r',
+'t', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030',
+'\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'O', '\n', '\014', 't',
+'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y',
+'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', 'e',
+'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'H', '\000', 'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', 'i',
+'g', 'B', '\r', '\n', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\022', '\003', '\370', 'B', '\001', '\032', 'm', '\n', '\033', 'C', 'e', 'r', 't', 'i',
+'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', '\022', '#', '\n',
+'\r', 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\014', 'i', 'n', 's',
+'t', 'a', 'n', 'c', 'e', 'N', 'a', 'm', 'e', '\022', ')', '\n', '\020', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_',
+'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\017', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'N', 'a',
+'m', 'e', '\032', '\244', '\006', '\n', '$', 'C', 'o', 'm', 'b', 'i', 'n', 'e', 'd', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't',
+'e', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '\217', '\001', '\n', '\032', 'd', 'e',
+'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030',
+'\001', ' ', '\001', '(', '\013', '2', 'G', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.',
+'t', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', '.',
+'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't',
+'e', 'x', 't', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\030', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l',
+'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '\224', '\001', '\n', '$', 'v', 'a', 'l', 'i', 'd', 'a',
+'t', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 's', 'd', 's', '_', 's', 'e', 'c', 'r', 'e', 't', '_', 'c',
+'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n',
's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't',
-'l', 's', '.', 'v', '3', 'B', '\010', 'T', 'l', 's', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'V', 'g', 'i', 't', 'h', 'u', 'b',
-'.', 'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o',
-'l', '-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '/',
-'t', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '/', 't', 'l', 's', '/', 'v', '3', ';',
-'t', 'l', 's', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
+'l', 's', '.', 'v', '3', '.', 'S', 'd', 's', 'S', 'e', 'c', 'r', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', 'B', '\010', '\372', 'B',
+'\005', '\212', '\001', '\002', '\020', '\001', 'R', ' ', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't',
+'S', 'd', 's', 'S', 'e', 'c', 'r', 'e', 't', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '\263', '\001', '\n', '\'', 'v', 'a', 'l', 'i', 'd',
+'a', 't', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e',
+'_', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\013', '2', 'O', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e',
+'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e',
+'t', 's', '.', 't', 'l', 's', '.', 'v', '3', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e', 'x',
+'t', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'B', '\013', '\030', '\001',
+'\222', '\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'R', '$', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't',
+'e', 'x', 't', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '\022', '\314', '\001',
+'\n', '0', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 'c', 'e', 'r', 't',
+'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', '_', 'i', 'n', 's', 't', 'a', 'n', 'c', 'e',
+'\030', '\004', ' ', '\001', '(', '\013', '2', 'W', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's',
+'.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3',
+'.', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e', 'x', 't', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i',
+'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 'B', '\013', '\030', '\001', '\222',
+'\307', '\206', '\330', '\004', '\003', '3', '.', '0', 'R', ',', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'C', 'o', 'n', 't', 'e',
+'x', 't', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n', 's', 't',
+'a', 'n', 'c', 'e', ':', 'N', '\232', '\305', '\210', '\036', 'I', '\n', 'G', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'p', 'i', '.', 'v', '2',
+'.', 'a', 'u', 't', 'h', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e', 'x', 't', '.', 'C', 'o',
+'m', 'b', 'i', 'n', 'e', 'd', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i',
+'o', 'n', 'C', 'o', 'n', 't', 'e', 'x', 't', ':', ')', '\232', '\305', '\210', '\036', '$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', '.', 'a',
+'p', 'i', '.', 'v', '2', '.', 'a', 'u', 't', 'h', '.', 'C', 'o', 'm', 'm', 'o', 'n', 'T', 'l', 's', 'C', 'o', 'n', 't', 'e',
+'x', 't', 'B', '\031', '\n', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_',
+'t', 'y', 'p', 'e', 'J', '\004', '\010', '\005', '\020', '\006', 'B', '\245', '\001', '\n', '7', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r',
+'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n',
+'s', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '.', 't', 'l', 's', '.', 'v', '3', 'B', '\010', 'T', 'l', 's',
+'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'V', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y',
+'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n',
+'v', 'o', 'y', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '/', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_',
+'s', 'o', 'c', 'k', 'e', 't', 's', '/', 't', 'l', 's', '/', 'v', '3', ';', 't', 'l', 's', 'v', '3', '\272', '\200', '\310', '\321', '\006',
+'\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
};
static _upb_DefPool_Init *deps[11] = {
@@ -254,5 +254,5 @@ _upb_DefPool_Init envoy_extensions_transport_sockets_tls_v3_tls_proto_upbdefinit
deps,
&envoy_extensions_transport_sockets_tls_v3_tls_proto_upb_file_layout,
"envoy/extensions/transport_sockets/tls/v3/tls.proto",
- UPB_STRINGVIEW_INIT(descriptor, 5346)
+ UPB_STRINGVIEW_INIT(descriptor, 5336)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/discovery/v3/ads.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/discovery/v3/ads.upbdefs.c
index f7ce2ecb82..50984f404b 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/discovery/v3/ads.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/discovery/v3/ads.upbdefs.c
@@ -13,7 +13,7 @@
extern _upb_DefPool_Init envoy_service_discovery_v3_discovery_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_versioning_proto_upbdefinit;
-static const char descriptor[684] = {'\n', '$', 'e', 'n', 'v', 'o', 'y', '/', 's', 'e', 'r', 'v', 'i', 'c', 'e', '/', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y',
+static const char descriptor[681] = {'\n', '$', 'e', 'n', 'v', 'o', 'y', '/', 's', 'e', 'r', 'v', 'i', 'c', 'e', '/', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y',
'/', 'v', '3', '/', 'a', 'd', 's', '.', 'p', 'r', 'o', 't', 'o', '\022', '\032', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r', 'v',
'i', 'c', 'e', '.', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', '.', 'v', '3', '\032', '*', 'e', 'n', 'v', 'o', 'y', '/', 's',
'e', 'r', 'v', 'i', 'c', 'e', '/', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', '/', 'v', '3', '/', 'd', 'i', 's', 'c', 'o',
@@ -34,13 +34,13 @@ static const char descriptor[684] = {'\n', '$', 'e', 'n', 'v', 'o', 'y', '/', 's
'D', 'e', 'l', 't', 'a', 'D', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', 'R', 'e', 'q', 'u', 'e', 's', 't', '\032', '2', '.', 'e',
'n', 'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', '.', 'v', '3',
'.', 'D', 'e', 'l', 't', 'a', 'D', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', '\"', '\000',
-'(', '\001', '0', '\001', 'B', '\220', '\001', '\n', '(', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n',
+'(', '\001', '0', '\001', 'B', '\215', '\001', '\n', '(', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n',
'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', '.', 'v', '3', 'B',
'\010', 'A', 'd', 's', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'M', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '/', 'e',
'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-', 'p', 'l', 'a', 'n',
'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 's', 'e', 'r', 'v', 'i', 'c', 'e', '/', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y',
-'/', 'v', '3', ';', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', 'v', '3', '\210', '\001', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020',
-'\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
+'/', 'v', '3', ';', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006',
+'p', 'r', 'o', 't', 'o', '3',
};
static _upb_DefPool_Init *deps[4] = {
@@ -54,5 +54,5 @@ _upb_DefPool_Init envoy_service_discovery_v3_ads_proto_upbdefinit = {
deps,
&envoy_service_discovery_v3_ads_proto_upb_file_layout,
"envoy/service/discovery/v3/ads.proto",
- UPB_STRINGVIEW_INIT(descriptor, 684)
+ UPB_STRINGVIEW_INIT(descriptor, 681)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c
index d32aff62cf..739effafab 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c
@@ -15,7 +15,7 @@ extern _upb_DefPool_Init envoy_config_endpoint_v3_load_report_proto_upbdefinit;
extern _upb_DefPool_Init google_protobuf_duration_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_versioning_proto_upbdefinit;
-static const char descriptor[1040] = {'\n', '%', 'e', 'n', 'v', 'o', 'y', '/', 's', 'e', 'r', 'v', 'i', 'c', 'e', '/', 'l', 'o', 'a', 'd', '_', 's', 't', 'a', 't',
+static const char descriptor[1037] = {'\n', '%', 'e', 'n', 'v', 'o', 'y', '/', 's', 'e', 'r', 'v', 'i', 'c', 'e', '/', 'l', 'o', 'a', 'd', '_', 's', 't', 'a', 't',
's', '/', 'v', '3', '/', 'l', 'r', 's', '.', 'p', 'r', 'o', 't', 'o', '\022', '\033', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r',
'v', 'i', 'c', 'e', '.', 'l', 'o', 'a', 'd', '_', 's', 't', 'a', 't', 's', '.', 'v', '3', '\032', '\037', 'e', 'n', 'v', 'o', 'y',
'/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'b', 'a', 's', 'e', '.', 'p', 'r', 'o', 't',
@@ -50,13 +50,13 @@ static const char descriptor[1040] = {'\n', '%', 'e', 'n', 'v', 'o', 'y', '/', '
'a', 'd', '_', 's', 't', 'a', 't', 's', '.', 'v', '3', '.', 'L', 'o', 'a', 'd', 'S', 't', 'a', 't', 's', 'R', 'e', 'q', 'u',
'e', 's', 't', '\032', '.', '.', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 'l', 'o', 'a', 'd', '_',
's', 't', 'a', 't', 's', '.', 'v', '3', '.', 'L', 'o', 'a', 'd', 'S', 't', 'a', 't', 's', 'R', 'e', 's', 'p', 'o', 'n', 's',
-'e', '\"', '\000', '(', '\001', '0', '\001', 'B', '\223', '\001', '\n', ')', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y',
+'e', '\"', '\000', '(', '\001', '0', '\001', 'B', '\220', '\001', '\n', ')', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y',
'.', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 'l', 'o', 'a', 'd', '_', 's', 't', 'a', 't', 's',
'.', 'v', '3', 'B', '\010', 'L', 'r', 's', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'O', 'g', 'i', 't', 'h', 'u', 'b', '.', 'c',
'o', 'm', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l', '-',
'p', 'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 's', 'e', 'r', 'v', 'i', 'c', 'e', '/', 'l', 'o', 'a', 'd', '_',
-'s', 't', 'a', 't', 's', '/', 'v', '3', ';', 'l', 'o', 'a', 'd', '_', 's', 't', 'a', 't', 's', 'v', '3', '\210', '\001', '\001', '\272',
-'\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
+'s', 't', 'a', 't', 's', '/', 'v', '3', ';', 'l', 'o', 'a', 'd', '_', 's', 't', 'a', 't', 's', 'v', '3', '\272', '\200', '\310', '\321',
+'\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
};
static _upb_DefPool_Init *deps[6] = {
@@ -72,5 +72,5 @@ _upb_DefPool_Init envoy_service_load_stats_v3_lrs_proto_upbdefinit = {
deps,
&envoy_service_load_stats_v3_lrs_proto_upb_file_layout,
"envoy/service/load_stats/v3/lrs.proto",
- UPB_STRINGVIEW_INIT(descriptor, 1040)
+ UPB_STRINGVIEW_INIT(descriptor, 1037)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c
index 96b6d43101..50dbc1b689 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c
@@ -19,7 +19,7 @@ extern _upb_DefPool_Init google_protobuf_timestamp_proto_upbdefinit;
extern _upb_DefPool_Init envoy_annotations_deprecation_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
extern _upb_DefPool_Init udpa_annotations_versioning_proto_upbdefinit;
-static const char descriptor[2758] = {'\n', '\"', 'e', 'n', 'v', 'o', 'y', '/', 's', 'e', 'r', 'v', 'i', 'c', 'e', '/', 's', 't', 'a', 't', 'u', 's', '/', 'v', '3',
+static const char descriptor[2755] = {'\n', '\"', 'e', 'n', 'v', 'o', 'y', '/', 's', 'e', 'r', 'v', 'i', 'c', 'e', '/', 's', 't', 'a', 't', 'u', 's', '/', 'v', '3',
'/', 'c', 's', 'd', 's', '.', 'p', 'r', 'o', 't', 'o', '\022', '\027', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c',
'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '3', '\032', '\'', 'e', 'n', 'v', 'o', 'y', '/', 'a', 'd', 'm', 'i', 'n', '/',
'v', '3', '/', 'c', 'o', 'n', 'f', 'i', 'g', '_', 'd', 'u', 'm', 'p', '_', 's', 'h', 'a', 'r', 'e', 'd', '.', 'p', 'r', 'o',
@@ -123,13 +123,13 @@ static const char descriptor[2758] = {'\n', '\"', 'e', 'n', 'v', 'o', 'y', '/',
'y', '.', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '3', '.', 'C', 'l', 'i', 'e', 'n',
't', 'S', 't', 'a', 't', 'u', 's', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', '\"', ',', '\202', '\323', '\344', '\223', '\002', '\035', '\"', '\033',
'/', 'v', '3', '/', 'd', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', ':', 'c', 'l', 'i', 'e', 'n', 't', '_', 's', 't', 'a', 't',
-'u', 's', '\202', '\323', '\344', '\223', '\002', '\003', ':', '\001', '*', 'B', '\210', '\001', '\n', '%', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p',
+'u', 's', '\202', '\323', '\344', '\223', '\002', '\003', ':', '\001', '*', 'B', '\205', '\001', '\n', '%', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p',
'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 's', 't', 'a', 't', 'u', 's',
'.', 'v', '3', 'B', '\t', 'C', 's', 'd', 's', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'G', 'g', 'i', 't', 'h', 'u', 'b', '.',
'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l',
'-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 's', 'e', 'r', 'v', 'i', 'c', 'e', '/', 's', 't', 'a', 't',
-'u', 's', '/', 'v', '3', ';', 's', 't', 'a', 't', 'u', 's', 'v', '3', '\210', '\001', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002',
-'b', '\006', 'p', 'r', 'o', 't', 'o', '3',
+'u', 's', '/', 'v', '3', ';', 's', 't', 'a', 't', 'u', 's', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p',
+'r', 'o', 't', 'o', '3',
};
static _upb_DefPool_Init *deps[10] = {
@@ -149,5 +149,5 @@ _upb_DefPool_Init envoy_service_status_v3_csds_proto_upbdefinit = {
deps,
&envoy_service_status_v3_csds_proto_upb_file_layout,
"envoy/service/status/v3/csds.proto",
- UPB_STRINGVIEW_INIT(descriptor, 2758)
+ UPB_STRINGVIEW_INIT(descriptor, 2755)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/http_inputs.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/http_inputs.upbdefs.c
index 50facfcdaf..60c9a937b4 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/http_inputs.upbdefs.c
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/http_inputs.upbdefs.c
@@ -12,7 +12,7 @@
extern _upb_DefPool_Init udpa_annotations_status_proto_upbdefinit;
extern _upb_DefPool_Init validate_validate_proto_upbdefinit;
-static const char descriptor[579] = {'\n', '\'', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 'h',
+static const char descriptor[656] = {'\n', '\'', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 'h',
't', 't', 'p', '_', 'i', 'n', 'p', 'u', 't', 's', '.', 'p', 'r', 'o', 't', 'o', '\022', '\025', 'e', 'n', 'v', 'o', 'y', '.', 't',
'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o',
't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l',
@@ -29,13 +29,16 @@ static const char descriptor[579] = {'\n', '\'', 'e', 'n', 'v', 'o', 'y', '/', '
'a', 'm', 'e', '\"', 'M', '\n', '\035', 'H', 't', 't', 'p', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', 'T', 'r', 'a', 'i', 'l', 'e',
'r', 'M', 'a', 't', 'c', 'h', 'I', 'n', 'p', 'u', 't', '\022', ',', '\n', '\013', 'h', 'e', 'a', 'd', 'e', 'r', '_', 'n', 'a', 'm',
'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\013', '\372', 'B', '\010', 'r', '\006', '\300', '\001', '\001', '\310', '\001', '\000', 'R', '\n', 'h', 'e', 'a',
-'d', 'e', 'r', 'N', 'a', 'm', 'e', 'B', '\210', '\001', '\n', '#', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y',
-'.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', 'B', '\017', 'H',
-'t', 't', 'p', 'I', 'n', 'p', 'u', 't', 's', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'F', 'g', 'i', 't', 'h', 'u', 'b', '.',
-'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r', 'o', 'l',
-'-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', 'e', 'r',
-'/', 'v', '3', ';', 'm', 'a', 't', 'c', 'h', 'e', 'r', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r',
-'o', 't', 'o', '3',
+'d', 'e', 'r', 'N', 'a', 'm', 'e', '\"', 'K', '\n', '\037', 'H', 't', 't', 'p', 'R', 'e', 'q', 'u', 'e', 's', 't', 'Q', 'u', 'e',
+'r', 'y', 'P', 'a', 'r', 'a', 'm', 'M', 'a', 't', 'c', 'h', 'I', 'n', 'p', 'u', 't', '\022', '(', '\n', '\013', 'q', 'u', 'e', 'r',
+'y', '_', 'p', 'a', 'r', 'a', 'm', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\n', 'q',
+'u', 'e', 'r', 'y', 'P', 'a', 'r', 'a', 'm', 'B', '\210', '\001', '\n', '#', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o',
+'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', 'B',
+'\017', 'H', 't', 't', 'p', 'I', 'n', 'p', 'u', 't', 's', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', 'F', 'g', 'i', 't', 'h', 'u',
+'b', '.', 'c', 'o', 'm', '/', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '/', 'g', 'o', '-', 'c', 'o', 'n', 't', 'r',
+'o', 'l', '-', 'p', 'l', 'a', 'n', 'e', '/', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h',
+'e', 'r', '/', 'v', '3', ';', 'm', 'a', 't', 'c', 'h', 'e', 'r', 'v', '3', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006',
+'p', 'r', 'o', 't', 'o', '3',
};
static _upb_DefPool_Init *deps[3] = {
@@ -48,5 +51,5 @@ _upb_DefPool_Init envoy_type_matcher_v3_http_inputs_proto_upbdefinit = {
deps,
&envoy_type_matcher_v3_http_inputs_proto_upb_file_layout,
"envoy/type/matcher/v3/http_inputs.proto",
- UPB_STRINGVIEW_INIT(descriptor, 579)
+ UPB_STRINGVIEW_INIT(descriptor, 656)
};
diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/http_inputs.upbdefs.h b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/http_inputs.upbdefs.h
index b78331cd1d..c449d9b98e 100644
--- a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/http_inputs.upbdefs.h
+++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/http_inputs.upbdefs.h
@@ -41,6 +41,11 @@ UPB_INLINE const upb_MessageDef *envoy_type_matcher_v3_HttpResponseTrailerMatchI
return upb_DefPool_FindMessageByName(s, "envoy.type.matcher.v3.HttpResponseTrailerMatchInput");
}
+UPB_INLINE const upb_MessageDef *envoy_type_matcher_v3_HttpRequestQueryParamMatchInput_getmsgdef(upb_DefPool *s) {
+ _upb_DefPool_LoadDefInit(s, &envoy_type_matcher_v3_http_inputs_proto_upbdefinit);
+ return upb_DefPool_FindMessageByName(s, "envoy.type.matcher.v3.HttpRequestQueryParamMatchInput");
+}
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_channel_stack_modifier.cc b/contrib/libs/grpc/src/core/ext/xds/xds_channel_stack_modifier.cc
index c80affe84f..5120e42762 100644
--- a/contrib/libs/grpc/src/core/ext/xds/xds_channel_stack_modifier.cc
+++ b/contrib/libs/grpc/src/core/ext/xds/xds_channel_stack_modifier.cc
@@ -62,8 +62,7 @@ bool XdsChannelStackModifier::ModifyChannelStack(ChannelStackBuilder* builder) {
auto it = builder->mutable_stack()->begin();
while (it != builder->mutable_stack()->end()) {
const char* filter_name_at_it = (*it)->name;
- if (strcmp("census_server", filter_name_at_it) == 0 ||
- strcmp("opencensus_server", filter_name_at_it) == 0) {
+ if (strcmp("census_server", filter_name_at_it) == 0) {
break;
}
++it;
diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_client_stats.cc b/contrib/libs/grpc/src/core/ext/xds/xds_client_stats.cc
index 4b68368add..16c3f156ca 100644
--- a/contrib/libs/grpc/src/core/ext/xds/xds_client_stats.cc
+++ b/contrib/libs/grpc/src/core/ext/xds/xds_client_stats.cc
@@ -131,29 +131,43 @@ XdsClusterLocalityStats::~XdsClusterLocalityStats() {
XdsClusterLocalityStats::Snapshot
XdsClusterLocalityStats::GetSnapshotAndReset() {
- Snapshot snapshot = {
- GetAndResetCounter(&total_successful_requests_),
- // Don't reset total_requests_in_progress because it's
- // not related to a single reporting interval.
- total_requests_in_progress_.load(std::memory_order_relaxed),
- GetAndResetCounter(&total_error_requests_),
- GetAndResetCounter(&total_issued_requests_),
- {}};
- MutexLock lock(&backend_metrics_mu_);
- snapshot.backend_metrics = std::move(backend_metrics_);
+ Snapshot snapshot;
+ for (auto& percpu_stats : stats_) {
+ Snapshot percpu_snapshot = {
+ GetAndResetCounter(&percpu_stats.total_successful_requests),
+ // Don't reset total_requests_in_progress because it's
+ // not related to a single reporting interval.
+ percpu_stats.total_requests_in_progress.load(std::memory_order_relaxed),
+ GetAndResetCounter(&percpu_stats.total_error_requests),
+ GetAndResetCounter(&percpu_stats.total_issued_requests),
+ {}};
+ {
+ MutexLock lock(&percpu_stats.backend_metrics_mu);
+ percpu_snapshot.backend_metrics = std::move(percpu_stats.backend_metrics);
+ }
+ snapshot += percpu_snapshot;
+ }
return snapshot;
}
void XdsClusterLocalityStats::AddCallStarted() {
- total_issued_requests_.fetch_add(1, std::memory_order_relaxed);
- total_requests_in_progress_.fetch_add(1, std::memory_order_relaxed);
+ Stats& stats = stats_.this_cpu();
+ stats.total_issued_requests.fetch_add(1, std::memory_order_relaxed);
+ stats.total_requests_in_progress.fetch_add(1, std::memory_order_relaxed);
}
-void XdsClusterLocalityStats::AddCallFinished(bool fail) {
+void XdsClusterLocalityStats::AddCallFinished(
+ const std::map<y_absl::string_view, double>* named_metrics, bool fail) {
+ Stats& stats = stats_.this_cpu();
std::atomic<uint64_t>& to_increment =
- fail ? total_error_requests_ : total_successful_requests_;
+ fail ? stats.total_error_requests : stats.total_successful_requests;
to_increment.fetch_add(1, std::memory_order_relaxed);
- total_requests_in_progress_.fetch_add(-1, std::memory_order_acq_rel);
+ stats.total_requests_in_progress.fetch_add(-1, std::memory_order_acq_rel);
+ if (named_metrics == nullptr) return;
+ MutexLock lock(&stats.backend_metrics_mu);
+ for (const auto& m : *named_metrics) {
+ stats.backend_metrics[TString(m.first)] += BackendMetric{1, m.second};
+ }
}
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_client_stats.h b/contrib/libs/grpc/src/core/ext/xds/xds_client_stats.h
index 90f7a5c121..0de30e3cc2 100644
--- a/contrib/libs/grpc/src/core/ext/xds/xds_client_stats.h
+++ b/contrib/libs/grpc/src/core/ext/xds/xds_client_stats.h
@@ -35,6 +35,7 @@
#include "src/core/ext/xds/xds_bootstrap.h"
#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/per_cpu.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/sync.h"
@@ -160,8 +161,8 @@ class XdsClusterDropStats : public RefCounted<XdsClusterDropStats> {
class XdsClusterLocalityStats : public RefCounted<XdsClusterLocalityStats> {
public:
struct BackendMetric {
- uint64_t num_requests_finished_with_metric;
- double total_metric_value;
+ uint64_t num_requests_finished_with_metric = 0;
+ double total_metric_value = 0;
BackendMetric& operator+=(const BackendMetric& other) {
num_requests_finished_with_metric +=
@@ -176,10 +177,10 @@ class XdsClusterLocalityStats : public RefCounted<XdsClusterLocalityStats> {
};
struct Snapshot {
- uint64_t total_successful_requests;
- uint64_t total_requests_in_progress;
- uint64_t total_error_requests;
- uint64_t total_issued_requests;
+ uint64_t total_successful_requests = 0;
+ uint64_t total_requests_in_progress = 0;
+ uint64_t total_error_requests = 0;
+ uint64_t total_issued_requests = 0;
std::map<TString, BackendMetric> backend_metrics;
Snapshot& operator+=(const Snapshot& other) {
@@ -216,27 +217,30 @@ class XdsClusterLocalityStats : public RefCounted<XdsClusterLocalityStats> {
Snapshot GetSnapshotAndReset();
void AddCallStarted();
- void AddCallFinished(bool fail = false);
+ void AddCallFinished(const std::map<y_absl::string_view, double>* named_metrics,
+ bool fail = false);
private:
+ struct Stats {
+ std::atomic<uint64_t> total_successful_requests{0};
+ std::atomic<uint64_t> total_requests_in_progress{0};
+ std::atomic<uint64_t> total_error_requests{0};
+ std::atomic<uint64_t> total_issued_requests{0};
+
+ // Protects backend_metrics. A mutex is necessary because the length of
+ // backend_metrics_ can be accessed by both the callback intercepting the
+ // call's recv_trailing_metadata and the load reporting thread.
+ Mutex backend_metrics_mu;
+ std::map<TString, BackendMetric> backend_metrics
+ Y_ABSL_GUARDED_BY(backend_metrics_mu);
+ };
+
RefCountedPtr<XdsClient> xds_client_;
const XdsBootstrap::XdsServer& lrs_server_;
y_absl::string_view cluster_name_;
y_absl::string_view eds_service_name_;
RefCountedPtr<XdsLocalityName> name_;
-
- std::atomic<uint64_t> total_successful_requests_{0};
- std::atomic<uint64_t> total_requests_in_progress_{0};
- std::atomic<uint64_t> total_error_requests_{0};
- std::atomic<uint64_t> total_issued_requests_{0};
-
- // Protects backend_metrics_. A mutex is necessary because the length of
- // backend_metrics_ can be accessed by both the callback intercepting the
- // call's recv_trailing_metadata (not from the control plane work serializer)
- // and the load reporting thread (from the control plane work serializer).
- Mutex backend_metrics_mu_;
- std::map<TString, BackendMetric> backend_metrics_
- Y_ABSL_GUARDED_BY(backend_metrics_mu_);
+ PerCpu<Stats> stats_{32};
};
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.cc b/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.cc
index e9c5537895..d0a5851fd8 100644
--- a/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.cc
+++ b/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.cc
@@ -93,11 +93,14 @@ TString XdsEndpointResource::Priority::ToString() const {
}
bool XdsEndpointResource::DropConfig::ShouldDrop(
- const TString** category_name) const {
+ const TString** category_name) {
for (size_t i = 0; i < drop_category_list_.size(); ++i) {
const auto& drop_category = drop_category_list_[i];
// Generate a random number in [0, 1000000).
- const uint32_t random = static_cast<uint32_t>(rand()) % 1000000;
+ const uint32_t random = [&]() {
+ MutexLock lock(&mu_);
+ return y_absl::Uniform<uint32_t>(bit_gen_, 0, 1000000);
+ }();
if (random < drop_category.parts_per_million) {
*category_name = &drop_category.name;
return true;
diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.h b/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.h
index f77558a997..ee1a17d277 100644
--- a/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.h
+++ b/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.h
@@ -29,6 +29,8 @@
#include <utility>
#include <vector>
+#include "y_absl/base/thread_annotations.h"
+#include "y_absl/random/random.h"
#include "y_absl/strings/string_view.h"
#include "envoy/config/endpoint/v3/endpoint.upbdefs.h"
#include "upb/def.h"
@@ -39,6 +41,7 @@
#include "src/core/ext/xds/xds_resource_type_impl.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/resolver/server_address.h"
namespace grpc_core {
@@ -91,7 +94,7 @@ struct XdsEndpointResource : public XdsResourceType::ResourceData {
// The only method invoked from outside the WorkSerializer (used in
// the data plane).
- bool ShouldDrop(const TString** category_name) const;
+ bool ShouldDrop(const TString** category_name);
const DropCategoryList& drop_category_list() const {
return drop_category_list_;
@@ -109,6 +112,11 @@ struct XdsEndpointResource : public XdsResourceType::ResourceData {
private:
DropCategoryList drop_category_list_;
bool drop_all_ = false;
+
+ // TODO(roth): Consider using a separate thread-local BitGen for each CPU
+ // to avoid the need for this mutex.
+ Mutex mu_;
+ y_absl::BitGen bit_gen_ Y_ABSL_GUARDED_BY(&mu_);
};
PriorityList priorities;
diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.cc b/contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.cc
index 69a35ce23a..719bafabe3 100644
--- a/contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.cc
+++ b/contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.cc
@@ -397,7 +397,7 @@ Json ParseHttpRbacToJson(const envoy_extensions_filters_http_rbac_v3_RBAC* rbac,
}
Json::Object inner_rbac_json;
inner_rbac_json.emplace("action", envoy_config_rbac_v3_RBAC_action(rules));
- if (envoy_config_rbac_v3_RBAC_has_policies(rules)) {
+ if (envoy_config_rbac_v3_RBAC_policies_size(rules) != 0) {
Json::Object policies_object;
size_t iter = kUpb_Map_Begin;
while (true) {
diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_lb_policy_registry.cc b/contrib/libs/grpc/src/core/ext/xds/xds_lb_policy_registry.cc
index 4ecdabd9fe..7455d17281 100644
--- a/contrib/libs/grpc/src/core/ext/xds/xds_lb_policy_registry.cc
+++ b/contrib/libs/grpc/src/core/ext/xds/xds_lb_policy_registry.cc
@@ -125,6 +125,19 @@ class ClientSideWeightedRoundRobinLbPolicyConfigFactory
Duration duration = ParseDuration(duration_proto, errors);
config["weightExpirationPeriod"] = duration.ToJsonString();
}
+ // error_utilization_penalty
+ auto* error_utilization_penalty =
+ envoy_extensions_load_balancing_policies_client_side_weighted_round_robin_v3_ClientSideWeightedRoundRobin_error_utilization_penalty(
+ resource);
+ if (error_utilization_penalty != nullptr) {
+ ValidationErrors::ScopedField field(errors, ".error_utilization_penalty");
+ const float value =
+ google_protobuf_FloatValue_value(error_utilization_penalty);
+ if (value < 0.0) {
+ errors->AddError("value must be non-negative");
+ }
+ config["errorUtilizationPenalty"] = value;
+ }
return Json::Object{
{"weighted_round_robin_experimental", std::move(config)}};
}
diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_transport_grpc.cc b/contrib/libs/grpc/src/core/ext/xds/xds_transport_grpc.cc
index bef66a78c6..e5d4482902 100644
--- a/contrib/libs/grpc/src/core/ext/xds/xds_transport_grpc.cc
+++ b/contrib/libs/grpc/src/core/ext/xds/xds_transport_grpc.cc
@@ -291,7 +291,7 @@ GrpcXdsTransportFactory::GrpcXdsTransport::GrpcXdsTransport(
}
GrpcXdsTransportFactory::GrpcXdsTransport::~GrpcXdsTransport() {
- grpc_channel_destroy(channel_);
+ grpc_channel_destroy_internal(channel_);
}
void GrpcXdsTransportFactory::GrpcXdsTransport::Orphan() {
diff --git a/contrib/libs/grpc/src/core/lib/channel/call_finalization.h b/contrib/libs/grpc/src/core/lib/channel/call_finalization.h
index dcab5c25fa..793586f0e3 100644
--- a/contrib/libs/grpc/src/core/lib/channel/call_finalization.h
+++ b/contrib/libs/grpc/src/core/lib/channel/call_finalization.h
@@ -36,7 +36,7 @@ class CallFinalization {
public:
// Add a step to the finalization context.
// Takes a callable with a signature compatible with:
- // (const grpc_call_final_info&) -> void.
+ // (const grpc_call_final_info*) -> void.
// Finalizers are run in the reverse order they are added.
template <typename F>
void Add(F&& t) {
diff --git a/contrib/libs/grpc/src/core/lib/channel/call_tracer.cc b/contrib/libs/grpc/src/core/lib/channel/call_tracer.cc
new file mode 100644
index 0000000000..e73b594d91
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/channel/call_tracer.cc
@@ -0,0 +1,51 @@
+//
+//
+// Copyright 2023 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/channel/call_tracer.h"
+
+namespace grpc_core {
+
+//
+// ServerCallTracerFactory
+//
+
+namespace {
+ServerCallTracerFactory* g_server_call_tracer_factory_ = nullptr;
+
+const char* kServerCallTracerFactoryChannelArgName =
+ "grpc.experimental.server_call_tracer_factory";
+} // namespace
+
+ServerCallTracerFactory* ServerCallTracerFactory::Get(
+ const ChannelArgs& channel_args) {
+ ServerCallTracerFactory* factory =
+ channel_args.GetObject<ServerCallTracerFactory>();
+ return factory != nullptr ? factory : g_server_call_tracer_factory_;
+}
+
+void ServerCallTracerFactory::RegisterGlobal(ServerCallTracerFactory* factory) {
+ g_server_call_tracer_factory_ = factory;
+}
+
+y_absl::string_view ServerCallTracerFactory::ChannelArgName() {
+ return kServerCallTracerFactoryChannelArgName;
+}
+
+} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/channel/call_tracer.h b/contrib/libs/grpc/src/core/lib/channel/call_tracer.h
index 80eaa4776a..705c630f9b 100644
--- a/contrib/libs/grpc/src/core/lib/channel/call_tracer.h
+++ b/contrib/libs/grpc/src/core/lib/channel/call_tracer.h
@@ -21,83 +21,147 @@
#include <grpc/support/port_platform.h>
-#include <stdint.h>
+#include <util/generic/string.h>
+#include <util/string/cast.h>
#include "y_absl/status/status.h"
#include "y_absl/strings/string_view.h"
-#include <grpc/support/atm.h>
#include <grpc/support/time.h>
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
namespace grpc_core {
+// The interface hierarchy is as follows -
+// CallTracerAnnotationInterface
+// / \
+// ClientCallTracer CallTracerInterface
+// / \
+// CallAttemptTracer ServerCallTracer
+
+// The base class for all tracer implementations.
+class CallTracerAnnotationInterface {
+ public:
+ virtual ~CallTracerAnnotationInterface() {}
+ // Records an annotation on the call attempt.
+ // TODO(yashykt): If needed, extend this to attach attributes with
+ // annotations.
+ virtual void RecordAnnotation(y_absl::string_view annotation) = 0;
+ virtual TString TraceId() = 0;
+ virtual TString SpanId() = 0;
+ virtual bool IsSampled() = 0;
+};
+
+// The base class for CallAttemptTracer and ServerCallTracer.
+// TODO(yashykt): What's a better name for this?
+class CallTracerInterface : public CallTracerAnnotationInterface {
+ public:
+ ~CallTracerInterface() override {}
+ // Please refer to `grpc_transport_stream_op_batch_payload` for details on
+ // arguments.
+ virtual void RecordSendInitialMetadata(
+ grpc_metadata_batch* send_initial_metadata) = 0;
+ virtual void RecordSendTrailingMetadata(
+ grpc_metadata_batch* send_trailing_metadata) = 0;
+ virtual void RecordSendMessage(const SliceBuffer& send_message) = 0;
+ // Only invoked if message was actually compressed.
+ virtual void RecordSendCompressedMessage(
+ const SliceBuffer& send_compressed_message) = 0;
+ // The `RecordReceivedInitialMetadata()` and `RecordReceivedMessage()`
+ // methods should only be invoked when the metadata/message was
+ // successfully received, i.e., without any error.
+ virtual void RecordReceivedInitialMetadata(
+ grpc_metadata_batch* recv_initial_metadata) = 0;
+ virtual void RecordReceivedMessage(const SliceBuffer& recv_message) = 0;
+ // Only invoked if message was actually decompressed.
+ virtual void RecordReceivedDecompressedMessage(
+ const SliceBuffer& recv_decompressed_message) = 0;
+ virtual void RecordCancel(grpc_error_handle cancel_error) = 0;
+};
+
// Interface for a tracer that records activities on a call. Actual attempts for
// this call are traced with CallAttemptTracer after invoking RecordNewAttempt()
-// on the CallTracer object.
-class CallTracer {
+// on the ClientCallTracer object.
+class ClientCallTracer : public CallTracerAnnotationInterface {
public:
// Interface for a tracer that records activities on a particular call
// attempt.
// (A single RPC can have multiple attempts due to retry/hedging policies or
// as transparent retry attempts.)
- class CallAttemptTracer {
+ class CallAttemptTracer : public CallTracerInterface {
public:
- virtual ~CallAttemptTracer() {}
- // Please refer to `grpc_transport_stream_op_batch_payload` for details on
- // arguments.
- virtual void RecordSendInitialMetadata(
- grpc_metadata_batch* send_initial_metadata) = 0;
- // TODO(yashkt): We are using gpr_atm here instead of y_absl::string_view
- // since that's what the transport API uses, and performing an atomic load
- // is unnecessary if the census tracer does not need it at present. Fix this
- // when the transport API changes.
- virtual void RecordOnDoneSendInitialMetadata(gpr_atm* peer_string) = 0;
- virtual void RecordSendTrailingMetadata(
- grpc_metadata_batch* send_trailing_metadata) = 0;
- virtual void RecordSendMessage(const SliceBuffer& send_message) = 0;
- // The `RecordReceivedInitialMetadata()` and `RecordReceivedMessage()`
- // methods should only be invoked when the metadata/message was
- // successfully received, i.e., without any error.
- virtual void RecordReceivedInitialMetadata(
- grpc_metadata_batch* recv_initial_metadata, uint32_t flags) = 0;
- virtual void RecordReceivedMessage(const SliceBuffer& recv_message) = 0;
+ ~CallAttemptTracer() override {}
+ // TODO(yashykt): The following two methods `RecordReceivedTrailingMetadata`
+ // and `RecordEnd` should be moved into CallTracerInterface.
// If the call was cancelled before the recv_trailing_metadata op
// was started, recv_trailing_metadata and transport_stream_stats
// will be null.
virtual void RecordReceivedTrailingMetadata(
y_absl::Status status, grpc_metadata_batch* recv_trailing_metadata,
const grpc_transport_stream_stats* transport_stream_stats) = 0;
- virtual void RecordCancel(grpc_error_handle cancel_error) = 0;
// Should be the last API call to the object. Once invoked, the tracer
// library is free to destroy the object.
virtual void RecordEnd(const gpr_timespec& latency) = 0;
- // Records an annotation on the call attempt.
- // TODO(yashykt): If needed, extend this to attach attributes with
- // annotations.
- virtual void RecordAnnotation(y_absl::string_view annotation) = 0;
};
- virtual ~CallTracer() {}
+ ~ClientCallTracer() override {}
// Records a new attempt for the associated call. \a transparent denotes
// whether the attempt is being made as a transparent retry or as a
// non-transparent retry/heding attempt. (There will be at least one attempt
- // even if the call is not being retried.) The `CallTracer` object retains
- // ownership to the newly created `CallAttemptTracer` object. RecordEnd()
- // serves as an indication that the call stack is done with all API calls, and
- // the tracer library is free to destroy it after that.
+ // even if the call is not being retried.) The `ClientCallTracer` object
+ // retains ownership to the newly created `CallAttemptTracer` object.
+ // RecordEnd() serves as an indication that the call stack is done with all
+ // API calls, and the tracer library is free to destroy it after that.
virtual CallAttemptTracer* StartNewAttempt(bool is_transparent_retry) = 0;
- // Records an annotation on the call attempt.
- // TODO(yashykt): If needed, extend this to attach attributes with
- // annotations.
- virtual void RecordAnnotation(y_absl::string_view annotation) = 0;
};
+// Interface for a tracer that records activities on a server call.
+class ServerCallTracer : public CallTracerInterface {
+ public:
+ ~ServerCallTracer() override {}
+ // TODO(yashykt): The following two methods `RecordReceivedTrailingMetadata`
+ // and `RecordEnd` should be moved into CallTracerInterface.
+ virtual void RecordReceivedTrailingMetadata(
+ grpc_metadata_batch* recv_trailing_metadata) = 0;
+ // Should be the last API call to the object. Once invoked, the tracer
+ // library is free to destroy the object.
+ virtual void RecordEnd(const grpc_call_final_info* final_info) = 0;
+};
+
+// Interface for a factory that can create a ServerCallTracer object per
+// server call.
+class ServerCallTracerFactory {
+ public:
+ struct RawPointerChannelArgTag {};
+
+ virtual ~ServerCallTracerFactory() {}
+
+ virtual ServerCallTracer* CreateNewServerCallTracer(Arena* arena) = 0;
+
+ // Use this method to get the server call tracer factory from channel args,
+ // instead of directly fetching it with `GetObject`.
+ static ServerCallTracerFactory* Get(const ChannelArgs& channel_args);
+
+ // Registers a global ServerCallTracerFactory that wil be used by default if
+ // no corresponding channel arg was found. It is only valid to call this
+ // before grpc_init(). It is the responsibility of the caller to maintain
+ // this for the lifetime of the process.
+ static void RegisterGlobal(ServerCallTracerFactory* factory);
+
+ static y_absl::string_view ChannelArgName();
+};
+
+void RegisterServerCallTracerFilter(CoreConfiguration::Builder* builder);
+
} // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_CHANNEL_CALL_TRACER_H
diff --git a/contrib/libs/grpc/src/core/lib/channel/connected_channel.cc b/contrib/libs/grpc/src/core/lib/channel/connected_channel.cc
index ce92ee52fc..88105226c6 100644
--- a/contrib/libs/grpc/src/core/lib/channel/connected_channel.cc
+++ b/contrib/libs/grpc/src/core/lib/channel/connected_channel.cc
@@ -21,22 +21,17 @@
#include "src/core/lib/channel/connected_channel.h"
#include <inttypes.h>
-#include <string.h>
-#include <algorithm>
#include <functional>
#include <initializer_list>
#include <memory>
#include <util/generic/string.h>
#include <util/string/cast.h>
+#include <type_traits>
#include <utility>
-#include <vector>
-#include "y_absl/base/thread_annotations.h"
-#include "y_absl/container/inlined_vector.h"
#include "y_absl/status/status.h"
-#include "y_absl/strings/str_cat.h"
-#include "y_absl/strings/str_join.h"
+#include "y_absl/status/statusor.h"
#include "y_absl/types/optional.h"
#include "y_absl/types/variant.h"
@@ -48,39 +43,48 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_fwd.h"
#include "src/core/lib/channel/channel_stack.h"
-#include "src/core/lib/channel/context.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/gpr/alloc.h"
#include "src/core/lib/gprpp/debug_location.h"
-#include "src/core/lib/gprpp/match.h"
#include "src/core/lib/gprpp/orphanable.h"
-#include "src/core/lib/gprpp/status_helper.h"
-#include "src/core/lib/gprpp/sync.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/call_combiner.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/error.h"
-#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/promise/activity.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/context.h"
+#include "src/core/lib/promise/detail/basic_join.h"
#include "src/core/lib/promise/detail/basic_seq.h"
+#include "src/core/lib/promise/for_each.h"
+#include "src/core/lib/promise/if.h"
+#include "src/core/lib/promise/latch.h"
+#include "src/core/lib/promise/loop.h"
+#include "src/core/lib/promise/map.h"
+#include "src/core/lib/promise/party.h"
#include "src/core/lib/promise/pipe.h"
#include "src/core/lib/promise/poll.h"
+#include "src/core/lib/promise/promise.h"
+#include "src/core/lib/promise/race.h"
+#include "src/core/lib/promise/seq.h"
+#include "src/core/lib/promise/try_join.h"
+#include "src/core/lib/promise/try_seq.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/call_trace.h"
#include "src/core/lib/surface/channel_stack_type.h"
+#include "src/core/lib/transport/batch_builder.h"
+#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/lib/transport/transport_fwd.h"
#include "src/core/lib/transport/transport_impl.h"
-#define MAX_BUFFER_LENGTH 8192
-
typedef struct connected_channel_channel_data {
grpc_transport* transport;
} channel_data;
@@ -253,10 +257,24 @@ namespace {
defined(GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_SERVER_CALL)
class ConnectedChannelStream : public Orphanable {
public:
+ explicit ConnectedChannelStream(grpc_transport* transport)
+ : transport_(transport), stream_(nullptr, StreamDeleter(this)) {
+ GRPC_STREAM_REF_INIT(
+ &stream_refcount_, 1,
+ [](void* p, grpc_error_handle) {
+ static_cast<ConnectedChannelStream*>(p)->BeginDestroy();
+ },
+ this, "ConnectedChannelStream");
+ }
+
grpc_transport* transport() { return transport_; }
grpc_closure* stream_destroyed_closure() { return &stream_destroyed_; }
- void IncrementRefCount(const char* reason) {
+ BatchBuilder::Target batch_target() {
+ return BatchBuilder::Target{transport_, stream_.get(), &stream_refcount_};
+ }
+
+ void IncrementRefCount(const char* reason = "smartptr") {
#ifndef NDEBUG
grpc_stream_ref(&stream_refcount_, reason);
#else
@@ -265,7 +283,7 @@ class ConnectedChannelStream : public Orphanable {
#endif
}
- void Unref(const char* reason) {
+ void Unref(const char* reason = "smartptr") {
#ifndef NDEBUG
grpc_stream_unref(&stream_refcount_, reason);
#else
@@ -274,234 +292,48 @@ class ConnectedChannelStream : public Orphanable {
#endif
}
+ RefCountedPtr<ConnectedChannelStream> InternalRef() {
+ IncrementRefCount("smartptr");
+ return RefCountedPtr<ConnectedChannelStream>(this);
+ }
+
void Orphan() final {
- bool finished;
- {
- MutexLock lock(mu());
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[connected] DropStream: %s finished=%s",
- Activity::current()->DebugTag().c_str(),
- ActiveOpsString().c_str(), finished_ ? "true" : "false");
- }
- finished = finished_;
+ bool finished = finished_.IsSet();
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[connected] Orphan stream, finished: %d",
+ party_->DebugTag().c_str(), finished);
}
// If we hadn't already observed the stream to be finished, we need to
// cancel it at the transport.
if (!finished) {
- IncrementRefCount("shutdown client stream");
- auto* cancel_op =
- GetContext<Arena>()->New<grpc_transport_stream_op_batch>();
- cancel_op->cancel_stream = true;
- cancel_op->payload = batch_payload();
- auto* s = stream();
- cancel_op->on_complete = NewClosure(
- [this](grpc_error_handle) { Unref("shutdown client stream"); });
- batch_payload()->cancel_stream.cancel_error = y_absl::CancelledError();
- grpc_transport_perform_stream_op(transport(), s, cancel_op);
+ party_->Spawn(
+ "finish",
+ [self = InternalRef()]() {
+ if (!self->finished_.IsSet()) {
+ self->finished_.Set();
+ }
+ return Empty{};
+ },
+ [](Empty) {});
+ GetContext<BatchBuilder>()->Cancel(batch_target(),
+ y_absl::CancelledError());
}
- Unref("orphan client stream");
+ Unref("orphan connected stream");
}
- protected:
- explicit ConnectedChannelStream(grpc_transport* transport)
- : transport_(transport), stream_(nullptr, StreamDeleter(this)) {
- call_context_->IncrementRefCount("connected_channel_stream");
- GRPC_STREAM_REF_INIT(
- &stream_refcount_, 1,
- [](void* p, grpc_error_handle) {
- static_cast<ConnectedChannelStream*>(p)->BeginDestroy();
- },
- this, "client_stream");
- }
+ // Returns a promise that implements the receive message loop.
+ auto RecvMessages(PipeSender<MessageHandle>* incoming_messages);
+ // Returns a promise that implements the send message loop.
+ auto SendMessages(PipeReceiver<MessageHandle>* outgoing_messages);
- grpc_stream* stream() { return stream_.get(); }
void SetStream(grpc_stream* stream) { stream_.reset(stream); }
+ grpc_stream* stream() { return stream_.get(); }
grpc_stream_refcount* stream_refcount() { return &stream_refcount_; }
- Mutex* mu() const Y_ABSL_LOCK_RETURNED(mu_) { return &mu_; }
- grpc_transport_stream_op_batch_payload* batch_payload() {
- return &batch_payload_;
- }
- bool finished() const Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) { return finished_; }
- void set_finished() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) { finished_ = true; }
- virtual TString ActiveOpsString() const
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) = 0;
- void SchedulePush(grpc_transport_stream_op_batch* batch)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%s[connected] Push batch to transport: %s",
- Activity::current()->DebugTag().c_str(),
- grpc_transport_stream_op_batch_string(batch).c_str());
- }
- if (push_batches_.empty()) {
- IncrementRefCount("push");
- ExecCtx::Run(DEBUG_LOCATION, &push_, y_absl::OkStatus());
- }
- push_batches_.push_back(batch);
- }
-
- void PollSendMessage(PipeReceiver<MessageHandle>* outgoing_messages,
- ClientMetadataHandle* client_trailing_metadata)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
- if (y_absl::holds_alternative<Closed>(send_message_state_)) {
- message_to_send_.reset();
- }
- if (y_absl::holds_alternative<Idle>(send_message_state_)) {
- message_to_send_.reset();
- send_message_state_.emplace<PipeReceiverNextType<MessageHandle>>(
- outgoing_messages->Next());
- }
- if (auto* next = y_absl::get_if<PipeReceiverNextType<MessageHandle>>(
- &send_message_state_)) {
- auto r = (*next)();
- if (auto* p = r.value_if_ready()) {
- memset(&send_message_, 0, sizeof(send_message_));
- send_message_.payload = batch_payload();
- send_message_.on_complete = &send_message_batch_done_;
- // No value => half close from above.
- if (p->has_value()) {
- message_to_send_ = std::move(*p);
- send_message_state_ = SendMessageToTransport{};
- send_message_.send_message = true;
- batch_payload()->send_message.send_message =
- (*message_to_send_)->payload();
- batch_payload()->send_message.flags = (*message_to_send_)->flags();
- } else {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[connected] PollConnectedChannel: half close",
- Activity::current()->DebugTag().c_str());
- }
- GPR_ASSERT(!y_absl::holds_alternative<Closed>(send_message_state_));
- send_message_state_ = Closed{};
- send_message_.send_trailing_metadata = true;
- if (client_trailing_metadata != nullptr) {
- *client_trailing_metadata =
- GetContext<Arena>()->MakePooled<ClientMetadata>(
- GetContext<Arena>());
- batch_payload()->send_trailing_metadata.send_trailing_metadata =
- client_trailing_metadata->get();
- batch_payload()->send_trailing_metadata.sent = nullptr;
- } else {
- return; // Skip rest of function for server
- }
- }
- IncrementRefCount("send_message");
- send_message_waker_ = Activity::current()->MakeOwningWaker();
- SchedulePush(&send_message_);
- }
- }
- }
-
- void PollRecvMessage(PipeSender<MessageHandle>*& incoming_messages)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
- if (auto* pending =
- y_absl::get_if<PendingReceiveMessage>(&recv_message_state_)) {
- if (pending->received) {
- if (pending->payload.has_value()) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[connected] PollRecvMessage: received payload of "
- "%" PRIdPTR " bytes",
- recv_message_waker_.ActivityDebugTag().c_str(),
- pending->payload->Length());
- }
- recv_message_state_ =
- incoming_messages->Push(GetContext<Arena>()->MakePooled<Message>(
- std::move(*pending->payload), pending->flags));
- } else {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[connected] PollRecvMessage: received no payload",
- recv_message_waker_.ActivityDebugTag().c_str());
- }
- recv_message_state_ = Closed{};
- std::exchange(incoming_messages, nullptr)->Close();
- }
- }
- }
- if (y_absl::holds_alternative<Idle>(recv_message_state_)) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[connected] PollRecvMessage: requesting message",
- Activity::current()->DebugTag().c_str());
- }
- PushRecvMessage();
- }
- if (auto* push = y_absl::get_if<PipeSender<MessageHandle>::PushType>(
- &recv_message_state_)) {
- auto r = (*push)();
- if (bool* result = r.value_if_ready()) {
- if (*result) {
- if (!finished_) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[connected] PollRecvMessage: pushed message; "
- "requesting next",
- Activity::current()->DebugTag().c_str());
- }
- PushRecvMessage();
- } else {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[connected] PollRecvMessage: pushed message "
- "and finished; "
- "marking closed",
- Activity::current()->DebugTag().c_str());
- }
- recv_message_state_ = Closed{};
- std::exchange(incoming_messages, nullptr)->Close();
- }
- } else {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[connected] PollRecvMessage: failed to push "
- "message; marking "
- "closed",
- Activity::current()->DebugTag().c_str());
- }
- recv_message_state_ = Closed{};
- std::exchange(incoming_messages, nullptr)->Close();
- }
- }
- }
- }
-
- TString SendMessageString() const Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu()) {
- return Match(
- send_message_state_, [](Idle) -> TString { return "IDLE"; },
- [](Closed) -> TString { return "CLOSED"; },
- [](const PipeReceiverNextType<MessageHandle>&) -> TString {
- return "WAITING";
- },
- [](SendMessageToTransport) -> TString { return "SENDING"; });
- }
-
- TString RecvMessageString() const Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu()) {
- return Match(
- recv_message_state_, [](Idle) -> TString { return "IDLE"; },
- [](Closed) -> TString { return "CLOSED"; },
- [](const PendingReceiveMessage&) -> TString { return "WAITING"; },
- [](const y_absl::optional<MessageHandle>& message) -> TString {
- return y_absl::StrCat(
- "READY:", message.has_value()
- ? y_absl::StrCat((*message)->payload()->Length(), "b")
- : "EOS");
- },
- [](const PipeSender<MessageHandle>::PushType&) -> TString {
- return "PUSHING";
- });
- }
-
- bool IsPromiseReceiving() const Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu()) {
- return y_absl::holds_alternative<PipeSender<MessageHandle>::PushType>(
- recv_message_state_) ||
- y_absl::holds_alternative<PendingReceiveMessage>(recv_message_state_);
- }
+ void set_finished() { finished_.Set(); }
+ auto WaitFinished() { return finished_.Wait(); }
private:
- struct SendMessageToTransport {};
- struct Idle {};
- struct Closed {};
-
class StreamDeleter {
public:
explicit StreamDeleter(ConnectedChannelStream* impl) : impl_(impl) {}
@@ -517,11 +349,7 @@ class ConnectedChannelStream : public Orphanable {
using StreamPtr = std::unique_ptr<grpc_stream, StreamDeleter>;
void StreamDestroyed() {
- call_context_->RunInContext([this] {
- auto* cc = call_context_;
- this->~ConnectedChannelStream();
- cc->Unref("child_stream");
- });
+ call_context_->RunInContext([this] { this->~ConnectedChannelStream(); });
}
void BeginDestroy() {
@@ -532,828 +360,434 @@ class ConnectedChannelStream : public Orphanable {
}
}
- // Called from outside the activity to push work down to the transport.
- void Push() {
- PushBatches push_batches;
- {
- MutexLock lock(&mu_);
- push_batches.swap(push_batches_);
- }
- for (auto* batch : push_batches) {
- if (stream() != nullptr) {
- grpc_transport_perform_stream_op(transport(), stream(), batch);
- } else {
- grpc_transport_stream_op_batch_finish_with_failure_from_transport(
- batch, y_absl::CancelledError());
- }
- }
- Unref("push");
- }
-
- void SendMessageBatchDone(grpc_error_handle error) {
- {
- MutexLock lock(&mu_);
- if (error != y_absl::OkStatus()) {
- // Note that we're in error here, the call will be closed by the
- // transport in a moment, and we'll return from the promise with an
- // error - so we don't need to do any extra work to close out pipes or
- // the like.
- send_message_state_ = Closed{};
- }
- if (!y_absl::holds_alternative<Closed>(send_message_state_)) {
- send_message_state_ = Idle{};
- }
- send_message_waker_.Wakeup();
- }
- Unref("send_message");
- }
-
- void RecvMessageBatchDone(grpc_error_handle error) {
- {
- MutexLock lock(mu());
- if (error != y_absl::OkStatus()) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[connected] RecvMessageBatchDone: error=%s",
- recv_message_waker_.ActivityDebugTag().c_str(),
- StatusToString(error).c_str());
- }
- } else if (y_absl::holds_alternative<Closed>(recv_message_state_)) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[connected] RecvMessageBatchDone: already closed, "
- "ignoring",
- recv_message_waker_.ActivityDebugTag().c_str());
- }
- } else {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[connected] RecvMessageBatchDone: received message",
- recv_message_waker_.ActivityDebugTag().c_str());
- }
- auto pending =
- y_absl::get_if<PendingReceiveMessage>(&recv_message_state_);
- GPR_ASSERT(pending != nullptr);
- GPR_ASSERT(pending->received == false);
- pending->received = true;
- }
- recv_message_waker_.Wakeup();
- }
- Unref("recv_message");
- }
-
- void PushRecvMessage() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
- recv_message_state_ = PendingReceiveMessage{};
- auto& pending_recv_message =
- y_absl::get<PendingReceiveMessage>(recv_message_state_);
- memset(&recv_message_, 0, sizeof(recv_message_));
- recv_message_.payload = batch_payload();
- recv_message_.on_complete = nullptr;
- recv_message_.recv_message = true;
- batch_payload()->recv_message.recv_message = &pending_recv_message.payload;
- batch_payload()->recv_message.flags = &pending_recv_message.flags;
- batch_payload()->recv_message.call_failed_before_recv_message = nullptr;
- batch_payload()->recv_message.recv_message_ready =
- &recv_message_batch_done_;
- IncrementRefCount("recv_message");
- recv_message_waker_ = Activity::current()->MakeOwningWaker();
- SchedulePush(&recv_message_);
- }
-
- mutable Mutex mu_;
grpc_transport* const transport_;
- CallContext* const call_context_{GetContext<CallContext>()};
+ RefCountedPtr<CallContext> const call_context_{
+ GetContext<CallContext>()->Ref()};
grpc_closure stream_destroyed_ =
MakeMemberClosure<ConnectedChannelStream,
&ConnectedChannelStream::StreamDestroyed>(
this, DEBUG_LOCATION);
grpc_stream_refcount stream_refcount_;
StreamPtr stream_;
- using PushBatches = y_absl::InlinedVector<grpc_transport_stream_op_batch*, 3>;
- PushBatches push_batches_ Y_ABSL_GUARDED_BY(mu_);
- grpc_closure push_ =
- MakeMemberClosure<ConnectedChannelStream, &ConnectedChannelStream::Push>(
- this, DEBUG_LOCATION);
-
- NextResult<MessageHandle> message_to_send_ Y_ABSL_GUARDED_BY(mu_);
- y_absl::variant<Idle, Closed, PipeReceiverNextType<MessageHandle>,
- SendMessageToTransport>
- send_message_state_ Y_ABSL_GUARDED_BY(mu_);
- grpc_transport_stream_op_batch send_message_;
- grpc_closure send_message_batch_done_ =
- MakeMemberClosure<ConnectedChannelStream,
- &ConnectedChannelStream::SendMessageBatchDone>(
- this, DEBUG_LOCATION);
-
- struct PendingReceiveMessage {
- y_absl::optional<SliceBuffer> payload;
- uint32_t flags;
- bool received = false;
- };
- y_absl::variant<Idle, PendingReceiveMessage, Closed,
- PipeSender<MessageHandle>::PushType>
- recv_message_state_ Y_ABSL_GUARDED_BY(mu_);
- grpc_closure recv_message_batch_done_ =
- MakeMemberClosure<ConnectedChannelStream,
- &ConnectedChannelStream::RecvMessageBatchDone>(
- this, DEBUG_LOCATION);
- grpc_transport_stream_op_batch recv_message_;
-
- Waker send_message_waker_ Y_ABSL_GUARDED_BY(mu_);
- Waker recv_message_waker_ Y_ABSL_GUARDED_BY(mu_);
- bool finished_ Y_ABSL_GUARDED_BY(mu_) = false;
-
- grpc_transport_stream_op_batch_payload batch_payload_{
- GetContext<grpc_call_context_element>()};
-};
-#endif
-
-#ifdef GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_CLIENT_CALL
-class ClientStream : public ConnectedChannelStream {
- public:
- ClientStream(grpc_transport* transport, CallArgs call_args)
- : ConnectedChannelStream(transport),
- server_initial_metadata_pipe_(call_args.server_initial_metadata),
- client_to_server_messages_(call_args.client_to_server_messages),
- server_to_client_messages_(call_args.server_to_client_messages),
- client_initial_metadata_(std::move(call_args.client_initial_metadata)) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[connected] InitImpl: intitial_metadata=%s",
- Activity::current()->DebugTag().c_str(),
- client_initial_metadata_->DebugString().c_str());
- }
- }
-
- Poll<ServerMetadataHandle> PollOnce() {
- MutexLock lock(mu());
- GPR_ASSERT(!finished());
-
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[connected] PollConnectedChannel: %s",
- Activity::current()->DebugTag().c_str(),
- ActiveOpsString().c_str());
- }
-
- if (!std::exchange(requested_metadata_, true)) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[connected] PollConnectedChannel: requesting metadata",
- Activity::current()->DebugTag().c_str());
- }
- SetStream(static_cast<grpc_stream*>(
- GetContext<Arena>()->Alloc(transport()->vtable->sizeof_stream)));
- grpc_transport_init_stream(transport(), stream(), stream_refcount(),
- nullptr, GetContext<Arena>());
- grpc_transport_set_pops(transport(), stream(),
- GetContext<CallContext>()->polling_entity());
- memset(&metadata_, 0, sizeof(metadata_));
- metadata_.send_initial_metadata = true;
- metadata_.recv_initial_metadata = true;
- metadata_.recv_trailing_metadata = true;
- metadata_.payload = batch_payload();
- metadata_.on_complete = &metadata_batch_done_;
- batch_payload()->send_initial_metadata.send_initial_metadata =
- client_initial_metadata_.get();
- batch_payload()->send_initial_metadata.peer_string =
- GetContext<CallContext>()->peer_string_atm_ptr();
- server_initial_metadata_ =
- GetContext<Arena>()->MakePooled<ServerMetadata>(GetContext<Arena>());
- batch_payload()->recv_initial_metadata.recv_initial_metadata =
- server_initial_metadata_.get();
- batch_payload()->recv_initial_metadata.recv_initial_metadata_ready =
- &recv_initial_metadata_ready_;
- batch_payload()->recv_initial_metadata.trailing_metadata_available =
- nullptr;
- batch_payload()->recv_initial_metadata.peer_string = nullptr;
- server_trailing_metadata_ =
- GetContext<Arena>()->MakePooled<ServerMetadata>(GetContext<Arena>());
- batch_payload()->recv_trailing_metadata.recv_trailing_metadata =
- server_trailing_metadata_.get();
- batch_payload()->recv_trailing_metadata.collect_stats =
- &GetContext<CallContext>()->call_stats()->transport_stream_stats;
- batch_payload()->recv_trailing_metadata.recv_trailing_metadata_ready =
- &recv_trailing_metadata_ready_;
- IncrementRefCount("metadata_batch_done");
- IncrementRefCount("initial_metadata_ready");
- IncrementRefCount("trailing_metadata_ready");
- initial_metadata_waker_ = Activity::current()->MakeOwningWaker();
- trailing_metadata_waker_ = Activity::current()->MakeOwningWaker();
- SchedulePush(&metadata_);
- }
- if (server_initial_metadata_state_ ==
- ServerInitialMetadataState::kReceivedButNotPushed) {
- server_initial_metadata_state_ = ServerInitialMetadataState::kPushing;
- server_initial_metadata_push_promise_ =
- server_initial_metadata_pipe_->Push(
- std::move(server_initial_metadata_));
- }
- if (server_initial_metadata_state_ ==
- ServerInitialMetadataState::kPushing) {
- auto r = (*server_initial_metadata_push_promise_)();
- if (r.ready()) {
- server_initial_metadata_state_ = ServerInitialMetadataState::kPushed;
- server_initial_metadata_push_promise_.reset();
- }
- }
- PollSendMessage(client_to_server_messages_, &client_trailing_metadata_);
- PollRecvMessage(server_to_client_messages_);
- if (server_initial_metadata_state_ == ServerInitialMetadataState::kPushed &&
- !IsPromiseReceiving() &&
- std::exchange(queued_trailing_metadata_, false)) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[connected] PollConnectedChannel: finished request, "
- "returning: {%s}; "
- "active_ops: %s",
- Activity::current()->DebugTag().c_str(),
- server_trailing_metadata_->DebugString().c_str(),
- ActiveOpsString().c_str());
- }
- set_finished();
- return ServerMetadataHandle(std::move(server_trailing_metadata_));
- }
- return Pending{};
- }
-
- void RecvInitialMetadataReady(grpc_error_handle error) {
- GPR_ASSERT(error == y_absl::OkStatus());
- {
- MutexLock lock(mu());
- server_initial_metadata_state_ =
- ServerInitialMetadataState::kReceivedButNotPushed;
- initial_metadata_waker_.Wakeup();
- }
- Unref("initial_metadata_ready");
- }
-
- void RecvTrailingMetadataReady(grpc_error_handle error) {
- GPR_ASSERT(error == y_absl::OkStatus());
- {
- MutexLock lock(mu());
- queued_trailing_metadata_ = true;
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_DEBUG,
- "%s[connected] RecvTrailingMetadataReady: "
- "queued_trailing_metadata_ "
- "set to true; active_ops: %s",
- trailing_metadata_waker_.ActivityDebugTag().c_str(),
- ActiveOpsString().c_str());
- }
- trailing_metadata_waker_.Wakeup();
- }
- Unref("trailing_metadata_ready");
- }
-
- void MetadataBatchDone(grpc_error_handle error) {
- GPR_ASSERT(error == y_absl::OkStatus());
- Unref("metadata_batch_done");
- }
-
- private:
- enum class ServerInitialMetadataState : uint8_t {
- // Initial metadata has not been received from the server.
- kNotReceived,
- // Initial metadata has been received from the server via the transport, but
- // has not yet been pushed onto the pipe to publish it up the call stack.
- kReceivedButNotPushed,
- // Initial metadata has been received from the server via the transport and
- // has been pushed on the pipe to publish it up the call stack.
- // It's still in the pipe and has not been removed by the call at the top
- // yet.
- kPushing,
- // Initial metadata has been received from the server via the transport and
- // has been pushed on the pipe to publish it up the call stack AND removed
- // by the call at the top.
- kPushed,
- };
-
- TString ActiveOpsString() const override
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu()) {
- std::vector<TString> ops;
- if (finished()) ops.push_back("FINISHED");
- // Outstanding Operations on Transport
- std::vector<TString> waiting;
- if (initial_metadata_waker_ != Waker()) {
- waiting.push_back("initial_metadata");
- }
- if (trailing_metadata_waker_ != Waker()) {
- waiting.push_back("trailing_metadata");
- }
- if (!waiting.empty()) {
- ops.push_back(y_absl::StrCat("waiting:", y_absl::StrJoin(waiting, ",")));
- }
- // Results from transport
- std::vector<TString> queued;
- if (server_initial_metadata_state_ ==
- ServerInitialMetadataState::kReceivedButNotPushed) {
- queued.push_back("initial_metadata");
- }
- if (queued_trailing_metadata_) queued.push_back("trailing_metadata");
- if (!queued.empty()) {
- ops.push_back(y_absl::StrCat("queued:", y_absl::StrJoin(queued, ",")));
- }
- // Send message
- TString send_message_state = SendMessageString();
- if (send_message_state != "WAITING") {
- ops.push_back(y_absl::StrCat("send_message:", send_message_state));
- }
- // Receive message
- TString recv_message_state = RecvMessageString();
- if (recv_message_state != "IDLE") {
- ops.push_back(y_absl::StrCat("recv_message:", recv_message_state));
- }
- return y_absl::StrJoin(ops, " ");
- }
-
- bool requested_metadata_ = false;
- ServerInitialMetadataState server_initial_metadata_state_
- Y_ABSL_GUARDED_BY(mu()) = ServerInitialMetadataState::kNotReceived;
- bool queued_trailing_metadata_ Y_ABSL_GUARDED_BY(mu()) = false;
- Waker initial_metadata_waker_ Y_ABSL_GUARDED_BY(mu());
- Waker trailing_metadata_waker_ Y_ABSL_GUARDED_BY(mu());
- PipeSender<ServerMetadataHandle>* server_initial_metadata_pipe_;
- PipeReceiver<MessageHandle>* client_to_server_messages_;
- PipeSender<MessageHandle>* server_to_client_messages_;
- grpc_closure recv_initial_metadata_ready_ =
- MakeMemberClosure<ClientStream, &ClientStream::RecvInitialMetadataReady>(
- this, DEBUG_LOCATION);
- grpc_closure recv_trailing_metadata_ready_ =
- MakeMemberClosure<ClientStream, &ClientStream::RecvTrailingMetadataReady>(
- this, DEBUG_LOCATION);
- ClientMetadataHandle client_initial_metadata_;
- ClientMetadataHandle client_trailing_metadata_;
- ServerMetadataHandle server_initial_metadata_;
- ServerMetadataHandle server_trailing_metadata_;
- y_absl::optional<PipeSender<ServerMetadataHandle>::PushType>
- server_initial_metadata_push_promise_;
- grpc_transport_stream_op_batch metadata_;
- grpc_closure metadata_batch_done_ =
- MakeMemberClosure<ClientStream, &ClientStream::MetadataBatchDone>(
- this, DEBUG_LOCATION);
+ Arena* arena_ = GetContext<Arena>();
+ Party* const party_ = static_cast<Party*>(Activity::current());
+ ExternallyObservableLatch<void> finished_;
};
-class ClientConnectedCallPromise {
- public:
- ClientConnectedCallPromise(grpc_transport* transport, CallArgs call_args)
- : impl_(GetContext<Arena>()->New<ClientStream>(transport,
- std::move(call_args))) {}
-
- ClientConnectedCallPromise(const ClientConnectedCallPromise&) = delete;
- ClientConnectedCallPromise& operator=(const ClientConnectedCallPromise&) =
- delete;
- ClientConnectedCallPromise(ClientConnectedCallPromise&& other) noexcept
- : impl_(std::exchange(other.impl_, nullptr)) {}
- ClientConnectedCallPromise& operator=(
- ClientConnectedCallPromise&& other) noexcept {
- impl_ = std::move(other.impl_);
- return *this;
- }
-
- static ArenaPromise<ServerMetadataHandle> Make(grpc_transport* transport,
- CallArgs call_args,
- NextPromiseFactory) {
- return ClientConnectedCallPromise(transport, std::move(call_args));
- }
+auto ConnectedChannelStream::RecvMessages(
+ PipeSender<MessageHandle>* incoming_messages) {
+ return Loop([self = InternalRef(),
+ incoming_messages = std::move(*incoming_messages)]() mutable {
+ return Seq(
+ GetContext<BatchBuilder>()->ReceiveMessage(self->batch_target()),
+ [&incoming_messages](
+ y_absl::StatusOr<y_absl::optional<MessageHandle>> status) mutable {
+ bool has_message = status.ok() && status->has_value();
+ auto publish_message = [&incoming_messages, &status]() {
+ auto pending_message = std::move(**status);
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "%s[connected] RecvMessage: received payload of %" PRIdPTR
+ " bytes",
+ Activity::current()->DebugTag().c_str(),
+ pending_message->payload()->Length());
+ }
+ return Map(incoming_messages.Push(std::move(pending_message)),
+ [](bool ok) -> LoopCtl<y_absl::Status> {
+ if (!ok) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "%s[connected] RecvMessage: failed to "
+ "push message towards the application",
+ Activity::current()->DebugTag().c_str());
+ }
+ return y_absl::OkStatus();
+ }
+ return Continue{};
+ });
+ };
+ auto publish_close = [&status]() mutable {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "%s[connected] RecvMessage: reached end of stream with "
+ "status:%s",
+ Activity::current()->DebugTag().c_str(),
+ status.status().ToString().c_str());
+ }
+ return Immediate(LoopCtl<y_absl::Status>(status.status()));
+ };
+ return If(has_message, std::move(publish_message),
+ std::move(publish_close));
+ });
+ });
+}
- Poll<ServerMetadataHandle> operator()() { return impl_->PollOnce(); }
+auto ConnectedChannelStream::SendMessages(
+ PipeReceiver<MessageHandle>* outgoing_messages) {
+ return ForEach(std::move(*outgoing_messages),
+ [self = InternalRef()](MessageHandle message) {
+ return GetContext<BatchBuilder>()->SendMessage(
+ self->batch_target(), std::move(message));
+ });
+}
+#endif // defined(GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_CLIENT_CALL) ||
+ // defined(GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_SERVER_CALL)
- private:
- OrphanablePtr<ClientStream> impl_;
-};
+#ifdef GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_CLIENT_CALL
+ArenaPromise<ServerMetadataHandle> MakeClientCallPromise(
+ grpc_transport* transport, CallArgs call_args, NextPromiseFactory) {
+ OrphanablePtr<ConnectedChannelStream> stream(
+ GetContext<Arena>()->New<ConnectedChannelStream>(transport));
+ stream->SetStream(static_cast<grpc_stream*>(
+ GetContext<Arena>()->Alloc(transport->vtable->sizeof_stream)));
+ grpc_transport_init_stream(transport, stream->stream(),
+ stream->stream_refcount(), nullptr,
+ GetContext<Arena>());
+ grpc_transport_set_pops(transport, stream->stream(),
+ GetContext<CallContext>()->polling_entity());
+ auto* party = static_cast<Party*>(Activity::current());
+ // Start a loop to send messages from client_to_server_messages to the
+ // transport. When the pipe closes and the loop completes, send a trailing
+ // metadata batch to close the stream.
+ party->Spawn(
+ "send_messages",
+ TrySeq(stream->SendMessages(call_args.client_to_server_messages),
+ [stream = stream->InternalRef()]() {
+ return GetContext<BatchBuilder>()->SendClientTrailingMetadata(
+ stream->batch_target());
+ }),
+ [](y_absl::Status) {});
+ // Start a promise to receive server initial metadata and then forward it up
+ // through the receiving pipe.
+ auto server_initial_metadata =
+ GetContext<Arena>()->MakePooled<ServerMetadata>(GetContext<Arena>());
+ party->Spawn(
+ "recv_initial_metadata",
+ TrySeq(GetContext<BatchBuilder>()->ReceiveServerInitialMetadata(
+ stream->batch_target()),
+ [pipe = call_args.server_initial_metadata](
+ ServerMetadataHandle server_initial_metadata) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG,
+ "%s[connected] Publish client initial metadata: %s",
+ Activity::current()->DebugTag().c_str(),
+ server_initial_metadata->DebugString().c_str());
+ }
+ return Map(pipe->Push(std::move(server_initial_metadata)),
+ [](bool r) {
+ if (r) return y_absl::OkStatus();
+ return y_absl::CancelledError();
+ });
+ }),
+ [](y_absl::Status) {});
+
+ // Build up the rest of the main call promise:
+
+ // Create a promise that will send initial metadata and then signal completion
+ // of that via the token.
+ auto send_initial_metadata = Seq(
+ GetContext<BatchBuilder>()->SendClientInitialMetadata(
+ stream->batch_target(), std::move(call_args.client_initial_metadata)),
+ [sent_initial_metadata_token =
+ std::move(call_args.client_initial_metadata_outstanding)](
+ y_absl::Status status) mutable {
+ sent_initial_metadata_token.Complete(status.ok());
+ return status;
+ });
+ // Create a promise that will receive server trailing metadata.
+ // If this fails, we massage the error into metadata that we can report
+ // upwards.
+ auto server_trailing_metadata =
+ GetContext<Arena>()->MakePooled<ServerMetadata>(GetContext<Arena>());
+ auto recv_trailing_metadata =
+ Map(GetContext<BatchBuilder>()->ReceiveServerTrailingMetadata(
+ stream->batch_target()),
+ [](y_absl::StatusOr<ServerMetadataHandle> status) mutable {
+ if (!status.ok()) {
+ auto server_trailing_metadata =
+ GetContext<Arena>()->MakePooled<ServerMetadata>(
+ GetContext<Arena>());
+ grpc_status_code status_code = GRPC_STATUS_UNKNOWN;
+ TString message;
+ grpc_error_get_status(status.status(), Timestamp::InfFuture(),
+ &status_code, &message, nullptr, nullptr);
+ server_trailing_metadata->Set(GrpcStatusMetadata(), status_code);
+ server_trailing_metadata->Set(GrpcMessageMetadata(),
+ Slice::FromCopiedString(message));
+ return server_trailing_metadata;
+ } else {
+ return std::move(*status);
+ }
+ });
+ // Finally the main call promise.
+ // Concurrently: send initial metadata and receive messages, until BOTH
+ // complete (or one fails).
+ // Next: receive trailing metadata, and return that up the stack.
+ auto recv_messages =
+ stream->RecvMessages(call_args.server_to_client_messages);
+ return Map(TrySeq(TryJoin(std::move(send_initial_metadata),
+ std::move(recv_messages)),
+ std::move(recv_trailing_metadata)),
+ [stream = std::move(stream)](ServerMetadataHandle result) {
+ stream->set_finished();
+ return result;
+ });
+}
#endif
#ifdef GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_SERVER_CALL
-class ServerStream final : public ConnectedChannelStream {
- public:
- ServerStream(grpc_transport* transport,
- NextPromiseFactory next_promise_factory)
- : ConnectedChannelStream(transport) {
- SetStream(static_cast<grpc_stream*>(
- GetContext<Arena>()->Alloc(transport->vtable->sizeof_stream)));
- grpc_transport_init_stream(
- transport, stream(), stream_refcount(),
- GetContext<CallContext>()->server_call_context()->server_stream_data(),
- GetContext<Arena>());
- grpc_transport_set_pops(transport, stream(),
- GetContext<CallContext>()->polling_entity());
-
- // Fetch initial metadata
- auto& gim = call_state_.emplace<GettingInitialMetadata>(this);
- gim.recv_initial_metadata_ready_waker =
- Activity::current()->MakeOwningWaker();
- memset(&gim.recv_initial_metadata, 0, sizeof(gim.recv_initial_metadata));
- gim.recv_initial_metadata.payload = batch_payload();
- gim.recv_initial_metadata.on_complete = nullptr;
- gim.recv_initial_metadata.recv_initial_metadata = true;
- gim.next_promise_factory = std::move(next_promise_factory);
- batch_payload()->recv_initial_metadata.recv_initial_metadata =
- gim.client_initial_metadata.get();
- batch_payload()->recv_initial_metadata.recv_initial_metadata_ready =
- &gim.recv_initial_metadata_ready;
- SchedulePush(&gim.recv_initial_metadata);
-
- // Fetch trailing metadata (to catch cancellations)
- auto& gtm =
- client_trailing_metadata_state_.emplace<WaitingForTrailingMetadata>();
- gtm.recv_trailing_metadata_ready =
- MakeMemberClosure<ServerStream,
- &ServerStream::RecvTrailingMetadataReady>(this);
- memset(&gtm.recv_trailing_metadata, 0, sizeof(gtm.recv_trailing_metadata));
- gtm.recv_trailing_metadata.payload = batch_payload();
- gtm.recv_trailing_metadata.recv_trailing_metadata = true;
- batch_payload()->recv_trailing_metadata.recv_trailing_metadata =
- gtm.result.get();
- batch_payload()->recv_trailing_metadata.collect_stats =
- &GetContext<CallContext>()->call_stats()->transport_stream_stats;
- batch_payload()->recv_trailing_metadata.recv_trailing_metadata_ready =
- &gtm.recv_trailing_metadata_ready;
- SchedulePush(&gtm.recv_trailing_metadata);
- gtm.waker = Activity::current()->MakeOwningWaker();
- }
-
- Poll<ServerMetadataHandle> PollOnce() {
- MutexLock lock(mu());
-
- auto poll_send_initial_metadata = [this]() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(
- mu()) {
- if (auto* promise =
- y_absl::get_if<PipeReceiverNextType<ServerMetadataHandle>>(
- &server_initial_metadata_)) {
- auto r = (*promise)();
- if (auto* md = r.value_if_ready()) {
- if (grpc_call_trace.enabled()) {
- gpr_log(
- GPR_INFO, "%s[connected] got initial metadata %s",
- Activity::current()->DebugTag().c_str(),
- (md->has_value() ? (**md)->DebugString() : "<trailers-only>")
- .c_str());
- }
- memset(&send_initial_metadata_, 0, sizeof(send_initial_metadata_));
- send_initial_metadata_.send_initial_metadata = true;
- send_initial_metadata_.payload = batch_payload();
- send_initial_metadata_.on_complete = &send_initial_metadata_done_;
- batch_payload()->send_initial_metadata.send_initial_metadata =
- server_initial_metadata_
- .emplace<ServerMetadataHandle>(std::move(**md))
- .get();
- batch_payload()->send_initial_metadata.peer_string = nullptr;
- SchedulePush(&send_initial_metadata_);
- return true;
- } else {
- return false;
- }
- } else {
- return true;
- }
- };
-
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[connected] PollConnectedChannel: %s",
- Activity::current()->DebugTag().c_str(),
- ActiveOpsString().c_str());
- }
-
- poll_send_initial_metadata();
-
- if (auto* p = y_absl::get_if<GotClientHalfClose>(
- &client_trailing_metadata_state_)) {
- pipes_.client_to_server.sender.Close();
- if (!p->result.ok()) {
- // client cancelled, we should cancel too
- if (y_absl::holds_alternative<y_absl::monostate>(call_state_) ||
- y_absl::holds_alternative<GotInitialMetadata>(call_state_) ||
- y_absl::holds_alternative<MessageLoop>(call_state_)) {
- if (!y_absl::holds_alternative<ServerMetadataHandle>(
- server_initial_metadata_)) {
- // pretend we've sent initial metadata to stop that op from
- // progressing if it's stuck somewhere above us in the stack
- server_initial_metadata_.emplace<ServerMetadataHandle>();
- }
- // cancel the call - this status will be returned to the server bottom
- // promise
- call_state_.emplace<Complete>(
- Complete{ServerMetadataFromStatus(p->result)});
- }
- }
- }
-
- if (auto* p = y_absl::get_if<GotInitialMetadata>(&call_state_)) {
- incoming_messages_ = &pipes_.client_to_server.sender;
- auto promise = p->next_promise_factory(CallArgs{
- std::move(p->client_initial_metadata),
- &pipes_.server_initial_metadata.sender,
- &pipes_.client_to_server.receiver, &pipes_.server_to_client.sender});
- call_state_.emplace<MessageLoop>(
- MessageLoop{&pipes_.server_to_client.receiver, std::move(promise)});
- server_initial_metadata_
- .emplace<PipeReceiverNextType<ServerMetadataHandle>>(
- pipes_.server_initial_metadata.receiver.Next());
- }
- if (incoming_messages_ != nullptr) {
- PollRecvMessage(incoming_messages_);
- }
- if (auto* p = y_absl::get_if<MessageLoop>(&call_state_)) {
- if (y_absl::holds_alternative<ServerMetadataHandle>(
- server_initial_metadata_)) {
- PollSendMessage(p->outgoing_messages, nullptr);
- }
- auto poll = p->promise();
- if (auto* r = poll.value_if_ready()) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[connected] got trailing metadata %s; %s",
- Activity::current()->DebugTag().c_str(),
- (*r)->DebugString().c_str(), ActiveOpsString().c_str());
- }
- auto& completing = call_state_.emplace<Completing>();
- completing.server_trailing_metadata = std::move(*r);
- completing.on_complete =
- MakeMemberClosure<ServerStream,
- &ServerStream::SendTrailingMetadataDone>(this);
- completing.waker = Activity::current()->MakeOwningWaker();
- auto& op = completing.send_trailing_metadata;
- memset(&op, 0, sizeof(op));
- op.payload = batch_payload();
- op.on_complete = &completing.on_complete;
- // If we've gotten initial server metadata, we can send trailing
- // metadata.
- // Otherwise we need to cancel the call.
- // There could be an unlucky ordering, so we poll here to make sure.
- if (poll_send_initial_metadata()) {
- op.send_trailing_metadata = true;
- batch_payload()->send_trailing_metadata.send_trailing_metadata =
- completing.server_trailing_metadata.get();
- batch_payload()->send_trailing_metadata.sent = &completing.sent;
- } else {
- op.cancel_stream = true;
- const auto status_code =
- completing.server_trailing_metadata->get(GrpcStatusMetadata())
- .value_or(GRPC_STATUS_UNKNOWN);
- batch_payload()->cancel_stream.cancel_error = grpc_error_set_int(
- y_absl::Status(static_cast<y_absl::StatusCode>(status_code),
- completing.server_trailing_metadata
- ->GetOrCreatePointer(GrpcMessageMetadata())
- ->as_string_view()),
- StatusIntProperty::kRpcStatus, status_code);
- }
- SchedulePush(&op);
- }
- }
- if (auto* p = y_absl::get_if<Complete>(&call_state_)) {
- set_finished();
- return std::move(p->result);
- }
- return Pending{};
- }
-
- private:
- // Call state: we've asked the transport for initial metadata and are
- // waiting for it before proceeding.
- struct GettingInitialMetadata {
- explicit GettingInitialMetadata(ServerStream* stream)
- : recv_initial_metadata_ready(
- MakeMemberClosure<ServerStream,
- &ServerStream::RecvInitialMetadataReady>(
- stream)) {}
- // The batch we're using to get initial metadata.
- grpc_transport_stream_op_batch recv_initial_metadata;
- // Waker to re-enter the activity once the transport returns.
- Waker recv_initial_metadata_ready_waker;
- // Initial metadata storage for the transport.
- ClientMetadataHandle client_initial_metadata =
- GetContext<Arena>()->MakePooled<ClientMetadata>(GetContext<Arena>());
- // Closure for the transport to call when it's ready.
- grpc_closure recv_initial_metadata_ready;
- // Next promise factory to use once we have initial metadata.
- NextPromiseFactory next_promise_factory;
- };
-
- // Call state: transport has returned initial metadata, we're waiting to
- // re-enter the activity to process it.
- struct GotInitialMetadata {
- ClientMetadataHandle client_initial_metadata;
- NextPromiseFactory next_promise_factory;
- };
-
- // Call state: we're sending/receiving messages and processing the filter
- // stack.
- struct MessageLoop {
- PipeReceiver<MessageHandle>* outgoing_messages;
- ArenaPromise<ServerMetadataHandle> promise;
- };
-
- // Call state: promise stack has returned trailing metadata, we're sending it
- // to the transport to communicate.
- struct Completing {
- ServerMetadataHandle server_trailing_metadata;
- grpc_transport_stream_op_batch send_trailing_metadata;
- grpc_closure on_complete;
- bool sent = false;
- Waker waker;
- };
-
- // Call state: server metadata has been communicated to the transport and sent
- // to the client.
- // The metadata will be returned down to the server call to tick the
- // cancellation bit or not on the originating batch.
- struct Complete {
- ServerMetadataHandle result;
- };
-
- // Trailing metadata state: we've asked the transport for trailing metadata
- // and are waiting for it before proceeding.
- struct WaitingForTrailingMetadata {
- ClientMetadataHandle result =
- GetContext<Arena>()->MakePooled<ClientMetadata>(GetContext<Arena>());
- grpc_transport_stream_op_batch recv_trailing_metadata;
- grpc_closure recv_trailing_metadata_ready;
- Waker waker;
- };
-
- // We've received trailing metadata from the transport - which indicates reads
- // are closed.
- // We convert to an y_absl::Status here and use that to drive a decision to
- // cancel the call (on error) or not.
- struct GotClientHalfClose {
- y_absl::Status result;
- };
-
- void RecvInitialMetadataReady(y_absl::Status status) {
- MutexLock lock(mu());
- auto& getting = y_absl::get<GettingInitialMetadata>(call_state_);
- auto waker = std::move(getting.recv_initial_metadata_ready_waker);
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%sGOT INITIAL METADATA: err=%s %s",
- waker.ActivityDebugTag().c_str(), status.ToString().c_str(),
- getting.client_initial_metadata->DebugString().c_str());
- }
- GotInitialMetadata got{std::move(getting.client_initial_metadata),
- std::move(getting.next_promise_factory)};
- call_state_.emplace<GotInitialMetadata>(std::move(got));
- waker.Wakeup();
- }
-
- void SendTrailingMetadataDone(y_absl::Status result) {
- MutexLock lock(mu());
- auto& completing = y_absl::get<Completing>(call_state_);
- auto md = std::move(completing.server_trailing_metadata);
- auto waker = std::move(completing.waker);
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%sSEND TRAILING METADATA DONE: err=%s sent=%s %s",
- waker.ActivityDebugTag().c_str(), result.ToString().c_str(),
- completing.sent ? "true" : "false", md->DebugString().c_str());
- }
- md->Set(GrpcStatusFromWire(), completing.sent);
- if (!result.ok()) {
- md->Clear();
- md->Set(GrpcStatusMetadata(),
- static_cast<grpc_status_code>(result.code()));
- md->Set(GrpcMessageMetadata(), Slice::FromCopiedString(result.message()));
- md->Set(GrpcStatusFromWire(), false);
- }
- call_state_.emplace<Complete>(Complete{std::move(md)});
- waker.Wakeup();
- }
-
- TString ActiveOpsString() const override
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu()) {
- std::vector<TString> ops;
- ops.push_back(y_absl::StrCat(
- "call_state:",
- Match(
- call_state_,
- [](const y_absl::monostate&) { return "y_absl::monostate"; },
- [](const GettingInitialMetadata&) { return "GETTING"; },
- [](const GotInitialMetadata&) { return "GOT"; },
- [](const MessageLoop&) { return "RUNNING"; },
- [](const Completing&) { return "COMPLETING"; },
- [](const Complete&) { return "COMPLETE"; })));
- ops.push_back(
- y_absl::StrCat("client_trailing_metadata_state:",
- Match(
- client_trailing_metadata_state_,
- [](const y_absl::monostate&) -> TString {
- return "y_absl::monostate";
- },
- [](const WaitingForTrailingMetadata&) -> TString {
- return "WAITING";
- },
- [](const GotClientHalfClose& got) -> TString {
- return y_absl::StrCat("GOT:", got.result.ToString());
- })));
- // Send initial metadata
- ops.push_back(y_absl::StrCat(
- "server_initial_metadata_state:",
- Match(
- server_initial_metadata_,
- [](const y_absl::monostate&) { return "y_absl::monostate"; },
- [](const PipeReceiverNextType<ServerMetadataHandle>&) {
- return "WAITING";
- },
- [](const ServerMetadataHandle&) { return "GOT"; })));
- // Send message
- TString send_message_state = SendMessageString();
- if (send_message_state != "WAITING") {
- ops.push_back(y_absl::StrCat("send_message:", send_message_state));
- }
- // Receive message
- TString recv_message_state = RecvMessageString();
- if (recv_message_state != "IDLE") {
- ops.push_back(y_absl::StrCat("recv_message:", recv_message_state));
- }
- return y_absl::StrJoin(ops, " ");
- }
-
- void SendInitialMetadataDone() {}
-
- void RecvTrailingMetadataReady(y_absl::Status error) {
- MutexLock lock(mu());
- auto& state =
- y_absl::get<WaitingForTrailingMetadata>(client_trailing_metadata_state_);
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%sRecvTrailingMetadataReady: error:%s metadata:%s state:%s",
- state.waker.ActivityDebugTag().c_str(), error.ToString().c_str(),
- state.result->DebugString().c_str(), ActiveOpsString().c_str());
- }
- auto waker = std::move(state.waker);
- ServerMetadataHandle result = std::move(state.result);
- if (error.ok()) {
- auto* message = result->get_pointer(GrpcMessageMetadata());
- error = y_absl::Status(
- static_cast<y_absl::StatusCode>(
- result->get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN)),
- message == nullptr ? "" : message->as_string_view());
- }
- client_trailing_metadata_state_.emplace<GotClientHalfClose>(
- GotClientHalfClose{error});
- waker.Wakeup();
- }
-
- struct Pipes {
+ArenaPromise<ServerMetadataHandle> MakeServerCallPromise(
+ grpc_transport* transport, CallArgs,
+ NextPromiseFactory next_promise_factory) {
+ OrphanablePtr<ConnectedChannelStream> stream(
+ GetContext<Arena>()->New<ConnectedChannelStream>(transport));
+
+ stream->SetStream(static_cast<grpc_stream*>(
+ GetContext<Arena>()->Alloc(transport->vtable->sizeof_stream)));
+ grpc_transport_init_stream(
+ transport, stream->stream(), stream->stream_refcount(),
+ GetContext<CallContext>()->server_call_context()->server_stream_data(),
+ GetContext<Arena>());
+ grpc_transport_set_pops(transport, stream->stream(),
+ GetContext<CallContext>()->polling_entity());
+
+ auto* party = static_cast<Party*>(Activity::current());
+
+ // Arifacts we need for the lifetime of the call.
+ struct CallData {
Pipe<MessageHandle> server_to_client;
Pipe<MessageHandle> client_to_server;
Pipe<ServerMetadataHandle> server_initial_metadata;
+ Latch<ServerMetadataHandle> failure_latch;
+ bool sent_initial_metadata = false;
+ bool sent_trailing_metadata = false;
};
-
- using CallState =
- y_absl::variant<y_absl::monostate, GettingInitialMetadata, GotInitialMetadata,
- MessageLoop, Completing, Complete>;
- CallState call_state_ Y_ABSL_GUARDED_BY(mu()) = y_absl::monostate{};
- using ClientTrailingMetadataState =
- y_absl::variant<y_absl::monostate, WaitingForTrailingMetadata,
- GotClientHalfClose>;
- ClientTrailingMetadataState client_trailing_metadata_state_
- Y_ABSL_GUARDED_BY(mu()) = y_absl::monostate{};
- y_absl::variant<y_absl::monostate, PipeReceiverNextType<ServerMetadataHandle>,
- ServerMetadataHandle>
- Y_ABSL_GUARDED_BY(mu()) server_initial_metadata_ = y_absl::monostate{};
- PipeSender<MessageHandle>* incoming_messages_ = nullptr;
- grpc_transport_stream_op_batch send_initial_metadata_;
- grpc_closure send_initial_metadata_done_ =
- MakeMemberClosure<ServerStream, &ServerStream::SendInitialMetadataDone>(
- this);
- Pipes pipes_ Y_ABSL_GUARDED_BY(mu());
-};
-
-class ServerConnectedCallPromise {
- public:
- ServerConnectedCallPromise(grpc_transport* transport,
- NextPromiseFactory next_promise_factory)
- : impl_(GetContext<Arena>()->New<ServerStream>(
- transport, std::move(next_promise_factory))) {}
-
- ServerConnectedCallPromise(const ServerConnectedCallPromise&) = delete;
- ServerConnectedCallPromise& operator=(const ServerConnectedCallPromise&) =
- delete;
- ServerConnectedCallPromise(ServerConnectedCallPromise&& other) noexcept
- : impl_(std::exchange(other.impl_, nullptr)) {}
- ServerConnectedCallPromise& operator=(
- ServerConnectedCallPromise&& other) noexcept {
- impl_ = std::move(other.impl_);
- return *this;
- }
-
- static ArenaPromise<ServerMetadataHandle> Make(grpc_transport* transport,
- CallArgs,
- NextPromiseFactory next) {
- return ServerConnectedCallPromise(transport, std::move(next));
- }
-
- Poll<ServerMetadataHandle> operator()() { return impl_->PollOnce(); }
-
- private:
- OrphanablePtr<ServerStream> impl_;
-};
+ auto* call_data = GetContext<Arena>()->ManagedNew<CallData>();
+
+ auto server_to_client_empty =
+ call_data->server_to_client.receiver.AwaitEmpty();
+
+ // Create a promise that will receive client initial metadata, and then run
+ // the main stem of the call (calling next_promise_factory up through the
+ // filters).
+ // Race the main call with failure_latch, allowing us to forcefully complete
+ // the call in the case of a failure.
+ auto recv_initial_metadata_then_run_promise =
+ TrySeq(GetContext<BatchBuilder>()->ReceiveClientInitialMetadata(
+ stream->batch_target()),
+ [next_promise_factory = std::move(next_promise_factory),
+ server_to_client_empty = std::move(server_to_client_empty),
+ call_data](ClientMetadataHandle client_initial_metadata) {
+ auto call_promise = next_promise_factory(CallArgs{
+ std::move(client_initial_metadata),
+ ClientInitialMetadataOutstandingToken::Empty(),
+ &call_data->server_initial_metadata.sender,
+ &call_data->client_to_server.receiver,
+ &call_data->server_to_client.sender,
+ });
+ return Race(call_data->failure_latch.Wait(),
+ [call_promise = std::move(call_promise),
+ server_to_client_empty =
+ std::move(server_to_client_empty)]() mutable
+ -> Poll<ServerMetadataHandle> {
+ // TODO(ctiller): this is deeply weird and we need
+ // to clean this up.
+ //
+ // The following few lines check to ensure that
+ // there's no message currently pending in the
+ // outgoing message queue, and if (and only if)
+ // that's true decides to poll the main promise to
+ // see if there's a result.
+ //
+ // This essentially introduces a polling priority
+ // scheme that makes the current promise structure
+ // work out the way we want when talking to
+ // transports.
+ //
+ // The problem is that transports are going to need
+ // to replicate this structure when they convert to
+ // promises, and that becomes troubling as we'll be
+ // replicating weird throughout the stack.
+ //
+ // Instead we likely need to change the way we're
+ // composing promises through the stack.
+ //
+ // Proposed is to change filters from a promise
+ // that takes ClientInitialMetadata and returns
+ // ServerTrailingMetadata with three pipes for
+ // ServerInitialMetadata and
+ // ClientToServerMessages, ServerToClientMessages.
+ // Instead we'll have five pipes, moving
+ // ClientInitialMetadata and ServerTrailingMetadata
+ // to pipes that can be intercepted.
+ //
+ // The effect of this change will be to cripple the
+ // things that can be done in a filter (but cripple
+ // in line with what most filters actually do).
+ // We'll likely need to add a `CallContext::Cancel`
+ // to allow filters to cancel a request, but this
+ // would also have the advantage of centralizing
+ // our cancellation machinery which seems like an
+ // additional win - with the net effect that the
+ // shape of the call gets made explicit at the top
+ // & bottom of the stack.
+ //
+ // There's a small set of filters (retry, this one,
+ // lame client, clinet channel) that terminate
+ // stacks and need a richer set of semantics, but
+ // that ends up being fine because we can spawn
+ // tasks in parties to handle those edge cases, and
+ // keep the majority of filters simple: they just
+ // call InterceptAndMap on a handful of filters at
+ // call initialization time and then proceed to
+ // actually filter.
+ //
+ // So that's the plan, why isn't it enacted here?
+ //
+ // Well, the plan ends up being easy to implement
+ // in the promise based world (I did a prototype on
+ // a branch in an afternoon). It's heinous to
+ // implement in promise_based_filter, and that code
+ // is load bearing for us at the time of writing.
+ // It's not worth delaying promises for a further N
+ // months (N ~ 6) to make that change.
+ //
+ // Instead, we'll move forward with this, get
+ // promise_based_filter out of the picture, and
+ // then during the mop-up phase for promises tweak
+ // the compute structure to move to the magical
+ // five pipes (I'm reminded of an old Onion
+ // article), and end up in a good happy place.
+ if (server_to_client_empty().pending()) {
+ return Pending{};
+ }
+ return call_promise();
+ });
+ });
+
+ // Promise factory that accepts a ServerMetadataHandle, and sends it as the
+ // trailing metadata for this call.
+ auto send_trailing_metadata =
+ [call_data, stream = stream->InternalRef()](
+ ServerMetadataHandle server_trailing_metadata) {
+ return GetContext<BatchBuilder>()->SendServerTrailingMetadata(
+ stream->batch_target(), std::move(server_trailing_metadata),
+ !std::exchange(call_data->sent_initial_metadata, true));
+ };
+
+ // Runs the receive message loop, either until all the messages
+ // are received or the server call is complete.
+ party->Spawn(
+ "recv_messages",
+ Race(
+ Map(stream->WaitFinished(), [](Empty) { return y_absl::OkStatus(); }),
+ Map(stream->RecvMessages(&call_data->client_to_server.sender),
+ [failure_latch = &call_data->failure_latch](y_absl::Status status) {
+ if (!status.ok() && !failure_latch->is_set()) {
+ failure_latch->Set(ServerMetadataFromStatus(status));
+ }
+ return status;
+ })),
+ [](y_absl::Status) {});
+
+ // Run a promise that will send initial metadata (if that pipe sends some).
+ // And then run the send message loop until that completes.
+
+ auto send_initial_metadata = Seq(
+ Race(Map(stream->WaitFinished(),
+ [](Empty) { return NextResult<ServerMetadataHandle>(true); }),
+ call_data->server_initial_metadata.receiver.Next()),
+ [call_data, stream = stream->InternalRef()](
+ NextResult<ServerMetadataHandle> next_result) mutable {
+ auto md = !call_data->sent_initial_metadata && next_result.has_value()
+ ? std::move(next_result.value())
+ : nullptr;
+ if (md != nullptr) {
+ call_data->sent_initial_metadata = true;
+ auto* party = static_cast<Party*>(Activity::current());
+ party->Spawn("connected/send_initial_metadata",
+ GetContext<BatchBuilder>()->SendServerInitialMetadata(
+ stream->batch_target(), std::move(md)),
+ [](y_absl::Status) {});
+ return Immediate(y_absl::OkStatus());
+ }
+ return Immediate(y_absl::CancelledError());
+ });
+ party->Spawn(
+ "send_initial_metadata_then_messages",
+ Race(Map(stream->WaitFinished(), [](Empty) { return y_absl::OkStatus(); }),
+ TrySeq(std::move(send_initial_metadata),
+ stream->SendMessages(&call_data->server_to_client.receiver))),
+ [](y_absl::Status) {});
+
+ // Spawn a job to fetch the "client trailing metadata" - if this is OK then
+ // it's client done, otherwise it's a signal of cancellation from the client
+ // which we'll use failure_latch to signal.
+
+ party->Spawn(
+ "recv_trailing_metadata",
+ Seq(GetContext<BatchBuilder>()->ReceiveClientTrailingMetadata(
+ stream->batch_target()),
+ [failure_latch = &call_data->failure_latch](
+ y_absl::StatusOr<ClientMetadataHandle> status) mutable {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(
+ GPR_DEBUG,
+ "%s[connected] Got trailing metadata; status=%s metadata=%s",
+ Activity::current()->DebugTag().c_str(),
+ status.status().ToString().c_str(),
+ status.ok() ? (*status)->DebugString().c_str() : "<none>");
+ }
+ ClientMetadataHandle trailing_metadata;
+ if (status.ok()) {
+ trailing_metadata = std::move(*status);
+ } else {
+ trailing_metadata =
+ GetContext<Arena>()->MakePooled<ClientMetadata>(
+ GetContext<Arena>());
+ grpc_status_code status_code = GRPC_STATUS_UNKNOWN;
+ TString message;
+ grpc_error_get_status(status.status(), Timestamp::InfFuture(),
+ &status_code, &message, nullptr, nullptr);
+ trailing_metadata->Set(GrpcStatusMetadata(), status_code);
+ trailing_metadata->Set(GrpcMessageMetadata(),
+ Slice::FromCopiedString(message));
+ }
+ if (trailing_metadata->get(GrpcStatusMetadata())
+ .value_or(GRPC_STATUS_UNKNOWN) != GRPC_STATUS_OK) {
+ if (!failure_latch->is_set()) {
+ failure_latch->Set(std::move(trailing_metadata));
+ }
+ }
+ return Empty{};
+ }),
+ [](Empty) {});
+
+ // Finally assemble the main call promise:
+ // Receive initial metadata from the client and start the promise up the
+ // filter stack.
+ // Upon completion, send trailing metadata to the client and then return it
+ // (allowing the call code to decide on what signalling to give the
+ // application).
+
+ return Map(Seq(std::move(recv_initial_metadata_then_run_promise),
+ std::move(send_trailing_metadata)),
+ [stream = std::move(stream)](ServerMetadataHandle md) {
+ stream->set_finished();
+ return md;
+ });
+}
#endif
template <ArenaPromise<ServerMetadataHandle> (*make_call_promise)(
grpc_transport*, CallArgs, NextPromiseFactory)>
grpc_channel_filter MakeConnectedFilter() {
// Create a vtable that contains both the legacy call methods (for filter
- // stack based calls) and the new promise based method for creating promise
- // based calls (the latter iff make_call_promise != nullptr).
- // In this way the filter can be inserted into either kind of channel stack,
- // and only if all the filters in the stack are promise based will the call
- // be promise based.
+ // stack based calls) and the new promise based method for creating
+ // promise based calls (the latter iff make_call_promise != nullptr). In
+ // this way the filter can be inserted into either kind of channel stack,
+ // and only if all the filters in the stack are promise based will the
+ // call be promise based.
auto make_call_wrapper = +[](grpc_channel_element* elem, CallArgs call_args,
NextPromiseFactory next) {
grpc_transport* transport =
@@ -1371,12 +805,11 @@ grpc_channel_filter MakeConnectedFilter() {
sizeof(channel_data),
connected_channel_init_channel_elem,
+[](grpc_channel_stack* channel_stack, grpc_channel_element* elem) {
- // HACK(ctiller): increase call stack size for the channel to make space
- // for channel data. We need a cleaner (but performant) way to do this,
- // and I'm not sure what that is yet.
- // This is only "safe" because call stacks place no additional data
- // after the last call element, and the last call element MUST be the
- // connected channel.
+ // HACK(ctiller): increase call stack size for the channel to make
+ // space for channel data. We need a cleaner (but performant) way to
+ // do this, and I'm not sure what that is yet. This is only "safe"
+ // because call stacks place no additional data after the last call
+ // element, and the last call element MUST be the connected channel.
channel_stack->call_stack_size += grpc_transport_stream_size(
static_cast<channel_data*>(elem->channel_data)->transport);
},
@@ -1396,7 +829,7 @@ const grpc_channel_filter kPromiseBasedTransportFilter =
#ifdef GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_CLIENT_CALL
const grpc_channel_filter kClientEmulatedFilter =
- MakeConnectedFilter<ClientConnectedCallPromise::Make>();
+ MakeConnectedFilter<MakeClientCallPromise>();
#else
const grpc_channel_filter kClientEmulatedFilter =
MakeConnectedFilter<nullptr>();
@@ -1404,7 +837,7 @@ const grpc_channel_filter kClientEmulatedFilter =
#ifdef GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_SERVER_CALL
const grpc_channel_filter kServerEmulatedFilter =
- MakeConnectedFilter<ServerConnectedCallPromise::Make>();
+ MakeConnectedFilter<MakeServerCallPromise>();
#else
const grpc_channel_filter kServerEmulatedFilter =
MakeConnectedFilter<nullptr>();
@@ -1420,20 +853,20 @@ bool grpc_add_connected_filter(grpc_core::ChannelStackBuilder* builder) {
// We can't know promise based call or not here (that decision needs the
// collaboration of all of the filters on the channel, and we don't want
// ordering constraints on when we add filters).
- // We can know if this results in a promise based call how we'll create our
- // promise (if indeed we can), and so that is the choice made here.
+ // We can know if this results in a promise based call how we'll create
+ // our promise (if indeed we can), and so that is the choice made here.
if (t->vtable->make_call_promise != nullptr) {
- // Option 1, and our ideal: the transport supports promise based calls, and
- // so we simply use the transport directly.
+ // Option 1, and our ideal: the transport supports promise based calls,
+ // and so we simply use the transport directly.
builder->AppendFilter(&grpc_core::kPromiseBasedTransportFilter);
} else if (grpc_channel_stack_type_is_client(builder->channel_stack_type())) {
- // Option 2: the transport does not support promise based calls, but we're
- // on the client and so we have an implementation that we can use to convert
- // to batches.
+ // Option 2: the transport does not support promise based calls, but
+ // we're on the client and so we have an implementation that we can use
+ // to convert to batches.
builder->AppendFilter(&grpc_core::kClientEmulatedFilter);
} else {
- // Option 3: the transport does not support promise based calls, and we're
- // on the server so we use the server filter.
+ // Option 3: the transport does not support promise based calls, and
+ // we're on the server so we use the server filter.
builder->AppendFilter(&grpc_core::kServerEmulatedFilter);
}
return true;
diff --git a/contrib/libs/grpc/src/core/lib/channel/context.h b/contrib/libs/grpc/src/core/lib/channel/context.h
index ea67e4d765..3325d1d577 100644
--- a/contrib/libs/grpc/src/core/lib/channel/context.h
+++ b/contrib/libs/grpc/src/core/lib/channel/context.h
@@ -36,7 +36,14 @@ typedef enum {
/// Value is a \a census_context.
GRPC_CONTEXT_TRACING,
- /// Value is a CallTracer object.
+ /// Value is a CallTracerAnnotationInterface. (ClientCallTracer object on the
+ /// client-side call, or ServerCallTracer on the server-side.)
+ GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE,
+
+ /// Value is a CallTracerInterface (ServerCallTracer on the server-side,
+ /// CallAttemptTracer on a subchannel call.)
+ /// TODO(yashykt): Maybe come up with a better name. This will go away in the
+ /// future anyway, so not super important.
GRPC_CONTEXT_CALL_TRACER,
/// Reserved for traffic_class_context.
diff --git a/contrib/libs/grpc/src/core/lib/channel/promise_based_filter.cc b/contrib/libs/grpc/src/core/lib/channel/promise_based_filter.cc
index 25a5101b2b..cf00f0ec25 100644
--- a/contrib/libs/grpc/src/core/lib/channel/promise_based_filter.cc
+++ b/contrib/libs/grpc/src/core/lib/channel/promise_based_filter.cc
@@ -16,6 +16,8 @@
#include "src/core/lib/channel/promise_based_filter.h"
+#include <inttypes.h>
+
#include <algorithm>
#include <initializer_list>
#include <memory>
@@ -53,7 +55,7 @@ class FakeActivity final : public Activity {
explicit FakeActivity(Activity* wake_activity)
: wake_activity_(wake_activity) {}
void Orphan() override {}
- void ForceImmediateRepoll() override {}
+ void ForceImmediateRepoll(WakeupMask) override {}
Waker MakeOwningWaker() override { return wake_activity_->MakeOwningWaker(); }
Waker MakeNonOwningWaker() override {
return wake_activity_->MakeNonOwningWaker();
@@ -92,6 +94,9 @@ BaseCallData::BaseCallData(
arena_(args->arena),
call_combiner_(args->call_combiner),
deadline_(args->deadline),
+ call_context_(flags & kFilterExaminesCallContext
+ ? arena_->New<CallContext>(nullptr)
+ : nullptr),
context_(args->context),
server_initial_metadata_pipe_(
flags & kFilterExaminesServerInitialMetadata
@@ -134,20 +139,22 @@ Waker BaseCallData::MakeNonOwningWaker() { return MakeOwningWaker(); }
Waker BaseCallData::MakeOwningWaker() {
GRPC_CALL_STACK_REF(call_stack_, "waker");
- return Waker(this, nullptr);
+ return Waker(this, 0);
}
-void BaseCallData::Wakeup(void*) {
+void BaseCallData::Wakeup(WakeupMask) {
auto wakeup = [](void* p, grpc_error_handle) {
auto* self = static_cast<BaseCallData*>(p);
self->OnWakeup();
- self->Drop(nullptr);
+ self->Drop(0);
};
auto* closure = GRPC_CLOSURE_CREATE(wakeup, this, nullptr);
GRPC_CALL_COMBINER_START(call_combiner_, closure, y_absl::OkStatus(), "wakeup");
}
-void BaseCallData::Drop(void*) { GRPC_CALL_STACK_UNREF(call_stack_, "waker"); }
+void BaseCallData::Drop(WakeupMask) {
+ GRPC_CALL_STACK_UNREF(call_stack_, "waker");
+}
TString BaseCallData::LogTag() const {
return y_absl::StrCat(
@@ -215,7 +222,7 @@ void BaseCallData::CapturedBatch::ResumeWith(Flusher* releaser) {
// refcnt==0 ==> cancelled
if (grpc_trace_channel.enabled()) {
gpr_log(GPR_INFO, "%sRESUME BATCH REQUEST CANCELLED",
- Activity::current()->DebugTag().c_str());
+ releaser->call()->DebugTag().c_str());
}
return;
}
@@ -239,6 +246,10 @@ void BaseCallData::CapturedBatch::CancelWith(grpc_error_handle error,
auto* batch = std::exchange(batch_, nullptr);
GPR_ASSERT(batch != nullptr);
uintptr_t& refcnt = *RefCountField(batch);
+ gpr_log(GPR_DEBUG, "%sCancelWith: %p refs=%" PRIdPTR " err=%s [%s]",
+ releaser->call()->DebugTag().c_str(), batch, refcnt,
+ error.ToString().c_str(),
+ grpc_transport_stream_op_batch_string(batch, false).c_str());
if (refcnt == 0) {
// refcnt==0 ==> cancelled
if (grpc_trace_channel.enabled()) {
@@ -275,16 +286,20 @@ BaseCallData::Flusher::~Flusher() {
static_cast<BaseCallData*>(batch->handler_private.extra_arg);
if (grpc_trace_channel.enabled()) {
gpr_log(GPR_INFO, "FLUSHER:forward batch via closure: %s",
- grpc_transport_stream_op_batch_string(batch).c_str());
+ grpc_transport_stream_op_batch_string(batch, false).c_str());
}
grpc_call_next_op(call->elem(), batch);
GRPC_CALL_STACK_UNREF(call->call_stack(), "flusher_batch");
};
for (size_t i = 1; i < release_.size(); i++) {
auto* batch = release_[i];
+ if (call_->call_context_ != nullptr && call_->call_context_->traced()) {
+ batch->is_traced = true;
+ }
if (grpc_trace_channel.enabled()) {
- gpr_log(GPR_INFO, "FLUSHER:queue batch to forward in closure: %s",
- grpc_transport_stream_op_batch_string(release_[i]).c_str());
+ gpr_log(
+ GPR_INFO, "FLUSHER:queue batch to forward in closure: %s",
+ grpc_transport_stream_op_batch_string(release_[i], false).c_str());
}
batch->handler_private.extra_arg = call_;
GRPC_CLOSURE_INIT(&batch->handler_private.closure, call_next_op, batch,
@@ -296,7 +311,7 @@ BaseCallData::Flusher::~Flusher() {
call_closures_.RunClosuresWithoutYielding(call_->call_combiner());
if (grpc_trace_channel.enabled()) {
gpr_log(GPR_INFO, "FLUSHER:forward batch: %s",
- grpc_transport_stream_op_batch_string(release_[0]).c_str());
+ grpc_transport_stream_op_batch_string(release_[0], false).c_str());
}
grpc_call_next_op(call_->elem(), release_[0]);
GRPC_CALL_STACK_UNREF(call_->call_stack(), "flusher");
@@ -325,6 +340,8 @@ const char* BaseCallData::SendMessage::StateString(State state) {
return "CANCELLED";
case State::kCancelledButNotYetPolled:
return "CANCELLED_BUT_NOT_YET_POLLED";
+ case State::kCancelledButNoStatus:
+ return "CANCELLED_BUT_NO_STATUS";
}
return "UNKNOWN";
}
@@ -349,6 +366,7 @@ void BaseCallData::SendMessage::StartOp(CapturedBatch batch) {
Crash(y_absl::StrFormat("ILLEGAL STATE: %s", StateString(state_)));
case State::kCancelled:
case State::kCancelledButNotYetPolled:
+ case State::kCancelledButNoStatus:
return;
}
batch_ = batch;
@@ -376,6 +394,7 @@ void BaseCallData::SendMessage::GotPipe(T* pipe_end) {
case State::kForwardedBatch:
case State::kBatchCompleted:
case State::kPushedToPipe:
+ case State::kCancelledButNoStatus:
Crash(y_absl::StrFormat("ILLEGAL STATE: %s", StateString(state_)));
case State::kCancelled:
case State::kCancelledButNotYetPolled:
@@ -391,6 +410,7 @@ bool BaseCallData::SendMessage::IsIdle() const {
case State::kForwardedBatch:
case State::kCancelled:
case State::kCancelledButNotYetPolled:
+ case State::kCancelledButNoStatus:
return true;
case State::kGotBatchNoPipe:
case State::kGotBatch:
@@ -419,6 +439,7 @@ void BaseCallData::SendMessage::OnComplete(y_absl::Status status) {
break;
case State::kCancelled:
case State::kCancelledButNotYetPolled:
+ case State::kCancelledButNoStatus:
flusher.AddClosure(intercepted_on_complete_, status,
"forward after cancel");
break;
@@ -443,10 +464,14 @@ void BaseCallData::SendMessage::Done(const ServerMetadata& metadata,
case State::kCancelledButNotYetPolled:
break;
case State::kInitial:
+ state_ = State::kCancelled;
+ break;
case State::kIdle:
case State::kForwardedBatch:
state_ = State::kCancelledButNotYetPolled;
+ if (base_->is_current()) base_->ForceImmediateRepoll();
break;
+ case State::kCancelledButNoStatus:
case State::kGotBatchNoPipe:
case State::kGotBatch: {
TString temp;
@@ -465,6 +490,7 @@ void BaseCallData::SendMessage::Done(const ServerMetadata& metadata,
push_.reset();
next_.reset();
state_ = State::kCancelledButNotYetPolled;
+ if (base_->is_current()) base_->ForceImmediateRepoll();
break;
}
}
@@ -483,6 +509,7 @@ void BaseCallData::SendMessage::WakeInsideCombiner(Flusher* flusher,
case State::kIdle:
case State::kGotBatchNoPipe:
case State::kCancelled:
+ case State::kCancelledButNoStatus:
break;
case State::kCancelledButNotYetPolled:
interceptor()->Push()->Close();
@@ -524,13 +551,18 @@ void BaseCallData::SendMessage::WakeInsideCombiner(Flusher* flusher,
"result.has_value=%s",
base_->LogTag().c_str(), p->has_value() ? "true" : "false");
}
- GPR_ASSERT(p->has_value());
- batch_->payload->send_message.send_message->Swap((**p)->payload());
- batch_->payload->send_message.flags = (**p)->flags();
- state_ = State::kForwardedBatch;
- batch_.ResumeWith(flusher);
- next_.reset();
- if ((*push_)().ready()) push_.reset();
+ if (p->has_value()) {
+ batch_->payload->send_message.send_message->Swap((**p)->payload());
+ batch_->payload->send_message.flags = (**p)->flags();
+ state_ = State::kForwardedBatch;
+ batch_.ResumeWith(flusher);
+ next_.reset();
+ if ((*push_)().ready()) push_.reset();
+ } else {
+ state_ = State::kCancelledButNoStatus;
+ next_.reset();
+ push_.reset();
+ }
}
} break;
case State::kForwardedBatch:
@@ -1088,11 +1120,14 @@ class ClientCallData::PollContext {
// Poll the promise once since we're waiting for it.
Poll<ServerMetadataHandle> poll = self_->promise_();
if (grpc_trace_channel.enabled()) {
- gpr_log(GPR_INFO, "%s ClientCallData.PollContext.Run: poll=%s",
+ gpr_log(GPR_INFO, "%s ClientCallData.PollContext.Run: poll=%s; %s",
self_->LogTag().c_str(),
- PollToString(poll, [](const ServerMetadataHandle& h) {
- return h->DebugString();
- }).c_str());
+ PollToString(poll,
+ [](const ServerMetadataHandle& h) {
+ return h->DebugString();
+ })
+ .c_str(),
+ self_->DebugString().c_str());
}
if (auto* r = poll.value_if_ready()) {
auto md = std::move(*r);
@@ -1272,7 +1307,11 @@ ClientCallData::ClientCallData(grpc_call_element* elem,
[args]() {
return args->arena->New<ReceiveInterceptor>(args->arena);
},
- [args]() { return args->arena->New<SendInterceptor>(args->arena); }) {
+ [args]() { return args->arena->New<SendInterceptor>(args->arena); }),
+ initial_metadata_outstanding_token_(
+ (flags & kFilterIsLast) != 0
+ ? ClientInitialMetadataOutstandingToken::New(arena())
+ : ClientInitialMetadataOutstandingToken::Empty()) {
GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready_,
RecvTrailingMetadataReadyCallback, this,
grpc_schedule_on_exec_ctx);
@@ -1288,8 +1327,12 @@ ClientCallData::~ClientCallData() {
}
}
+TString ClientCallData::DebugTag() const {
+ return y_absl::StrFormat("PBF_CLIENT[%p]: [%s] ", this, elem()->filter->name);
+}
+
// Activity implementation.
-void ClientCallData::ForceImmediateRepoll() {
+void ClientCallData::ForceImmediateRepoll(WakeupMask) {
GPR_ASSERT(poll_ctx_ != nullptr);
poll_ctx_->Repoll();
}
@@ -1541,6 +1584,7 @@ void ClientCallData::StartPromise(Flusher* flusher) {
promise_ = filter->MakeCallPromise(
CallArgs{WrapMetadata(send_initial_metadata_batch_->payload
->send_initial_metadata.send_initial_metadata),
+ std::move(initial_metadata_outstanding_token_),
server_initial_metadata_pipe() == nullptr
? nullptr
: &server_initial_metadata_pipe()->sender,
@@ -1648,8 +1692,7 @@ ArenaPromise<ServerMetadataHandle> ClientCallData::MakeNextPromise(
GPR_ASSERT(poll_ctx_ != nullptr);
GPR_ASSERT(send_initial_state_ == SendInitialState::kQueued);
send_initial_metadata_batch_->payload->send_initial_metadata
- .send_initial_metadata =
- UnwrapMetadata(std::move(call_args.client_initial_metadata));
+ .send_initial_metadata = call_args.client_initial_metadata.get();
if (recv_initial_metadata_ != nullptr) {
// Call args should contain a latch for receiving initial metadata.
// It might be the one we passed in - in which case we know this filter
@@ -1861,8 +1904,15 @@ struct ServerCallData::SendInitialMetadata {
class ServerCallData::PollContext {
public:
- explicit PollContext(ServerCallData* self, Flusher* flusher)
- : self_(self), flusher_(flusher) {
+ explicit PollContext(ServerCallData* self, Flusher* flusher,
+ DebugLocation created = DebugLocation())
+ : self_(self), flusher_(flusher), created_(created) {
+ if (self_->poll_ctx_ != nullptr) {
+ Crash(y_absl::StrCat(
+ "PollContext: disallowed recursion. New: ", created_.file(), ":",
+ created_.line(), "; Old: ", self_->poll_ctx_->created_.file(), ":",
+ self_->poll_ctx_->created_.line()));
+ }
GPR_ASSERT(self_->poll_ctx_ == nullptr);
self_->poll_ctx_ = this;
scoped_activity_.Init(self_);
@@ -1908,6 +1958,7 @@ class ServerCallData::PollContext {
Flusher* const flusher_;
bool repoll_ = false;
bool have_scoped_activity_;
+ GPR_NO_UNIQUE_ADDRESS DebugLocation created_;
};
const char* ServerCallData::StateString(RecvInitialState state) {
@@ -1967,11 +2018,18 @@ ServerCallData::~ServerCallData() {
gpr_log(GPR_INFO, "%s ~ServerCallData %s", LogTag().c_str(),
DebugString().c_str());
}
+ if (send_initial_metadata_ != nullptr) {
+ send_initial_metadata_->~SendInitialMetadata();
+ }
GPR_ASSERT(poll_ctx_ == nullptr);
}
+TString ServerCallData::DebugTag() const {
+ return y_absl::StrFormat("PBF_SERVER[%p]: [%s] ", this, elem()->filter->name);
+}
+
// Activity implementation.
-void ServerCallData::ForceImmediateRepoll() {
+void ServerCallData::ForceImmediateRepoll(WakeupMask) {
GPR_ASSERT(poll_ctx_ != nullptr);
poll_ctx_->Repoll();
}
@@ -2077,7 +2135,10 @@ void ServerCallData::StartBatch(grpc_transport_stream_op_batch* b) {
switch (send_trailing_state_) {
case SendTrailingState::kInitial:
send_trailing_metadata_batch_ = batch;
- if (receive_message() != nullptr) {
+ if (receive_message() != nullptr &&
+ batch->payload->send_trailing_metadata.send_trailing_metadata
+ ->get(GrpcStatusMetadata())
+ .value_or(GRPC_STATUS_UNKNOWN) != GRPC_STATUS_OK) {
receive_message()->Done(
*batch->payload->send_trailing_metadata.send_trailing_metadata,
&flusher);
@@ -2134,9 +2195,12 @@ void ServerCallData::Completed(grpc_error_handle error, Flusher* flusher) {
case SendTrailingState::kForwarded:
send_trailing_state_ = SendTrailingState::kCancelled;
if (!error.ok()) {
+ call_stack()->IncrementRefCount();
auto* batch = grpc_make_transport_stream_op(
- NewClosure([call_combiner = call_combiner()](y_absl::Status) {
+ NewClosure([call_combiner = call_combiner(),
+ call_stack = call_stack()](y_absl::Status) {
GRPC_CALL_COMBINER_STOP(call_combiner, "done-cancel");
+ call_stack->Unref();
}));
batch->cancel_stream = true;
batch->payload->cancel_stream.cancel_error = error;
@@ -2188,7 +2252,7 @@ void ServerCallData::Completed(grpc_error_handle error, Flusher* flusher) {
ArenaPromise<ServerMetadataHandle> ServerCallData::MakeNextPromise(
CallArgs call_args) {
GPR_ASSERT(recv_initial_state_ == RecvInitialState::kComplete);
- GPR_ASSERT(UnwrapMetadata(std::move(call_args.client_initial_metadata)) ==
+ GPR_ASSERT(std::move(call_args.client_initial_metadata).get() ==
recv_initial_metadata_);
forward_recv_initial_metadata_callback_ = true;
if (send_initial_metadata_ != nullptr) {
@@ -2310,6 +2374,7 @@ void ServerCallData::RecvInitialMetadataReady(grpc_error_handle error) {
FakeActivity(this).Run([this, filter] {
promise_ = filter->MakeCallPromise(
CallArgs{WrapMetadata(recv_initial_metadata_),
+ ClientInitialMetadataOutstandingToken::Empty(),
server_initial_metadata_pipe() == nullptr
? nullptr
: &server_initial_metadata_pipe()->sender,
@@ -2410,9 +2475,14 @@ void ServerCallData::WakeInsideCombiner(Flusher* flusher) {
(send_trailing_metadata_batch_->send_message &&
send_message()->IsForwarded()))) {
send_trailing_state_ = SendTrailingState::kQueued;
- send_message()->Done(*send_trailing_metadata_batch_->payload
- ->send_trailing_metadata.send_trailing_metadata,
- flusher);
+ if (send_trailing_metadata_batch_->payload->send_trailing_metadata
+ .send_trailing_metadata->get(GrpcStatusMetadata())
+ .value_or(GRPC_STATUS_UNKNOWN) != GRPC_STATUS_OK) {
+ send_message()->Done(
+ *send_trailing_metadata_batch_->payload->send_trailing_metadata
+ .send_trailing_metadata,
+ flusher);
+ }
}
}
if (receive_message() != nullptr) {
@@ -2463,8 +2533,7 @@ void ServerCallData::WakeInsideCombiner(Flusher* flusher) {
}
if (auto* r = poll.value_if_ready()) {
promise_ = ArenaPromise<ServerMetadataHandle>();
- auto* md = UnwrapMetadata(std::move(*r));
- bool destroy_md = true;
+ auto md = std::move(*r);
if (send_message() != nullptr) {
send_message()->Done(*md, flusher);
}
@@ -2476,11 +2545,9 @@ void ServerCallData::WakeInsideCombiner(Flusher* flusher) {
case SendTrailingState::kQueuedButHaventClosedSends:
case SendTrailingState::kQueued: {
if (send_trailing_metadata_batch_->payload->send_trailing_metadata
- .send_trailing_metadata != md) {
+ .send_trailing_metadata != md.get()) {
*send_trailing_metadata_batch_->payload->send_trailing_metadata
.send_trailing_metadata = std::move(*md);
- } else {
- destroy_md = false;
}
send_trailing_metadata_batch_.ResumeWith(flusher);
send_trailing_state_ = SendTrailingState::kForwarded;
@@ -2498,9 +2565,6 @@ void ServerCallData::WakeInsideCombiner(Flusher* flusher) {
// Nothing to do.
break;
}
- if (destroy_md) {
- md->~grpc_metadata_batch();
- }
}
}
if (std::exchange(forward_recv_initial_metadata_callback_, false)) {
diff --git a/contrib/libs/grpc/src/core/lib/channel/promise_based_filter.h b/contrib/libs/grpc/src/core/lib/channel/promise_based_filter.h
index 05a4176096..59341a79d7 100644
--- a/contrib/libs/grpc/src/core/lib/channel/promise_based_filter.h
+++ b/contrib/libs/grpc/src/core/lib/channel/promise_based_filter.h
@@ -63,6 +63,7 @@
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice_buffer.h"
+#include "src/core/lib/surface/call.h"
#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
@@ -135,6 +136,7 @@ static constexpr uint8_t kFilterExaminesServerInitialMetadata = 1;
static constexpr uint8_t kFilterIsLast = 2;
static constexpr uint8_t kFilterExaminesOutboundMessages = 4;
static constexpr uint8_t kFilterExaminesInboundMessages = 8;
+static constexpr uint8_t kFilterExaminesCallContext = 16;
namespace promise_filter_detail {
@@ -183,7 +185,7 @@ class BaseCallData : public Activity, private Wakeable {
Waker MakeNonOwningWaker() final;
Waker MakeOwningWaker() final;
- TString ActivityDebugTag(void*) const override { return DebugTag(); }
+ TString ActivityDebugTag(WakeupMask) const override { return DebugTag(); }
void Finalize(const grpc_call_final_info* final_info) {
finalization_.Run(final_info);
@@ -198,7 +200,8 @@ class BaseCallData : public Activity, private Wakeable {
public promise_detail::Context<grpc_polling_entity>,
public promise_detail::Context<CallFinalization>,
public promise_detail::Context<
- grpc_event_engine::experimental::EventEngine> {
+ grpc_event_engine::experimental::EventEngine>,
+ public promise_detail::Context<CallContext> {
public:
explicit ScopedContext(BaseCallData* call_data)
: promise_detail::Context<Arena>(call_data->arena_),
@@ -208,7 +211,8 @@ class BaseCallData : public Activity, private Wakeable {
call_data->pollent_.load(std::memory_order_acquire)),
promise_detail::Context<CallFinalization>(&call_data->finalization_),
promise_detail::Context<grpc_event_engine::experimental::EventEngine>(
- call_data->event_engine_) {}
+ call_data->event_engine_),
+ promise_detail::Context<CallContext>(call_data->call_context_) {}
};
class Flusher {
@@ -219,7 +223,11 @@ class BaseCallData : public Activity, private Wakeable {
void Resume(grpc_transport_stream_op_batch* batch) {
GPR_ASSERT(!call_->is_last());
- release_.push_back(batch);
+ if (batch->HasOp()) {
+ release_.push_back(batch);
+ } else if (batch->on_complete != nullptr) {
+ Complete(batch);
+ }
}
void Cancel(grpc_transport_stream_op_batch* batch,
@@ -238,6 +246,8 @@ class BaseCallData : public Activity, private Wakeable {
call_closures_.Add(closure, error, reason);
}
+ BaseCallData* call() const { return call_; }
+
private:
y_absl::InlinedVector<grpc_transport_stream_op_batch*, 1> release_;
CallCombinerClosureList call_closures_;
@@ -281,11 +291,6 @@ class BaseCallData : public Activity, private Wakeable {
Arena::PooledDeleter(nullptr));
}
- static grpc_metadata_batch* UnwrapMetadata(
- Arena::PoolPtr<grpc_metadata_batch> p) {
- return p.release();
- }
-
class ReceiveInterceptor final : public Interceptor {
public:
explicit ReceiveInterceptor(Arena* arena) : pipe_{arena} {}
@@ -399,6 +404,8 @@ class BaseCallData : public Activity, private Wakeable {
kCancelledButNotYetPolled,
// We're done.
kCancelled,
+ // We're done, but we haven't gotten a status yet
+ kCancelledButNoStatus,
};
static const char* StateString(State);
@@ -539,8 +546,8 @@ class BaseCallData : public Activity, private Wakeable {
private:
// Wakeable implementation.
- void Wakeup(void*) final;
- void Drop(void*) final;
+ void Wakeup(WakeupMask) final;
+ void Drop(WakeupMask) final;
virtual void OnWakeup() = 0;
@@ -550,6 +557,7 @@ class BaseCallData : public Activity, private Wakeable {
CallCombiner* const call_combiner_;
const Timestamp deadline_;
CallFinalization finalization_;
+ CallContext* call_context_ = nullptr;
grpc_call_context_element* const context_;
std::atomic<grpc_polling_entity*> pollent_{nullptr};
Pipe<ServerMetadataHandle>* const server_initial_metadata_pipe_;
@@ -565,10 +573,12 @@ class ClientCallData : public BaseCallData {
~ClientCallData() override;
// Activity implementation.
- void ForceImmediateRepoll() final;
+ void ForceImmediateRepoll(WakeupMask) final;
// Handle one grpc_transport_stream_op_batch
void StartBatch(grpc_transport_stream_op_batch* batch) override;
+ TString DebugTag() const override;
+
private:
// At what stage is our handling of send initial metadata?
enum class SendInitialState {
@@ -665,6 +675,8 @@ class ClientCallData : public BaseCallData {
RecvTrailingState recv_trailing_state_ = RecvTrailingState::kInitial;
// Polling related data. Non-null if we're actively polling
PollContext* poll_ctx_ = nullptr;
+ // Initial metadata outstanding token
+ ClientInitialMetadataOutstandingToken initial_metadata_outstanding_token_;
};
class ServerCallData : public BaseCallData {
@@ -674,10 +686,12 @@ class ServerCallData : public BaseCallData {
~ServerCallData() override;
// Activity implementation.
- void ForceImmediateRepoll() final;
+ void ForceImmediateRepoll(WakeupMask) final;
// Handle one grpc_transport_stream_op_batch
void StartBatch(grpc_transport_stream_op_batch* batch) override;
+ TString DebugTag() const override;
+
protected:
y_absl::string_view ClientOrServerString() const override { return "SVR"; }
diff --git a/contrib/libs/grpc/src/core/lib/channel/server_call_tracer_filter.cc b/contrib/libs/grpc/src/core/lib/channel/server_call_tracer_filter.cc
new file mode 100644
index 0000000000..b8739fbd6a
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/channel/server_call_tracer_filter.cc
@@ -0,0 +1,110 @@
+//
+// Copyright 2023 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <grpc/support/port_platform.h>
+
+#include <functional>
+#include <utility>
+
+#include "y_absl/status/status.h"
+#include "y_absl/status/statusor.h"
+
+#include "src/core/lib/channel/call_finalization.h"
+#include "src/core/lib/channel/call_tracer.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/channel_fwd.h"
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/channel/context.h"
+#include "src/core/lib/channel/promise_based_filter.h"
+#include "src/core/lib/config/core_configuration.h"
+#include "src/core/lib/promise/arena_promise.h"
+#include "src/core/lib/promise/cancel_callback.h"
+#include "src/core/lib/promise/context.h"
+#include "src/core/lib/promise/map.h"
+#include "src/core/lib/promise/pipe.h"
+#include "src/core/lib/promise/poll.h"
+#include "src/core/lib/surface/channel_init.h"
+#include "src/core/lib/surface/channel_stack_type.h"
+#include "src/core/lib/transport/transport.h"
+
+namespace grpc_core {
+
+namespace {
+
+// TODO(yashykt): This filter is not really needed. We should be able to move
+// this to the connected filter.
+class ServerCallTracerFilter : public ChannelFilter {
+ public:
+ static const grpc_channel_filter kFilter;
+
+ static y_absl::StatusOr<ServerCallTracerFilter> Create(
+ const ChannelArgs& /*args*/, ChannelFilter::Args /*filter_args*/);
+
+ ArenaPromise<ServerMetadataHandle> MakeCallPromise(
+ CallArgs call_args, NextPromiseFactory next_promise_factory) override;
+};
+
+const grpc_channel_filter ServerCallTracerFilter::kFilter =
+ MakePromiseBasedFilter<ServerCallTracerFilter, FilterEndpoint::kServer,
+ kFilterExaminesServerInitialMetadata>(
+ "server_call_tracer");
+
+y_absl::StatusOr<ServerCallTracerFilter> ServerCallTracerFilter::Create(
+ const ChannelArgs& /*args*/, ChannelFilter::Args /*filter_args*/) {
+ return ServerCallTracerFilter();
+}
+
+ArenaPromise<ServerMetadataHandle> ServerCallTracerFilter::MakeCallPromise(
+ CallArgs call_args, NextPromiseFactory next_promise_factory) {
+ auto* call_context = GetContext<grpc_call_context_element>();
+ auto* call_tracer = static_cast<ServerCallTracer*>(
+ call_context[GRPC_CONTEXT_CALL_TRACER].value);
+ if (call_tracer == nullptr) {
+ return next_promise_factory(std::move(call_args));
+ }
+ call_tracer->RecordReceivedInitialMetadata(
+ call_args.client_initial_metadata.get());
+ call_args.server_initial_metadata->InterceptAndMap(
+ [call_tracer](ServerMetadataHandle metadata) {
+ call_tracer->RecordSendInitialMetadata(metadata.get());
+ return metadata;
+ });
+ GetContext<CallFinalization>()->Add(
+ [call_tracer](const grpc_call_final_info* final_info) {
+ call_tracer->RecordEnd(final_info);
+ });
+ return OnCancel(
+ Map(next_promise_factory(std::move(call_args)),
+ [call_tracer](ServerMetadataHandle md) {
+ call_tracer->RecordSendTrailingMetadata(md.get());
+ return md;
+ }),
+ [call_tracer]() { call_tracer->RecordCancel(y_absl::CancelledError()); });
+}
+
+} // namespace
+
+void RegisterServerCallTracerFilter(CoreConfiguration::Builder* builder) {
+ builder->channel_init()->RegisterStage(
+ GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
+ [](ChannelStackBuilder* builder) {
+ builder->AppendFilter(&ServerCallTracerFilter::kFilter);
+ return true;
+ });
+}
+
+} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/config/config_vars.cc b/contrib/libs/grpc/src/core/lib/config/config_vars.cc
new file mode 100644
index 0000000000..f51c838a9a
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/config/config_vars.cc
@@ -0,0 +1,151 @@
+// Copyright 2023 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//
+// Automatically generated by tools/codegen/core/gen_config_vars.py
+//
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/config/config_vars.h"
+
+#include "y_absl/flags/flag.h"
+#include "y_absl/strings/escaping.h"
+#include "y_absl/strings/str_cat.h"
+
+#include "src/core/lib/config/load_config.h"
+
+#ifndef GPR_DEFAULT_LOG_VERBOSITY_STRING
+#define GPR_DEFAULT_LOG_VERBOSITY_STRING "ERROR"
+#endif // !GPR_DEFAULT_LOG_VERBOSITY_STRING
+
+#ifdef GRPC_ENABLE_FORK_SUPPORT
+#define GRPC_ENABLE_FORK_SUPPORT_DEFAULT true
+#else
+#define GRPC_ENABLE_FORK_SUPPORT_DEFAULT false
+#endif // GRPC_ENABLE_FORK_SUPPORT
+
+Y_ABSL_FLAG(y_absl::optional<TString>, grpc_experiments, y_absl::nullopt,
+ "A comma separated list of currently active experiments. Experiments "
+ "may be prefixed with a '-' to disable them.");
+Y_ABSL_FLAG(y_absl::optional<int32_t>, grpc_client_channel_backup_poll_interval_ms,
+ y_absl::nullopt,
+ "Declares the interval in ms between two backup polls on client "
+ "channels. These polls are run in the timer thread so that gRPC can "
+ "process connection failures while there is no active polling "
+ "thread. They help reconnect disconnected client channels (mostly "
+ "due to idleness), so that the next RPC on this channel won't fail. "
+ "Set to 0 to turn off the backup polls.");
+Y_ABSL_FLAG(y_absl::optional<TString>, grpc_dns_resolver, y_absl::nullopt,
+ "Declares which DNS resolver to use. The default is ares if gRPC is "
+ "built with c-ares support. Otherwise, the value of this environment "
+ "variable is ignored.");
+Y_ABSL_FLAG(y_absl::optional<TString>, grpc_trace, y_absl::nullopt,
+ "A comma separated list of tracers that provide additional insight "
+ "into how gRPC C core is processing requests via debug logs.");
+Y_ABSL_FLAG(y_absl::optional<TString>, grpc_verbosity, y_absl::nullopt,
+ "Default gRPC logging verbosity");
+Y_ABSL_FLAG(y_absl::optional<TString>, grpc_stacktrace_minloglevel,
+ y_absl::nullopt,
+ "Messages logged at the same or higher level than this will print "
+ "stacktrace");
+Y_ABSL_FLAG(y_absl::optional<bool>, grpc_enable_fork_support, y_absl::nullopt,
+ "Enable fork support");
+Y_ABSL_FLAG(y_absl::optional<TString>, grpc_poll_strategy, y_absl::nullopt,
+ "Declares which polling engines to try when starting gRPC. This is a "
+ "comma-separated list of engines, which are tried in priority order "
+ "first -> last.");
+Y_ABSL_FLAG(y_absl::optional<bool>, grpc_abort_on_leaks, y_absl::nullopt,
+ "A debugging aid to cause a call to abort() when gRPC objects are "
+ "leaked past grpc_shutdown()");
+Y_ABSL_FLAG(y_absl::optional<TString>, grpc_system_ssl_roots_dir, y_absl::nullopt,
+ "Custom directory to SSL Roots");
+Y_ABSL_FLAG(y_absl::optional<TString>, grpc_default_ssl_roots_file_path,
+ y_absl::nullopt, "Path to the default SSL roots file.");
+Y_ABSL_FLAG(y_absl::optional<bool>, grpc_not_use_system_ssl_roots, y_absl::nullopt,
+ "Disable loading system root certificates.");
+Y_ABSL_FLAG(y_absl::optional<TString>, grpc_ssl_cipher_suites, y_absl::nullopt,
+ "A colon separated list of cipher suites to use with OpenSSL");
+
+namespace grpc_core {
+
+ConfigVars::ConfigVars(const Overrides& overrides)
+ : client_channel_backup_poll_interval_ms_(
+ LoadConfig(FLAGS_grpc_client_channel_backup_poll_interval_ms,
+ "GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS",
+ overrides.client_channel_backup_poll_interval_ms, 5000)),
+ enable_fork_support_(LoadConfig(
+ FLAGS_grpc_enable_fork_support, "GRPC_ENABLE_FORK_SUPPORT",
+ overrides.enable_fork_support, GRPC_ENABLE_FORK_SUPPORT_DEFAULT)),
+ abort_on_leaks_(LoadConfig(FLAGS_grpc_abort_on_leaks,
+ "GRPC_ABORT_ON_LEAKS",
+ overrides.abort_on_leaks, false)),
+ not_use_system_ssl_roots_(LoadConfig(
+ FLAGS_grpc_not_use_system_ssl_roots, "GRPC_NOT_USE_SYSTEM_SSL_ROOTS",
+ overrides.not_use_system_ssl_roots, false)),
+ experiments_(LoadConfig(FLAGS_grpc_experiments, "GRPC_EXPERIMENTS",
+ overrides.experiments, "")),
+ dns_resolver_(LoadConfig(FLAGS_grpc_dns_resolver, "GRPC_DNS_RESOLVER",
+ overrides.dns_resolver, "")),
+ trace_(LoadConfig(FLAGS_grpc_trace, "GRPC_TRACE", overrides.trace, "")),
+ verbosity_(LoadConfig(FLAGS_grpc_verbosity, "GRPC_VERBOSITY",
+ overrides.verbosity,
+ GPR_DEFAULT_LOG_VERBOSITY_STRING)),
+ stacktrace_minloglevel_(LoadConfig(FLAGS_grpc_stacktrace_minloglevel,
+ "GRPC_STACKTRACE_MINLOGLEVEL",
+ overrides.stacktrace_minloglevel, "")),
+ poll_strategy_(LoadConfig(FLAGS_grpc_poll_strategy, "GRPC_POLL_STRATEGY",
+ overrides.poll_strategy, "all")),
+ ssl_cipher_suites_(LoadConfig(
+ FLAGS_grpc_ssl_cipher_suites, "GRPC_SSL_CIPHER_SUITES",
+ overrides.ssl_cipher_suites,
+ "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_"
+ "SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:"
+ "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384")),
+ override_system_ssl_roots_dir_(overrides.system_ssl_roots_dir),
+ override_default_ssl_roots_file_path_(
+ overrides.default_ssl_roots_file_path) {}
+
+TString ConfigVars::SystemSslRootsDir() const {
+ return LoadConfig(FLAGS_grpc_system_ssl_roots_dir,
+ "GRPC_SYSTEM_SSL_ROOTS_DIR", override_system_ssl_roots_dir_,
+ "");
+}
+
+TString ConfigVars::DefaultSslRootsFilePath() const {
+ return LoadConfig(FLAGS_grpc_default_ssl_roots_file_path,
+ "GRPC_DEFAULT_SSL_ROOTS_FILE_PATH",
+ override_default_ssl_roots_file_path_, "");
+}
+
+TString ConfigVars::ToString() const {
+ return y_absl::StrCat(
+ "experiments: ", "\"", y_absl::CEscape(Experiments()), "\"",
+ ", client_channel_backup_poll_interval_ms: ",
+ ClientChannelBackupPollIntervalMs(), ", dns_resolver: ", "\"",
+ y_absl::CEscape(DnsResolver()), "\"", ", trace: ", "\"",
+ y_absl::CEscape(Trace()), "\"", ", verbosity: ", "\"",
+ y_absl::CEscape(Verbosity()), "\"", ", stacktrace_minloglevel: ", "\"",
+ y_absl::CEscape(StacktraceMinloglevel()), "\"",
+ ", enable_fork_support: ", EnableForkSupport() ? "true" : "false",
+ ", poll_strategy: ", "\"", y_absl::CEscape(PollStrategy()), "\"",
+ ", abort_on_leaks: ", AbortOnLeaks() ? "true" : "false",
+ ", system_ssl_roots_dir: ", "\"", y_absl::CEscape(SystemSslRootsDir()),
+ "\"", ", default_ssl_roots_file_path: ", "\"",
+ y_absl::CEscape(DefaultSslRootsFilePath()), "\"",
+ ", not_use_system_ssl_roots: ", NotUseSystemSslRoots() ? "true" : "false",
+ ", ssl_cipher_suites: ", "\"", y_absl::CEscape(SslCipherSuites()), "\"");
+}
+
+} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/config/config_vars.h b/contrib/libs/grpc/src/core/lib/config/config_vars.h
new file mode 100644
index 0000000000..2c5823f786
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/config/config_vars.h
@@ -0,0 +1,128 @@
+// Copyright 2023 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//
+// Automatically generated by tools/codegen/core/gen_config_vars.py
+//
+
+#ifndef GRPC_SRC_CORE_LIB_CONFIG_CONFIG_VARS_H
+#define GRPC_SRC_CORE_LIB_CONFIG_CONFIG_VARS_H
+
+#include <grpc/support/port_platform.h>
+
+#include <stdint.h>
+
+#include <atomic>
+#include <util/generic/string.h>
+#include <util/string/cast.h>
+
+#include "y_absl/strings/string_view.h"
+#include "y_absl/types/optional.h"
+
+namespace grpc_core {
+
+class ConfigVars {
+ public:
+ struct Overrides {
+ y_absl::optional<int32_t> client_channel_backup_poll_interval_ms;
+ y_absl::optional<bool> enable_fork_support;
+ y_absl::optional<bool> abort_on_leaks;
+ y_absl::optional<bool> not_use_system_ssl_roots;
+ y_absl::optional<TString> experiments;
+ y_absl::optional<TString> dns_resolver;
+ y_absl::optional<TString> trace;
+ y_absl::optional<TString> verbosity;
+ y_absl::optional<TString> stacktrace_minloglevel;
+ y_absl::optional<TString> poll_strategy;
+ y_absl::optional<TString> system_ssl_roots_dir;
+ y_absl::optional<TString> default_ssl_roots_file_path;
+ y_absl::optional<TString> ssl_cipher_suites;
+ };
+ ConfigVars(const ConfigVars&) = delete;
+ ConfigVars& operator=(const ConfigVars&) = delete;
+ // Get the core configuration; if it does not exist, create it.
+ static const ConfigVars& Get() {
+ auto* p = config_vars_.load(std::memory_order_acquire);
+ if (p != nullptr) return *p;
+ return Load();
+ }
+ static void SetOverrides(const Overrides& overrides);
+ // Drop the config vars. Users must ensure no other threads are
+ // accessing the configuration.
+ static void Reset();
+ TString ToString() const;
+ // A comma separated list of currently active experiments. Experiments may be
+ // prefixed with a '-' to disable them.
+ y_absl::string_view Experiments() const { return experiments_; }
+ // Declares the interval in ms between two backup polls on client channels.
+ // These polls are run in the timer thread so that gRPC can process connection
+ // failures while there is no active polling thread. They help reconnect
+ // disconnected client channels (mostly due to idleness), so that the next RPC
+ // on this channel won't fail. Set to 0 to turn off the backup polls.
+ int32_t ClientChannelBackupPollIntervalMs() const {
+ return client_channel_backup_poll_interval_ms_;
+ }
+ // Declares which DNS resolver to use. The default is ares if gRPC is built
+ // with c-ares support. Otherwise, the value of this environment variable is
+ // ignored.
+ y_absl::string_view DnsResolver() const { return dns_resolver_; }
+ // A comma separated list of tracers that provide additional insight into how
+ // gRPC C core is processing requests via debug logs.
+ y_absl::string_view Trace() const { return trace_; }
+ // Default gRPC logging verbosity
+ y_absl::string_view Verbosity() const { return verbosity_; }
+ // Messages logged at the same or higher level than this will print stacktrace
+ y_absl::string_view StacktraceMinloglevel() const {
+ return stacktrace_minloglevel_;
+ }
+ // Enable fork support
+ bool EnableForkSupport() const { return enable_fork_support_; }
+ // Declares which polling engines to try when starting gRPC. This is a
+ // comma-separated list of engines, which are tried in priority order first ->
+ // last.
+ y_absl::string_view PollStrategy() const { return poll_strategy_; }
+ // A debugging aid to cause a call to abort() when gRPC objects are leaked
+ // past grpc_shutdown()
+ bool AbortOnLeaks() const { return abort_on_leaks_; }
+ // Custom directory to SSL Roots
+ TString SystemSslRootsDir() const;
+ // Path to the default SSL roots file.
+ TString DefaultSslRootsFilePath() const;
+ // Disable loading system root certificates.
+ bool NotUseSystemSslRoots() const { return not_use_system_ssl_roots_; }
+ // A colon separated list of cipher suites to use with OpenSSL
+ y_absl::string_view SslCipherSuites() const { return ssl_cipher_suites_; }
+
+ private:
+ explicit ConfigVars(const Overrides& overrides);
+ static const ConfigVars& Load();
+ static std::atomic<ConfigVars*> config_vars_;
+ int32_t client_channel_backup_poll_interval_ms_;
+ bool enable_fork_support_;
+ bool abort_on_leaks_;
+ bool not_use_system_ssl_roots_;
+ TString experiments_;
+ TString dns_resolver_;
+ TString trace_;
+ TString verbosity_;
+ TString stacktrace_minloglevel_;
+ TString poll_strategy_;
+ TString ssl_cipher_suites_;
+ y_absl::optional<TString> override_system_ssl_roots_dir_;
+ y_absl::optional<TString> override_default_ssl_roots_file_path_;
+};
+
+} // namespace grpc_core
+
+#endif // GRPC_SRC_CORE_LIB_CONFIG_CONFIG_VARS_H
diff --git a/contrib/libs/grpc/src/core/lib/config/config_vars_non_generated.cc b/contrib/libs/grpc/src/core/lib/config/config_vars_non_generated.cc
new file mode 100644
index 0000000000..e0b0270efc
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/config/config_vars_non_generated.cc
@@ -0,0 +1,52 @@
+// Copyright 2022 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <grpc/support/port_platform.h>
+
+#include <stdint.h>
+
+#include <atomic>
+#include <util/generic/string.h>
+#include <util/string/cast.h>
+
+#include "src/core/lib/config/config_vars.h"
+
+namespace grpc_core {
+
+std::atomic<ConfigVars*> ConfigVars::config_vars_{nullptr};
+
+const ConfigVars& ConfigVars::Load() {
+ // Called from get, so we know there's no existing config vars.
+ // We might race for them though.
+ auto vars = new ConfigVars({});
+ ConfigVars* expected = nullptr;
+ if (!config_vars_.compare_exchange_strong(expected, vars,
+ std::memory_order_acq_rel,
+ std::memory_order_acquire)) {
+ delete vars;
+ return *expected;
+ }
+ return *vars;
+}
+
+void ConfigVars::Reset() {
+ delete config_vars_.exchange(nullptr, std::memory_order_acq_rel);
+}
+
+void ConfigVars::SetOverrides(const Overrides& overrides) {
+ delete config_vars_.exchange(new ConfigVars(overrides),
+ std::memory_order_acq_rel);
+}
+
+} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/config/load_config.cc b/contrib/libs/grpc/src/core/lib/config/load_config.cc
new file mode 100644
index 0000000000..bda8c38835
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/config/load_config.cc
@@ -0,0 +1,66 @@
+// Copyright 2022 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/config/load_config.h"
+
+#include <stdio.h>
+
+#include "y_absl/flags/marshalling.h"
+#include "y_absl/strings/numbers.h"
+#include "y_absl/types/optional.h"
+
+#include "src/core/lib/gprpp/env.h"
+
+namespace grpc_core {
+
+namespace {
+y_absl::optional<TString> LoadEnv(y_absl::string_view environment_variable) {
+ return GetEnv(TString(environment_variable).c_str());
+}
+} // namespace
+
+TString LoadConfigFromEnv(y_absl::string_view environment_variable,
+ const char* default_value) {
+ return LoadEnv(environment_variable).value_or(default_value);
+}
+
+int32_t LoadConfigFromEnv(y_absl::string_view environment_variable,
+ int32_t default_value) {
+ auto env = LoadEnv(environment_variable);
+ if (env.has_value()) {
+ int32_t out;
+ if (y_absl::SimpleAtoi(*env, &out)) return out;
+ fprintf(stderr, "Error reading int from %s: '%s' is not a number",
+ TString(environment_variable).c_str(), env->c_str());
+ }
+ return default_value;
+}
+
+bool LoadConfigFromEnv(y_absl::string_view environment_variable,
+ bool default_value) {
+ auto env = LoadEnv(environment_variable);
+ if (env.has_value()) {
+ bool out;
+ TString error;
+ if (y_absl::ParseFlag(env->c_str(), &out, &error)) return out;
+ fprintf(stderr, "Error reading bool from %s: '%s' is not a bool: %s",
+ TString(environment_variable).c_str(), env->c_str(),
+ error.c_str());
+ }
+ return default_value;
+}
+
+} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/config/load_config.h b/contrib/libs/grpc/src/core/lib/config/load_config.h
new file mode 100644
index 0000000000..281206a2e2
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/config/load_config.h
@@ -0,0 +1,50 @@
+// Copyright 2022 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef GRPC_SRC_CORE_LIB_CONFIG_LOAD_CONFIG_H
+#define GRPC_SRC_CORE_LIB_CONFIG_LOAD_CONFIG_H
+
+#include <grpc/support/port_platform.h>
+
+#include <stdint.h>
+
+#include <util/generic/string.h>
+#include <util/string/cast.h>
+
+#include "y_absl/flags/flag.h"
+#include "y_absl/strings/string_view.h"
+#include "y_absl/types/optional.h"
+
+namespace grpc_core {
+
+TString LoadConfigFromEnv(y_absl::string_view environment_variable,
+ const char* default_value);
+int32_t LoadConfigFromEnv(y_absl::string_view environment_variable,
+ int32_t default_value);
+bool LoadConfigFromEnv(y_absl::string_view environment_variable,
+ bool default_value);
+
+template <typename T, typename D>
+T LoadConfig(const y_absl::Flag<y_absl::optional<T>>& flag,
+ y_absl::string_view environment_variable,
+ const y_absl::optional<T>& override, D default_value) {
+ if (override.has_value()) return *override;
+ auto from_flag = y_absl::GetFlag(flag);
+ if (from_flag.has_value()) return std::move(*from_flag);
+ return LoadConfigFromEnv(environment_variable, default_value);
+}
+
+} // namespace grpc_core
+
+#endif // GRPC_SRC_CORE_LIB_CONFIG_LOAD_CONFIG_H
diff --git a/contrib/libs/grpc/src/core/lib/debug/trace.cc b/contrib/libs/grpc/src/core/lib/debug/trace.cc
index 865f026b82..b388799a28 100644
--- a/contrib/libs/grpc/src/core/lib/debug/trace.cc
+++ b/contrib/libs/grpc/src/core/lib/debug/trace.cc
@@ -22,16 +22,17 @@
#include <string.h>
+#include <util/generic/string.h>
+#include <util/string/cast.h>
#include <type_traits>
+#include "y_absl/strings/string_view.h"
+
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
-GPR_GLOBAL_CONFIG_DEFINE_STRING(
- grpc_trace, "",
- "A comma separated list of tracers that provide additional insight into "
- "how gRPC C core is processing requests via debug logs.");
+#include "src/core/lib/config/config_vars.h"
int grpc_tracer_set_enabled(const char* name, int enabled);
@@ -144,8 +145,7 @@ void grpc_tracer_init(const char* env_var_name) {
}
void grpc_tracer_init() {
- grpc_core::UniquePtr<char> value = GPR_GLOBAL_CONFIG_GET(grpc_trace);
- parse(value.get());
+ parse(TString(grpc_core::ConfigVars::Get().Trace()).c_str());
}
int grpc_tracer_set_enabled(const char* name, int enabled) {
diff --git a/contrib/libs/grpc/src/core/lib/debug/trace.h b/contrib/libs/grpc/src/core/lib/debug/trace.h
index 2264653630..9e7071075f 100644
--- a/contrib/libs/grpc/src/core/lib/debug/trace.h
+++ b/contrib/libs/grpc/src/core/lib/debug/trace.h
@@ -23,11 +23,6 @@
#include <atomic>
-#include "src/core/lib/gprpp/global_config.h"
-#include "src/core/lib/gprpp/memory.h"
-
-GPR_GLOBAL_CONFIG_DECLARE_STRING(grpc_trace);
-
// TODO(veblush): Remove this deprecated function once codes depending on this
// function are updated in the internal repo.
void grpc_tracer_init(const char* env_var_name);
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/event_engine.cc b/contrib/libs/grpc/src/core/lib/event_engine/event_engine.cc
index a81145912b..ff455a9737 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/event_engine.cc
+++ b/contrib/libs/grpc/src/core/lib/event_engine/event_engine.cc
@@ -13,13 +13,48 @@
// limitations under the License.
#include <grpc/support/port_platform.h>
+#include <stdint.h>
+
#include <grpc/event_engine/event_engine.h>
namespace grpc_event_engine {
namespace experimental {
-constexpr EventEngine::TaskHandle EventEngine::kInvalidTaskHandle;
-constexpr EventEngine::ConnectionHandle EventEngine::kInvalidConnectionHandle;
+const EventEngine::TaskHandle EventEngine::TaskHandle::kInvalid = {-1, -1};
+const EventEngine::ConnectionHandle EventEngine::ConnectionHandle::kInvalid = {
+ -1, -1};
+const EventEngine::DNSResolver::LookupTaskHandle
+ EventEngine::DNSResolver::LookupTaskHandle::kInvalid = {-1, -1};
+
+bool operator==(const EventEngine::TaskHandle& lhs,
+ const EventEngine::TaskHandle& rhs) {
+ return lhs.keys[0] == rhs.keys[0] && lhs.keys[1] == rhs.keys[1];
+}
+
+bool operator!=(const EventEngine::TaskHandle& lhs,
+ const EventEngine::TaskHandle& rhs) {
+ return !(lhs == rhs);
+}
+
+bool operator==(const EventEngine::ConnectionHandle& lhs,
+ const EventEngine::ConnectionHandle& rhs) {
+ return lhs.keys[0] == rhs.keys[0] && lhs.keys[1] == rhs.keys[1];
+}
+
+bool operator!=(const EventEngine::ConnectionHandle& lhs,
+ const EventEngine::ConnectionHandle& rhs) {
+ return !(lhs == rhs);
+}
+
+bool operator==(const EventEngine::DNSResolver::LookupTaskHandle& lhs,
+ const EventEngine::DNSResolver::LookupTaskHandle& rhs) {
+ return lhs.keys[0] == rhs.keys[0] && lhs.keys[1] == rhs.keys[1];
+}
+
+bool operator!=(const EventEngine::DNSResolver::LookupTaskHandle& lhs,
+ const EventEngine::DNSResolver::LookupTaskHandle& rhs) {
+ return !(lhs == rhs);
+}
} // namespace experimental
} // namespace grpc_event_engine
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/handle_containers.h b/contrib/libs/grpc/src/core/lib/event_engine/handle_containers.h
index 32f6dd444b..0910ea3ee8 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/handle_containers.h
+++ b/contrib/libs/grpc/src/core/lib/event_engine/handle_containers.h
@@ -39,34 +39,19 @@ struct TaskHandleComparator {
return y_absl::Hash<HashType>()({handle.keys[0], handle.keys[1]});
}
};
- struct Eq {
- using is_transparent = void;
- bool operator()(const TaskHandle& lhs, const TaskHandle& rhs) const {
- return lhs.keys[0] == rhs.keys[0] && lhs.keys[1] == rhs.keys[1];
- }
- };
};
-using TaskHandleSet = y_absl::flat_hash_set<
- grpc_event_engine::experimental::EventEngine::TaskHandle,
- TaskHandleComparator<
- grpc_event_engine::experimental::EventEngine::TaskHandle>::Hash,
- TaskHandleComparator<
- grpc_event_engine::experimental::EventEngine::TaskHandle>::Eq>;
+using TaskHandleSet =
+ y_absl::flat_hash_set<EventEngine::TaskHandle,
+ TaskHandleComparator<EventEngine::TaskHandle>::Hash>;
using ConnectionHandleSet = y_absl::flat_hash_set<
- grpc_event_engine::experimental::EventEngine::ConnectionHandle,
- TaskHandleComparator<
- grpc_event_engine::experimental::EventEngine::ConnectionHandle>::Hash,
- TaskHandleComparator<
- grpc_event_engine::experimental::EventEngine::ConnectionHandle>::Eq>;
+ EventEngine::ConnectionHandle,
+ TaskHandleComparator<EventEngine::ConnectionHandle>::Hash>;
using LookupTaskHandleSet = y_absl::flat_hash_set<
- grpc_event_engine::experimental::EventEngine::DNSResolver::LookupTaskHandle,
- TaskHandleComparator<grpc_event_engine::experimental::EventEngine::
- DNSResolver::LookupTaskHandle>::Hash,
- TaskHandleComparator<grpc_event_engine::experimental::EventEngine::
- DNSResolver::LookupTaskHandle>::Eq>;
+ EventEngine::DNSResolver::LookupTaskHandle,
+ TaskHandleComparator<EventEngine::DNSResolver::LookupTaskHandle>::Hash>;
} // namespace experimental
} // namespace grpc_event_engine
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/memory_allocator_factory.h b/contrib/libs/grpc/src/core/lib/event_engine/memory_allocator_factory.h
new file mode 100644
index 0000000000..28cf5c30bd
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/event_engine/memory_allocator_factory.h
@@ -0,0 +1,47 @@
+// Copyright 2023 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef GRPC_SRC_CORE_LIB_EVENT_ENGINE_MEMORY_ALLOCATOR_FACTORY_H
+#define GRPC_SRC_CORE_LIB_EVENT_ENGINE_MEMORY_ALLOCATOR_FACTORY_H
+#include <grpc/support/port_platform.h>
+
+#include <memory>
+#include <utility>
+
+#include "y_absl/strings/string_view.h"
+
+#include <grpc/event_engine/memory_allocator.h>
+
+#include "src/core/lib/resource_quota/memory_quota.h"
+
+namespace grpc_event_engine {
+namespace experimental {
+
+class MemoryQuotaBasedMemoryAllocatorFactory : public MemoryAllocatorFactory {
+ public:
+ explicit MemoryQuotaBasedMemoryAllocatorFactory(
+ grpc_core::MemoryQuotaRefPtr memory_quota)
+ : memory_quota_(std::move(memory_quota)) {}
+
+ MemoryAllocator CreateMemoryAllocator(y_absl::string_view name) override {
+ return memory_quota_->CreateMemoryAllocator(name);
+ }
+
+ private:
+ grpc_core::MemoryQuotaRefPtr memory_quota_;
+};
+
+} // namespace experimental
+} // namespace grpc_event_engine
+
+#endif // GRPC_SRC_CORE_LIB_EVENT_ENGINE_MEMORY_ALLOCATOR_FACTORY_H
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/ev_poll_posix.cc b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/ev_poll_posix.cc
index 45ecda6a7f..05eabcbc29 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/ev_poll_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/ev_poll_posix.cc
@@ -40,7 +40,6 @@
#include "src/core/lib/event_engine/posix_engine/event_poller.h"
#include "src/core/lib/event_engine/posix_engine/posix_engine_closure.h"
#include "src/core/lib/gprpp/crash.h"
-#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET_EV_POLL
@@ -58,14 +57,11 @@
#include "src/core/lib/event_engine/posix_engine/wakeup_fd_posix_default.h"
#include "src/core/lib/event_engine/time_util.h"
#include "src/core/lib/gprpp/fork.h"
-#include "src/core/lib/gprpp/global_config.h"
#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/gprpp/strerror.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/gprpp/time.h"
-GPR_GLOBAL_CONFIG_DECLARE_STRING(grpc_poll_strategy);
-
static const intptr_t kClosureNotReady = 0;
static const intptr_t kClosureReady = 1;
static const int kPollinCheck = POLLIN | POLLHUP | POLLERR;
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/event_poller_posix_default.cc b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/event_poller_posix_default.cc
index 42a5598ede..a1680ad874 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/event_poller_posix_default.cc
+++ b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/event_poller_posix_default.cc
@@ -17,17 +17,12 @@
#include "y_absl/strings/str_split.h"
#include "y_absl/strings/string_view.h"
+#include "src/core/lib/config/config_vars.h"
#include "src/core/lib/event_engine/posix_engine/ev_epoll1_linux.h"
#include "src/core/lib/event_engine/posix_engine/ev_poll_posix.h"
#include "src/core/lib/event_engine/posix_engine/event_poller.h"
-#include "src/core/lib/gprpp/global_config.h"
-#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/port.h"
-#ifdef GRPC_POSIX_SOCKET_TCP
-GPR_GLOBAL_CONFIG_DECLARE_STRING(grpc_poll_strategy);
-#endif
-
namespace grpc_event_engine {
namespace experimental {
@@ -41,10 +36,9 @@ bool PollStrategyMatches(y_absl::string_view strategy, y_absl::string_view want)
} // namespace
PosixEventPoller* MakeDefaultPoller(Scheduler* scheduler) {
- static const char* poll_strategy =
- GPR_GLOBAL_CONFIG_GET(grpc_poll_strategy).release();
PosixEventPoller* poller = nullptr;
- auto strings = y_absl::StrSplit(poll_strategy, ',');
+ auto strings =
+ y_absl::StrSplit(grpc_core::ConfigVars::Get().PollStrategy(), ',');
for (auto it = strings.begin(); it != strings.end() && poller == nullptr;
it++) {
if (PollStrategyMatches(*it, "epoll1")) {
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_endpoint.cc b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_endpoint.cc
index 208a34622a..e1aa7cce92 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_endpoint.cc
+++ b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_endpoint.cc
@@ -576,12 +576,11 @@ void PosixEndpointImpl::HandleRead(y_absl::Status status) {
Unref();
}
-void PosixEndpointImpl::Read(y_absl::AnyInvocable<void(y_absl::Status)> on_read,
+bool PosixEndpointImpl::Read(y_absl::AnyInvocable<void(y_absl::Status)> on_read,
SliceBuffer* buffer,
const EventEngine::Endpoint::ReadArgs* args) {
grpc_core::ReleasableMutexLock lock(&read_mu_);
GPR_ASSERT(read_cb_ == nullptr);
- read_cb_ = std::move(on_read);
incoming_buffer_ = buffer;
incoming_buffer_->Clear();
incoming_buffer_->Swap(last_read_buffer_);
@@ -592,6 +591,7 @@ void PosixEndpointImpl::Read(y_absl::AnyInvocable<void(y_absl::Status)> on_read,
}
Ref().release();
if (is_first_read_) {
+ read_cb_ = std::move(on_read);
UpdateRcvLowat();
// Endpoint read called for the very first time. Register read callback
// with the polling engine.
@@ -599,16 +599,40 @@ void PosixEndpointImpl::Read(y_absl::AnyInvocable<void(y_absl::Status)> on_read,
lock.Release();
handle_->NotifyOnRead(on_read_);
} else if (inq_ == 0) {
+ read_cb_ = std::move(on_read);
UpdateRcvLowat();
lock.Release();
// Upper layer asked to read more but we know there is no pending data to
// read from previous reads. So, wait for POLLIN.
handle_->NotifyOnRead(on_read_);
} else {
- lock.Release();
- on_read_->SetStatus(y_absl::OkStatus());
- engine_->Run(on_read_);
+ y_absl::Status status;
+ MaybeMakeReadSlices();
+ if (!TcpDoRead(status)) {
+ UpdateRcvLowat();
+ read_cb_ = std::move(on_read);
+ // We've consumed the edge, request a new one.
+ lock.Release();
+ handle_->NotifyOnRead(on_read_);
+ return false;
+ }
+ if (!status.ok()) {
+ // Read failed immediately. Schedule the on_read callback to run
+ // asynchronously.
+ lock.Release();
+ engine_->Run([on_read = std::move(on_read), status]() mutable {
+ on_read(status);
+ });
+ Unref();
+ return false;
+ }
+ // Read succeeded immediately. Return true and don't run the on_read
+ // callback.
+ incoming_buffer_ = nullptr;
+ Unref();
+ return true;
}
+ return false;
}
#ifdef GRPC_LINUX_ERRQUEUE
@@ -938,7 +962,7 @@ bool PosixEndpointImpl::DoFlushZerocopy(TcpZerocopySendRecord* record,
} else {
#ifdef GRPC_LINUX_ERRQUEUE
GRPC_LOG_EVERY_N_SEC(
- 1,
+ 1, GPR_INFO,
"Tx0cp encountered an ENOBUFS error possibly because one or "
"both of RLIMIT_MEMLOCK or hard memlock ulimit values are too "
"small for the intended user. Current system value of "
@@ -1104,7 +1128,7 @@ void PosixEndpointImpl::HandleWrite(y_absl::Status status) {
}
}
-void PosixEndpointImpl::Write(
+bool PosixEndpointImpl::Write(
y_absl::AnyInvocable<void(y_absl::Status)> on_writable, SliceBuffer* data,
const EventEngine::Endpoint::WriteArgs* args) {
y_absl::Status status = y_absl::OkStatus();
@@ -1115,11 +1139,15 @@ void PosixEndpointImpl::Write(
GPR_DEBUG_ASSERT(data != nullptr);
if (data->Length() == 0) {
- on_writable(handle_->IsHandleShutdown()
- ? TcpAnnotateError(y_absl::InternalError("EOF"))
- : status);
TcpShutdownTracedBufferList();
- return;
+ if (handle_->IsHandleShutdown()) {
+ status = TcpAnnotateError(y_absl::InternalError("EOF"));
+ engine_->Run([on_writable = std::move(on_writable), status]() mutable {
+ on_writable(status);
+ });
+ return false;
+ }
+ return true;
}
zerocopy_send_record = TcpGetSendZerocopyRecord(*data);
@@ -1143,14 +1171,19 @@ void PosixEndpointImpl::Write(
write_cb_ = std::move(on_writable);
current_zerocopy_send_ = zerocopy_send_record;
handle_->NotifyOnWrite(on_write_);
- } else {
- // TODO(vigneshbabu): Consider eventually running this callback inline to
- // avoid a thread hop. At the time of submission, it causes deadlocks which
- // should be reolved after ExecCtx removal.
+ return false;
+ }
+ if (!status.ok()) {
+ // Write failed immediately. Schedule the on_writable callback to run
+ // asynchronously.
engine_->Run([on_writable = std::move(on_writable), status]() mutable {
on_writable(status);
});
+ return false;
}
+ // Write succeeded immediately. Return true and don't run the on_writable
+ // callback.
+ return true;
}
void PosixEndpointImpl::MaybeShutdown(
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_endpoint.h b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_endpoint.h
index 2609974b37..a56db67ba4 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_endpoint.h
+++ b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_endpoint.h
@@ -472,12 +472,12 @@ class PosixEndpointImpl : public grpc_core::RefCounted<PosixEndpointImpl> {
grpc_event_engine::experimental::MemoryAllocator&& allocator,
const PosixTcpOptions& options);
~PosixEndpointImpl() override;
- void Read(
+ bool Read(
y_absl::AnyInvocable<void(y_absl::Status)> on_read,
grpc_event_engine::experimental::SliceBuffer* buffer,
const grpc_event_engine::experimental::EventEngine::Endpoint::ReadArgs*
args);
- void Write(
+ bool Write(
y_absl::AnyInvocable<void(y_absl::Status)> on_writable,
grpc_event_engine::experimental::SliceBuffer* data,
const grpc_event_engine::experimental::EventEngine::Endpoint::WriteArgs*
@@ -608,20 +608,20 @@ class PosixEndpoint : public PosixEndpointWithFdSupport {
: impl_(new PosixEndpointImpl(handle, on_shutdown, std::move(engine),
std::move(allocator), options)) {}
- void Read(
+ bool Read(
y_absl::AnyInvocable<void(y_absl::Status)> on_read,
grpc_event_engine::experimental::SliceBuffer* buffer,
const grpc_event_engine::experimental::EventEngine::Endpoint::ReadArgs*
args) override {
- impl_->Read(std::move(on_read), buffer, args);
+ return impl_->Read(std::move(on_read), buffer, args);
}
- void Write(
+ bool Write(
y_absl::AnyInvocable<void(y_absl::Status)> on_writable,
grpc_event_engine::experimental::SliceBuffer* data,
const grpc_event_engine::experimental::EventEngine::Endpoint::WriteArgs*
args) override {
- impl_->Write(std::move(on_writable), data, args);
+ return impl_->Write(std::move(on_writable), data, args);
}
const grpc_event_engine::experimental::EventEngine::ResolvedAddress&
@@ -661,14 +661,14 @@ class PosixEndpoint : public PosixEndpointWithFdSupport {
public:
PosixEndpoint() = default;
- void Read(y_absl::AnyInvocable<void(y_absl::Status)> /*on_read*/,
+ bool Read(y_absl::AnyInvocable<void(y_absl::Status)> /*on_read*/,
grpc_event_engine::experimental::SliceBuffer* /*buffer*/,
const grpc_event_engine::experimental::EventEngine::Endpoint::
ReadArgs* /*args*/) override {
grpc_core::Crash("PosixEndpoint::Read not supported on this platform");
}
- void Write(y_absl::AnyInvocable<void(y_absl::Status)> /*on_writable*/,
+ bool Write(y_absl::AnyInvocable<void(y_absl::Status)> /*on_writable*/,
grpc_event_engine::experimental::SliceBuffer* /*data*/,
const grpc_event_engine::experimental::EventEngine::Endpoint::
WriteArgs* /*args*/) override {
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_engine.cc b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_engine.cc
index 988fe81381..67d15d22b7 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_engine.cc
+++ b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_engine.cc
@@ -233,7 +233,7 @@ EventEngine::ConnectionHandle PosixEventEngine::ConnectInternal(
ep = y_absl::FailedPreconditionError(y_absl::StrCat(
"connect failed: ", "invalid addr: ",
addr_uri.value()))]() mutable { on_connect(std::move(ep)); });
- return EventEngine::kInvalidConnectionHandle;
+ return EventEngine::ConnectionHandle::kInvalid;
}
TString name = y_absl::StrCat("tcp-client:", addr_uri.value());
@@ -254,7 +254,7 @@ EventEngine::ConnectionHandle PosixEventEngine::ConnectInternal(
std::move(allocator), options)]() mutable {
on_connect(std::move(ep));
});
- return EventEngine::kInvalidConnectionHandle;
+ return EventEngine::ConnectionHandle::kInvalid;
}
if (saved_errno != EWOULDBLOCK && saved_errno != EINPROGRESS) {
// Connection already failed. Return 0 to discourage any cancellation
@@ -266,7 +266,7 @@ EventEngine::ConnectionHandle PosixEventEngine::ConnectInternal(
" error: ", std::strerror(saved_errno)))]() mutable {
on_connect(std::move(ep));
});
- return EventEngine::kInvalidConnectionHandle;
+ return EventEngine::ConnectionHandle::kInvalid;
}
AsyncConnect* ac = new AsyncConnect(
std::move(on_connect), shared_from_this(), executor_.get(), handle,
@@ -300,7 +300,8 @@ PosixEnginePollerManager::PosixEnginePollerManager(
PosixEnginePollerManager::PosixEnginePollerManager(PosixEventPoller* poller)
: poller_(poller),
poller_state_(PollerState::kExternal),
- executor_(nullptr) {
+ executor_(nullptr),
+ trigger_shutdown_called_(false) {
GPR_DEBUG_ASSERT(poller_ != nullptr);
}
@@ -560,7 +561,7 @@ EventEngine::ConnectionHandle PosixEventEngine::Connect(
if (!socket.ok()) {
Run([on_connect = std::move(on_connect),
status = socket.status()]() mutable { on_connect(status); });
- return EventEngine::kInvalidConnectionHandle;
+ return EventEngine::ConnectionHandle::kInvalid;
}
return ConnectInternal((*socket).sock, std::move(on_connect),
(*socket).mapped_target_addr,
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc
index 4e58f9566c..3230b72c7e 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc
+++ b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc
@@ -65,11 +65,14 @@ PosixEngineListenerImpl::PosixEngineListenerImpl(
y_absl::StatusOr<int> PosixEngineListenerImpl::Bind(
const EventEngine::ResolvedAddress& addr,
PosixListenerWithFdSupport::OnPosixBindNewFdCallback on_bind_new_fd) {
+ y_absl::MutexLock lock(&this->mu_);
+ if (this->started_) {
+ return y_absl::FailedPreconditionError(
+ "Listener is already started, ports can no longer be bound");
+ }
EventEngine::ResolvedAddress res_addr = addr;
EventEngine::ResolvedAddress addr6_v4mapped;
int requested_port = ResolvedAddressGetPort(res_addr);
- y_absl::MutexLock lock(&this->mu_);
- GPR_ASSERT(!this->started_);
GPR_ASSERT(addr.size() <= EventEngine::ResolvedAddress::MAX_SIZE_BYTES);
UnlinkIfUnixDomainSocket(addr);
@@ -280,7 +283,7 @@ PosixEngineListenerImpl::~PosixEngineListenerImpl() {
// been destroyed. This is because each AsyncConnectionAcceptor has a
// shared_ptr ref to the parent PosixEngineListenerImpl.
if (on_shutdown_ != nullptr) {
- on_shutdown_(y_absl::InternalError("Shutting down listener"));
+ on_shutdown_(y_absl::OkStatus());
}
}
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc
index 76af60b866..9dbb6e3090 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc
+++ b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc
@@ -30,6 +30,7 @@
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/crash.h" // IWYU pragma: keep
+#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
@@ -96,8 +97,21 @@ y_absl::Status ErrorForFd(
int CreateSocket(std::function<int(int, int, int)> socket_factory, int family,
int type, int protocol) {
- return socket_factory != nullptr ? socket_factory(family, type, protocol)
- : socket(family, type, protocol);
+ int res = socket_factory != nullptr ? socket_factory(family, type, protocol)
+ : socket(family, type, protocol);
+ if (res < 0 && errno == EMFILE) {
+ int saved_errno = errno;
+ GRPC_LOG_EVERY_N_SEC(
+ 10, GPR_ERROR,
+ "socket(%d, %d, %d) returned %d with error: |%s|. This process "
+ "might not have a sufficient file descriptor limit for the number "
+ "of connections grpc wants to open (which is generally a function of "
+ "the number of grpc channels, the lb policy of each channel, and the "
+ "number of backends each channel is load balancing across).",
+ family, type, protocol, res, grpc_core::StrError(errno).c_str());
+ errno = saved_errno;
+ }
+ return res;
}
y_absl::Status PrepareTcpClientSocket(PosixSocketWrapper sock,
@@ -126,6 +140,11 @@ y_absl::Status PrepareTcpClientSocket(PosixSocketWrapper sock,
return y_absl::OkStatus();
}
+bool SetSocketDualStack(int fd) {
+ const int off = 0;
+ return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off));
+}
+
#endif // GRPC_POSIX_SOCKET_UTILS_COMMON
} // namespace
@@ -606,11 +625,6 @@ y_absl::Status PosixSocketWrapper::ApplySocketMutatorInOptions(
return SetSocketMutator(usage, options.socket_mutator);
}
-bool PosixSocketWrapper::SetSocketDualStack() {
- const int off = 0;
- return 0 == setsockopt(fd_, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off));
-}
-
bool PosixSocketWrapper::IsIpv6LoopbackAvailable() {
static bool kIpv6LoopbackAvailable = []() -> bool {
int fd = socket(AF_INET6, SOCK_STREAM, 0);
@@ -686,19 +700,18 @@ y_absl::StatusOr<PosixSocketWrapper> PosixSocketWrapper::CreateDualStackSocket(
newfd = -1;
errno = EAFNOSUPPORT;
}
- if (newfd < 0) {
- return ErrorForFd(newfd, addr);
- }
- PosixSocketWrapper sock(newfd);
// Check if we've got a valid dualstack socket.
- if (sock.SetSocketDualStack()) {
+ if (newfd > 0 && SetSocketDualStack(newfd)) {
dsmode = PosixSocketWrapper::DSMode::DSMODE_DUALSTACK;
- return sock;
+ return PosixSocketWrapper(newfd);
}
// If this isn't an IPv4 address, then return whatever we've got.
if (!ResolvedAddressIsV4Mapped(addr, nullptr)) {
+ if (newfd <= 0) {
+ return ErrorForFd(newfd, addr);
+ }
dsmode = PosixSocketWrapper::DSMode::DSMODE_IPV6;
- return sock;
+ return PosixSocketWrapper(newfd);
}
// Fall back to AF_INET.
if (newfd >= 0) {
@@ -820,10 +833,6 @@ y_absl::Status PosixSocketWrapper::ApplySocketMutatorInOptions(
grpc_core::Crash("unimplemented");
}
-bool PosixSocketWrapper::SetSocketDualStack() {
- grpc_core::Crash("unimplemented");
-}
-
bool PosixSocketWrapper::IsSocketReusePortSupported() {
grpc_core::Crash("unimplemented");
}
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/tcp_socket_utils.h b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/tcp_socket_utils.h
index c8f5723a4c..3a40b16027 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/tcp_socket_utils.h
+++ b/contrib/libs/grpc/src/core/lib/event_engine/posix_engine/tcp_socket_utils.h
@@ -239,9 +239,6 @@ class PosixSocketWrapper {
DSMODE_DUALSTACK
};
- // Tries to set the socket to dualstack. Returns true on success.
- bool SetSocketDualStack();
-
// Returns the underlying file-descriptor.
int Fd() const { return fd_; }
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/resolved_address.cc b/contrib/libs/grpc/src/core/lib/event_engine/resolved_address.cc
index 49ea888b61..7134c3209d 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/resolved_address.cc
+++ b/contrib/libs/grpc/src/core/lib/event_engine/resolved_address.cc
@@ -31,7 +31,8 @@ namespace experimental {
EventEngine::ResolvedAddress::ResolvedAddress(const sockaddr* address,
socklen_t size)
: size_(size) {
- GPR_ASSERT(size <= sizeof(address_));
+ GPR_DEBUG_ASSERT(size >= 0);
+ GPR_ASSERT(static_cast<size_t>(size) <= sizeof(address_));
memcpy(&address_, address, size);
}
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/windows/win_socket.cc b/contrib/libs/grpc/src/core/lib/event_engine/windows/win_socket.cc
index d6d584a46b..c7543ee2dc 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/windows/win_socket.cc
+++ b/contrib/libs/grpc/src/core/lib/event_engine/windows/win_socket.cc
@@ -58,7 +58,6 @@ void WinSocket::Shutdown() {
this);
return;
}
- GRPC_EVENT_ENGINE_ENDPOINT_TRACE("WinSocket::%p shutting down now.", this);
// Grab the function pointer for DisconnectEx for that specific socket.
// It may change depending on the interface.
GUID guid = WSAID_DISCONNECTEX;
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.cc b/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.cc
index f42b8a7dbe..0d6cd089d6 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.cc
+++ b/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.cc
@@ -34,19 +34,29 @@ namespace grpc_event_engine {
namespace experimental {
namespace {
-constexpr int64_t kDefaultTargetReadSize = 8192;
+constexpr size_t kDefaultTargetReadSize = 8192;
constexpr int kMaxWSABUFCount = 16;
+void DumpSliceBuffer(SliceBuffer* buffer, y_absl::string_view context_string) {
+ for (size_t i = 0; i < buffer->Count(); i++) {
+ auto str = buffer->MutableSliceAt(i).as_string_view();
+ gpr_log(GPR_INFO, "%s: %.*s", context_string.data(), str.length(),
+ str.data());
+ }
+}
+
} // namespace
WindowsEndpoint::WindowsEndpoint(
const EventEngine::ResolvedAddress& peer_address,
std::unique_ptr<WinSocket> socket, MemoryAllocator&& allocator,
- const EndpointConfig& /* config */, Executor* executor)
+ const EndpointConfig& /* config */, Executor* executor,
+ std::shared_ptr<EventEngine> engine)
: peer_address_(peer_address),
allocator_(std::move(allocator)),
executor_(executor),
- io_state_(std::make_shared<AsyncIOState>(this, std::move(socket))) {
+ io_state_(std::make_shared<AsyncIOState>(this, std::move(socket),
+ std::move(engine))) {
char addr[EventEngine::ResolvedAddress::MAX_SIZE_BYTES];
int addr_len = sizeof(addr);
if (getsockname(io_state_->socket->raw_socket(),
@@ -62,92 +72,95 @@ WindowsEndpoint::WindowsEndpoint(
}
WindowsEndpoint::~WindowsEndpoint() {
- GRPC_EVENT_ENGINE_ENDPOINT_TRACE("WindowsEndpoint::%p destoyed", this);
+ io_state_->socket->Shutdown(DEBUG_LOCATION, "~WindowsEndpoint");
+ GRPC_EVENT_ENGINE_ENDPOINT_TRACE("~WindowsEndpoint::%p", this);
}
-void WindowsEndpoint::Read(y_absl::AnyInvocable<void(y_absl::Status)> on_read,
- SliceBuffer* buffer, const ReadArgs* args) {
+y_absl::Status WindowsEndpoint::DoTcpRead(SliceBuffer* buffer) {
GRPC_EVENT_ENGINE_ENDPOINT_TRACE("WindowsEndpoint::%p reading", this);
if (io_state_->socket->IsShutdown()) {
- executor_->Run([on_read = std::move(on_read)]() mutable {
- on_read(y_absl::UnavailableError("Socket is shutting down."));
- });
- return;
+ return y_absl::UnavailableError("Socket is shutting down.");
}
// Prepare the WSABUF struct
- WSABUF wsa_buffers[kMaxWSABUFCount];
- // TODO(hork): introduce a last_read_buffer to save unused sliced.
- buffer->Clear();
- // TODO(hork): sometimes args->read_hint_bytes is 1, which is not useful.
- // Choose an appropriate size.
- int min_read_size = kDefaultTargetReadSize;
- if (buffer->Length() < min_read_size && buffer->Count() < kMaxWSABUFCount) {
- buffer->AppendIndexed(Slice(allocator_.MakeSlice(min_read_size)));
- }
GPR_ASSERT(buffer->Count() <= kMaxWSABUFCount);
- for (int i = 0; i < buffer->Count(); i++) {
+ WSABUF wsa_buffers[kMaxWSABUFCount];
+ for (size_t i = 0; i < buffer->Count(); i++) {
auto& slice = buffer->MutableSliceAt(i);
wsa_buffers[i].buf = (char*)slice.begin();
wsa_buffers[i].len = slice.size();
}
DWORD bytes_read = 0;
DWORD flags = 0;
- // First let's try a synchronous, non-blocking read.
+ // First try a synchronous, non-blocking read.
int status =
WSARecv(io_state_->socket->raw_socket(), wsa_buffers,
(DWORD)buffer->Count(), &bytes_read, &flags, nullptr, nullptr);
int wsa_error = status == 0 ? 0 : WSAGetLastError();
- // Did we get data immediately ? Yay.
if (wsa_error != WSAEWOULDBLOCK) {
+ // Data or some error was returned immediately.
io_state_->socket->read_info()->SetResult(
{/*wsa_error=*/wsa_error, /*bytes_read=*/bytes_read});
- y_absl::Status result;
- if (bytes_read == 0) {
- result = y_absl::UnavailableError("End of TCP stream");
- grpc_core::StatusSetInt(&result, grpc_core::StatusIntProperty::kRpcStatus,
- GRPC_STATUS_UNAVAILABLE);
- buffer->Clear();
- } else {
- result = y_absl::OkStatus();
- // prune slicebuffer
- if (bytes_read != buffer->Length()) {
- buffer->RemoveLastNBytes(buffer->Length() - bytes_read);
- }
- }
- executor_->Run(
- [result, on_read = std::move(on_read)]() mutable { on_read(result); });
- return;
+ executor_->Run(&io_state_->handle_read_event);
+ return y_absl::OkStatus();
+ }
+ // If the endpoint has already received some data, and the next call would
+ // block, return the data in case that is all the data the reader expects.
+ if (io_state_->handle_read_event.MaybeFinishIfDataHasAlreadyBeenRead()) {
+ return y_absl::OkStatus();
}
// Otherwise, let's retry, by queuing a read.
- memset(io_state_->socket->read_info()->overlapped(), 0, sizeof(OVERLAPPED));
status = WSARecv(io_state_->socket->raw_socket(), wsa_buffers,
(DWORD)buffer->Count(), &bytes_read, &flags,
io_state_->socket->read_info()->overlapped(), nullptr);
wsa_error = status == 0 ? 0 : WSAGetLastError();
if (wsa_error != 0 && wsa_error != WSA_IO_PENDING) {
// Async read returned immediately with an error
- executor_->Run([this, on_read = std::move(on_read), wsa_error]() mutable {
- on_read(GRPC_WSA_ERROR(
- wsa_error,
- y_absl::StrFormat("WindowsEndpont::%p Read failed", this).c_str()));
+ return GRPC_WSA_ERROR(
+ wsa_error,
+ y_absl::StrFormat("WindowsEndpont::%p Read failed", this).c_str());
+ }
+ io_state_->socket->NotifyOnRead(&io_state_->handle_read_event);
+ return y_absl::OkStatus();
+}
+
+bool WindowsEndpoint::Read(y_absl::AnyInvocable<void(y_absl::Status)> on_read,
+ SliceBuffer* buffer, const ReadArgs* /* args */) {
+ if (io_state_->socket->IsShutdown()) {
+ executor_->Run([on_read = std::move(on_read)]() mutable {
+ on_read(y_absl::UnavailableError("Socket is shutting down."));
});
- return;
+ return false;
+ }
+ buffer->Clear();
+ io_state_->handle_read_event.DonateSpareSlices(buffer);
+ // TODO(hork): sometimes args->read_hint_bytes is 1, which is not useful.
+ // Choose an appropriate size.
+ size_t min_read_size = kDefaultTargetReadSize;
+ if (buffer->Length() < min_read_size && buffer->Count() < kMaxWSABUFCount) {
+ buffer->AppendIndexed(Slice(allocator_.MakeSlice(min_read_size)));
}
io_state_->handle_read_event.Prime(io_state_, buffer, std::move(on_read));
- io_state_->socket->NotifyOnRead(&io_state_->handle_read_event);
+ auto status = DoTcpRead(buffer);
+ if (!status.ok()) {
+ // The read could not be completed.
+ io_state_->endpoint->executor_->Run([this, status]() {
+ io_state_->handle_read_event.ExecuteCallbackAndReset(status);
+ });
+ }
+ return false;
}
-void WindowsEndpoint::Write(y_absl::AnyInvocable<void(y_absl::Status)> on_writable,
+bool WindowsEndpoint::Write(y_absl::AnyInvocable<void(y_absl::Status)> on_writable,
SliceBuffer* data, const WriteArgs* /* args */) {
GRPC_EVENT_ENGINE_ENDPOINT_TRACE("WindowsEndpoint::%p writing", this);
if (io_state_->socket->IsShutdown()) {
executor_->Run([on_writable = std::move(on_writable)]() mutable {
on_writable(y_absl::UnavailableError("Socket is shutting down."));
});
- return;
+ return false;
}
if (grpc_event_engine_endpoint_data_trace.enabled()) {
- for (int i = 0; i < data->Count(); i++) {
+ for (size_t i = 0; i < data->Count(); i++) {
auto str = data->RefSlice(i).as_string_view();
gpr_log(GPR_INFO, "WindowsEndpoint::%p WRITE (peer=%s): %.*s", this,
peer_address_string_.c_str(), str.length(), str.data());
@@ -155,7 +168,7 @@ void WindowsEndpoint::Write(y_absl::AnyInvocable<void(y_absl::Status)> on_writab
}
GPR_ASSERT(data->Count() <= UINT_MAX);
y_absl::InlinedVector<WSABUF, kMaxWSABUFCount> buffers(data->Count());
- for (int i = 0; i < data->Count(); i++) {
+ for (size_t i = 0; i < data->Count(); i++) {
auto& slice = data->MutableSliceAt(i);
GPR_ASSERT(slice.size() <= ULONG_MAX);
buffers[i].len = slice.size();
@@ -171,11 +184,11 @@ void WindowsEndpoint::Write(y_absl::AnyInvocable<void(y_absl::Status)> on_writab
// Write completed, exiting early
executor_->Run(
[cb = std::move(on_writable)]() mutable { cb(y_absl::OkStatus()); });
- return;
+ return false;
}
// The data was not completely delivered, we should send the rest of it by
// doing an async write operation.
- for (int i = 0; i < data->Count(); i++) {
+ for (size_t i = 0; i < data->Count(); i++) {
if (buffers[i].len > bytes_sent) {
buffers[i].buf += bytes_sent;
buffers[i].len -= bytes_sent;
@@ -193,29 +206,28 @@ void WindowsEndpoint::Write(y_absl::AnyInvocable<void(y_absl::Status)> on_writab
executor_->Run([cb = std::move(on_writable), wsa_error]() mutable {
cb(GRPC_WSA_ERROR(wsa_error, "WSASend"));
});
- return;
+ return false;
}
}
auto write_info = io_state_->socket->write_info();
- memset(write_info->overlapped(), 0, sizeof(OVERLAPPED));
status =
WSASend(io_state_->socket->raw_socket(), &buffers[async_buffers_offset],
(DWORD)(data->Count() - async_buffers_offset), nullptr, 0,
write_info->overlapped(), nullptr);
-
if (status != 0) {
int wsa_error = WSAGetLastError();
if (wsa_error != WSA_IO_PENDING) {
executor_->Run([cb = std::move(on_writable), wsa_error]() mutable {
cb(GRPC_WSA_ERROR(wsa_error, "WSASend"));
});
- return;
+ return false;
}
}
// As all is now setup, we can now ask for the IOCP notification. It may
// trigger the callback immediately however, but no matter.
io_state_->handle_write_event.Prime(io_state_, data, std::move(on_writable));
io_state_->socket->NotifyOnWrite(&io_state_->handle_write_event);
+ return false;
}
const EventEngine::ResolvedAddress& WindowsEndpoint::GetPeerAddress() const {
return peer_address_;
@@ -234,11 +246,13 @@ void AbortOnEvent(y_absl::Status) {
} // namespace
void WindowsEndpoint::HandleReadClosure::Reset() {
+ io_state_.reset();
cb_ = &AbortOnEvent;
buffer_ = nullptr;
}
void WindowsEndpoint::HandleWriteClosure::Reset() {
+ io_state_.reset();
cb_ = &AbortOnEvent;
buffer_ = nullptr;
}
@@ -265,61 +279,94 @@ void WindowsEndpoint::HandleReadClosure::Run() {
GRPC_EVENT_ENGINE_ENDPOINT_TRACE("WindowsEndpoint::%p Handling Read Event",
io_state->endpoint);
y_absl::Status status;
- auto cb_cleanup = y_absl::MakeCleanup([this, &status]() {
- auto cb = std::move(cb_);
- Reset();
- cb(status);
- });
const auto result = io_state->socket->read_info()->result();
if (result.wsa_error != 0) {
status = GRPC_WSA_ERROR(result.wsa_error, "Async Read Error");
buffer_->Clear();
- return;
+ return ExecuteCallbackAndReset(status);
}
- if (result.bytes_transferred > 0) {
- GPR_ASSERT(result.bytes_transferred <= buffer_->Length());
- if (result.bytes_transferred != buffer_->Length()) {
- buffer_->RemoveLastNBytes(buffer_->Length() - result.bytes_transferred);
- }
- GPR_ASSERT(result.bytes_transferred == buffer_->Length());
+ if (result.bytes_transferred == 0) {
+ // Either the endpoint is shut down or we've seen the end of the stream
if (grpc_event_engine_endpoint_data_trace.enabled()) {
- for (int i = 0; i < buffer_->Count(); i++) {
- auto str = buffer_->RefSlice(i).as_string_view();
- gpr_log(GPR_INFO, "WindowsEndpoint::%p READ (peer=%s): %.*s",
- io_state->endpoint,
- io_state->endpoint->peer_address_string_.c_str(), str.length(),
- str.data());
- }
+ DumpSliceBuffer(
+ buffer_, y_absl::StrFormat("WindowsEndpoint::%p READ (peer=%s)",
+ io_state->endpoint,
+ io_state->endpoint->peer_address_string_));
}
- return;
+ status = y_absl::UnavailableError("End of TCP stream");
+ grpc_core::StatusSetInt(&status, grpc_core::StatusIntProperty::kRpcStatus,
+ GRPC_STATUS_UNAVAILABLE);
+ buffer_->Swap(last_read_buffer_);
+ return ExecuteCallbackAndReset(status);
+ }
+ GPR_DEBUG_ASSERT(result.bytes_transferred > 0);
+ GPR_DEBUG_ASSERT(result.bytes_transferred <= buffer_->Length());
+ buffer_->MoveFirstNBytesIntoSliceBuffer(result.bytes_transferred,
+ last_read_buffer_);
+ if (buffer_->Length() == 0) {
+ buffer_->Swap(last_read_buffer_);
+ return ExecuteCallbackAndReset(status);
+ }
+ // Doing another read. Let's keep the AsyncIOState alive a bit longer.
+ io_state_ = std::move(io_state);
+ status = io_state_->endpoint->DoTcpRead(buffer_);
+ if (!status.ok()) {
+ io_state_.reset();
+ ExecuteCallbackAndReset(status);
}
- // Either the endpoint is shut down or we've seen the end of the stream
- buffer_->Clear();
- status = y_absl::UnavailableError("End of TCP stream");
+}
+
+bool WindowsEndpoint::HandleReadClosure::MaybeFinishIfDataHasAlreadyBeenRead() {
+ if (last_read_buffer_.Length() > 0) {
+ buffer_->Swap(last_read_buffer_);
+ io_state_->endpoint->executor_->Run(
+ [this]() { ExecuteCallbackAndReset(y_absl::OkStatus()); });
+ return true;
+ }
+ return false;
+}
+
+void WindowsEndpoint::HandleReadClosure::ExecuteCallbackAndReset(
+ y_absl::Status status) {
+ auto cb = std::move(cb_);
+ Reset();
+ cb(status);
+}
+
+void WindowsEndpoint::HandleReadClosure::DonateSpareSlices(
+ SliceBuffer* buffer) {
+ // Donee buffer must be empty.
+ GPR_ASSERT(buffer->Length() == 0);
+ // HandleReadClosure must be in the reset state.
+ GPR_ASSERT(buffer_ == nullptr);
+ buffer->Swap(last_read_buffer_);
}
void WindowsEndpoint::HandleWriteClosure::Run() {
// Deletes the shared_ptr when this closure returns
auto io_state = std::move(io_state_);
GRPC_EVENT_ENGINE_ENDPOINT_TRACE("WindowsEndpoint::%p Handling Write Event",
- io_state_->endpoint);
+ io_state->endpoint);
auto cb = std::move(cb_);
const auto result = io_state->socket->write_info()->result();
- Reset();
y_absl::Status status;
if (result.wsa_error != 0) {
status = GRPC_WSA_ERROR(result.wsa_error, "WSASend");
} else {
GPR_ASSERT(result.bytes_transferred == buffer_->Length());
}
+ Reset();
cb(status);
}
// ---- AsyncIOState ----
WindowsEndpoint::AsyncIOState::AsyncIOState(WindowsEndpoint* endpoint,
- std::unique_ptr<WinSocket> socket)
- : endpoint(endpoint), socket(std::move(socket)) {}
+ std::unique_ptr<WinSocket> socket,
+ std::shared_ptr<EventEngine> engine)
+ : endpoint(endpoint),
+ socket(std::move(socket)),
+ engine(std::move(engine)) {}
WindowsEndpoint::AsyncIOState::~AsyncIOState() {
socket->Shutdown(DEBUG_LOCATION, "~AsyncIOState");
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.h b/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.h
index d9634e56dc..32a03d1420 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.h
+++ b/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_endpoint.h
@@ -29,17 +29,17 @@ class WindowsEndpoint : public EventEngine::Endpoint {
WindowsEndpoint(const EventEngine::ResolvedAddress& peer_address,
std::unique_ptr<WinSocket> socket,
MemoryAllocator&& allocator, const EndpointConfig& config,
- Executor* Executor);
+ Executor* Executor, std::shared_ptr<EventEngine> engine);
~WindowsEndpoint() override;
- void Read(y_absl::AnyInvocable<void(y_absl::Status)> on_read, SliceBuffer* buffer,
+ bool Read(y_absl::AnyInvocable<void(y_absl::Status)> on_read, SliceBuffer* buffer,
const ReadArgs* args) override;
- void Write(y_absl::AnyInvocable<void(y_absl::Status)> on_writable,
+ bool Write(y_absl::AnyInvocable<void(y_absl::Status)> on_writable,
SliceBuffer* data, const WriteArgs* args) override;
const EventEngine::ResolvedAddress& GetPeerAddress() const override;
const EventEngine::ResolvedAddress& GetLocalAddress() const override;
private:
- class AsyncIOState;
+ struct AsyncIOState;
// Permanent closure type for Read callbacks
class HandleReadClosure : public EventEngine::Closure {
@@ -49,11 +49,21 @@ class WindowsEndpoint : public EventEngine::Endpoint {
y_absl::AnyInvocable<void(y_absl::Status)> cb);
// Resets the per-request data
void Reset();
+ // Run the callback with whatever data is available, and reset state.
+ //
+ // Returns true if the callback has been called with some data. Returns
+ // false if no data has been read.
+ bool MaybeFinishIfDataHasAlreadyBeenRead();
+ // Execute the callback and reset.
+ void ExecuteCallbackAndReset(y_absl::Status status);
+ // Swap any leftover slices into the provided buffer
+ void DonateSpareSlices(SliceBuffer* buffer);
private:
std::shared_ptr<AsyncIOState> io_state_;
y_absl::AnyInvocable<void(y_absl::Status)> cb_;
SliceBuffer* buffer_ = nullptr;
+ SliceBuffer last_read_buffer_;
};
// Permanent closure type for Write callbacks
@@ -78,14 +88,20 @@ class WindowsEndpoint : public EventEngine::Endpoint {
// Endpoint, and be destroyed asynchronously when all pending overlapped
// events are complete.
struct AsyncIOState {
- AsyncIOState(WindowsEndpoint* endpoint, std::unique_ptr<WinSocket> socket);
+ AsyncIOState(WindowsEndpoint* endpoint, std::unique_ptr<WinSocket> socket,
+ std::shared_ptr<EventEngine> engine);
~AsyncIOState();
WindowsEndpoint* const endpoint;
std::unique_ptr<WinSocket> socket;
HandleReadClosure handle_read_event;
HandleWriteClosure handle_write_event;
+ std::shared_ptr<EventEngine> engine;
};
+ // Perform the low-level calls and execute the HandleReadClosure
+ // asynchronously.
+ y_absl::Status DoTcpRead(SliceBuffer* buffer);
+
EventEngine::ResolvedAddress peer_address_;
TString peer_address_string_;
EventEngine::ResolvedAddress local_address_;
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.cc b/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.cc
index 624d31425d..cac6538b99 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.cc
+++ b/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.cc
@@ -37,6 +37,7 @@
#include "src/core/lib/event_engine/windows/iocp.h"
#include "src/core/lib/event_engine/windows/windows_endpoint.h"
#include "src/core/lib/event_engine/windows/windows_engine.h"
+#include "src/core/lib/event_engine/windows/windows_listener.h"
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/gprpp/time.h"
@@ -106,16 +107,33 @@ WindowsEventEngine::WindowsEventEngine()
}
WindowsEventEngine::~WindowsEventEngine() {
+ GRPC_EVENT_ENGINE_TRACE("~WindowsEventEngine::%p", this);
{
- grpc_core::MutexLock lock(&task_mu_);
- if (GRPC_TRACE_FLAG_ENABLED(grpc_event_engine_trace)) {
- for (auto handle : known_handles_) {
- gpr_log(GPR_ERROR,
- "WindowsEventEngine:%p uncleared TaskHandle at shutdown:%s",
- this, HandleToString<EventEngine::TaskHandle>(handle).c_str());
+ task_mu_.Lock();
+ if (!known_handles_.empty()) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_event_engine_trace)) {
+ for (auto handle : known_handles_) {
+ gpr_log(GPR_ERROR,
+ "WindowsEventEngine:%p uncleared TaskHandle at shutdown:%s",
+ this,
+ HandleToString<EventEngine::TaskHandle>(handle).c_str());
+ }
+ }
+ // Allow a small grace period for timers to be run before shutting down.
+ auto deadline =
+ timer_manager_.Now() + grpc_core::Duration::FromSecondsAsDouble(10);
+ while (!known_handles_.empty() && timer_manager_.Now() < deadline) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_event_engine_trace)) {
+ GRPC_LOG_EVERY_N_SEC(1, GPR_DEBUG, "Waiting for timers. %d remaining",
+ known_handles_.size());
+ }
+ task_mu_.Unlock();
+ y_absl::SleepFor(y_absl::Milliseconds(200));
+ task_mu_.Lock();
}
}
GPR_ASSERT(GPR_LIKELY(known_handles_.empty()));
+ task_mu_.Unlock();
}
iocp_.Kick();
iocp_worker_.WaitForShutdown();
@@ -184,9 +202,11 @@ bool WindowsEventEngine::IsWorkerThread() { grpc_core::Crash("unimplemented"); }
void WindowsEventEngine::OnConnectCompleted(
std::shared_ptr<ConnectionState> state) {
y_absl::StatusOr<std::unique_ptr<WindowsEndpoint>> endpoint;
+ EventEngine::OnConnectCallback cb;
{
// Connection attempt complete!
grpc_core::MutexLock lock(&state->mu);
+ cb = std::move(state->on_connected_user_callback);
state->on_connected = nullptr;
{
grpc_core::MutexLock handle_lock(&connection_mu_);
@@ -204,10 +224,10 @@ void WindowsEventEngine::OnConnectCompleted(
ChannelArgsEndpointConfig cfg;
endpoint = std::make_unique<WindowsEndpoint>(
state->address, std::move(state->socket), std::move(state->allocator),
- cfg, executor_.get());
+ cfg, executor_.get(), shared_from_this());
}
}
- state->on_connected_user_callback(std::move(endpoint));
+ cb(std::move(endpoint));
}
EventEngine::ConnectionHandle WindowsEventEngine::Connect(
@@ -222,7 +242,7 @@ EventEngine::ConnectionHandle WindowsEventEngine::Connect(
Run([on_connect = std::move(on_connect), status = uri.status()]() mutable {
on_connect(status);
});
- return EventEngine::kInvalidConnectionHandle;
+ return EventEngine::ConnectionHandle::kInvalid;
}
GRPC_EVENT_ENGINE_TRACE("EventEngine::%p connecting to %s", this,
uri->c_str());
@@ -239,14 +259,14 @@ EventEngine::ConnectionHandle WindowsEventEngine::Connect(
status = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket")]() mutable {
on_connect(status);
});
- return EventEngine::kInvalidConnectionHandle;
+ return EventEngine::ConnectionHandle::kInvalid;
}
status = PrepareSocket(sock);
if (!status.ok()) {
Run([on_connect = std::move(on_connect), status]() mutable {
on_connect(status);
});
- return EventEngine::kInvalidConnectionHandle;
+ return EventEngine::ConnectionHandle::kInvalid;
}
// Grab the function pointer for ConnectEx for that specific socket It may
// change depending on the interface.
@@ -263,7 +283,7 @@ EventEngine::ConnectionHandle WindowsEventEngine::Connect(
"WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER)")]() mutable {
on_connect(status);
});
- return EventEngine::kInvalidConnectionHandle;
+ return EventEngine::ConnectionHandle::kInvalid;
}
// bind the local address
auto local_address = ResolvedAddressMakeWild6(0);
@@ -273,7 +293,7 @@ EventEngine::ConnectionHandle WindowsEventEngine::Connect(
status = GRPC_WSA_ERROR(WSAGetLastError(), "bind")]() mutable {
on_connect(status);
});
- return EventEngine::kInvalidConnectionHandle;
+ return EventEngine::ConnectionHandle::kInvalid;
}
// Connect
auto watched_socket = iocp_.Watch(sock);
@@ -291,7 +311,7 @@ EventEngine::ConnectionHandle WindowsEventEngine::Connect(
on_connect(status);
});
watched_socket->Shutdown(DEBUG_LOCATION, "ConnectEx");
- return EventEngine::kInvalidConnectionHandle;
+ return EventEngine::ConnectionHandle::kInvalid;
}
}
GPR_ASSERT(watched_socket != nullptr);
@@ -327,8 +347,7 @@ EventEngine::ConnectionHandle WindowsEventEngine::Connect(
}
bool WindowsEventEngine::CancelConnect(EventEngine::ConnectionHandle handle) {
- if (TaskHandleComparator<ConnectionHandle>::Eq()(
- handle, EventEngine::kInvalidConnectionHandle)) {
+ if (handle == EventEngine::ConnectionHandle::kInvalid) {
GRPC_EVENT_ENGINE_TRACE("%s",
"Attempted to cancel an invalid connection handle");
return false;
@@ -379,9 +398,11 @@ WindowsEventEngine::CreateListener(
y_absl::AnyInvocable<void(y_absl::Status)> on_shutdown,
const EndpointConfig& config,
std::unique_ptr<MemoryAllocatorFactory> memory_allocator_factory) {
- grpc_core::Crash("unimplemented");
+ return std::make_unique<WindowsEventEngineListener>(
+ &iocp_, std::move(on_accept), std::move(on_shutdown),
+ std::move(memory_allocator_factory), shared_from_this(), executor_.get(),
+ config);
}
-
} // namespace experimental
} // namespace grpc_event_engine
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.h b/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.h
index 21f4f4a41a..9f2573e2ac 100644
--- a/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.h
+++ b/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_engine.h
@@ -93,6 +93,7 @@ class WindowsEventEngine : public EventEngine,
// WindowsEventEngine type are effectively friends.
// Not intended for external use.
Executor* executor() { return executor_.get(); }
+ IOCP* poller() { return &iocp_; }
private:
// State of an active connection.
@@ -139,7 +140,7 @@ class WindowsEventEngine : public EventEngine,
bool CancelConnectInternalStateLocked(ConnectionState* connection_state)
Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(connection_state->mu);
- class TimerClosure;
+ struct TimerClosure;
EventEngine::TaskHandle RunAfterInternal(Duration when,
y_absl::AnyInvocable<void()> cb);
grpc_core::Mutex task_mu_;
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_listener.cc b/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_listener.cc
new file mode 100644
index 0000000000..9366a73e9c
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_listener.cc
@@ -0,0 +1,370 @@
+// Copyright 2023 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_WINDOWS
+
+#include "y_absl/status/status.h"
+#include "y_absl/strings/str_format.h"
+
+#include "src/core/lib/event_engine/tcp_socket_utils.h"
+#include "src/core/lib/event_engine/trace.h"
+#include "src/core/lib/event_engine/windows/iocp.h"
+#include "src/core/lib/event_engine/windows/win_socket.h"
+#include "src/core/lib/event_engine/windows/windows_endpoint.h"
+#include "src/core/lib/event_engine/windows/windows_listener.h"
+#include "src/core/lib/gprpp/crash.h"
+#include "src/core/lib/gprpp/sync.h"
+#include "src/core/lib/iomgr/error.h"
+
+namespace grpc_event_engine {
+namespace experimental {
+
+// ---- SinglePortSocketListener::AsyncIOState ----
+
+WindowsEventEngineListener::SinglePortSocketListener::AsyncIOState::
+ AsyncIOState(SinglePortSocketListener* port_listener,
+ std::unique_ptr<WinSocket> listener_socket)
+ : port_listener(port_listener),
+ listener_socket(std::move(listener_socket)) {}
+
+WindowsEventEngineListener::SinglePortSocketListener::AsyncIOState::
+ ~AsyncIOState() {
+ closesocket(accept_socket);
+}
+
+void WindowsEventEngineListener::SinglePortSocketListener::
+ OnAcceptCallbackWrapper::Run() {
+ GPR_ASSERT(io_state_ != nullptr);
+ grpc_core::ReleasableMutexLock lock(&io_state_->mu);
+ if (io_state_->listener_socket->IsShutdown()) {
+ GRPC_EVENT_ENGINE_TRACE(
+ "SinglePortSocketListener::%p listener socket is shut down. Shutting "
+ "down listener.",
+ io_state_->port_listener);
+ lock.Release();
+ io_state_.reset();
+ return;
+ }
+ io_state_->port_listener->OnAcceptCallbackLocked();
+}
+
+void WindowsEventEngineListener::SinglePortSocketListener::
+ OnAcceptCallbackWrapper::Prime(std::shared_ptr<AsyncIOState> io_state) {
+ io_state_ = std::move(io_state);
+}
+
+// ---- SinglePortSocketListener ----
+
+WindowsEventEngineListener::SinglePortSocketListener::
+ ~SinglePortSocketListener() {
+ grpc_core::MutexLock lock(&io_state_->mu);
+ io_state_->listener_socket->Shutdown(DEBUG_LOCATION,
+ "~SinglePortSocketListener");
+ GRPC_EVENT_ENGINE_TRACE("~SinglePortSocketListener::%p", this);
+}
+
+y_absl::StatusOr<
+ std::unique_ptr<WindowsEventEngineListener::SinglePortSocketListener>>
+WindowsEventEngineListener::SinglePortSocketListener::Create(
+ WindowsEventEngineListener* listener, SOCKET sock,
+ EventEngine::ResolvedAddress addr) {
+ // We need to grab the AcceptEx pointer for that port, as it may be
+ // interface-dependent. We'll cache it to avoid doing that again.
+ GUID guid = WSAID_ACCEPTEX;
+ DWORD ioctl_num_bytes;
+ LPFN_ACCEPTEX AcceptEx;
+ int status =
+ WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
+ &AcceptEx, sizeof(AcceptEx), &ioctl_num_bytes, NULL, NULL);
+ if (status != 0) {
+ auto error = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket");
+ closesocket(sock);
+ return error;
+ }
+ auto result = SinglePortSocketListener::PrepareListenerSocket(sock, addr);
+ GRPC_RETURN_IF_ERROR(result.status());
+ GPR_ASSERT(result->port >= 0);
+ // Using `new` to access non-public constructor
+ return y_absl::WrapUnique(new SinglePortSocketListener(
+ listener, AcceptEx, /*win_socket=*/listener->iocp_->Watch(sock),
+ result->port, result->hostbyname));
+}
+
+y_absl::Status WindowsEventEngineListener::SinglePortSocketListener::Start() {
+ grpc_core::MutexLock lock(&io_state_->mu);
+ return StartLocked();
+}
+
+y_absl::Status
+WindowsEventEngineListener::SinglePortSocketListener::StartLocked() {
+ SOCKET accept_socket = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
+ IOCP::GetDefaultSocketFlags());
+ if (accept_socket == INVALID_SOCKET) {
+ return GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket");
+ }
+ auto fail = [&](y_absl::Status error) -> y_absl::Status {
+ if (accept_socket != INVALID_SOCKET) closesocket(accept_socket);
+ return error;
+ };
+ auto error = PrepareSocket(accept_socket);
+ if (!error.ok()) return fail(error);
+ // Start the "accept" asynchronously.
+ DWORD addrlen = sizeof(sockaddr_in6) + 16;
+ DWORD bytes_received = 0;
+ int success =
+ AcceptEx(io_state_->listener_socket->raw_socket(), accept_socket,
+ addresses_, 0, addrlen, addrlen, &bytes_received,
+ io_state_->listener_socket->read_info()->overlapped());
+ // It is possible to get an accept immediately without delay. However, we
+ // will still get an IOCP notification for it. So let's just ignore it.
+ if (success != 0) {
+ int last_error = WSAGetLastError();
+ if (last_error != ERROR_IO_PENDING) {
+ return fail(GRPC_WSA_ERROR(last_error, "AcceptEx"));
+ }
+ }
+ // We're ready to do the accept. Calling NotifyOnRead may immediately process
+ // an accept that happened in the meantime.
+ io_state_->accept_socket = accept_socket;
+ io_state_->listener_socket->NotifyOnRead(&io_state_->on_accept_cb);
+ GRPC_EVENT_ENGINE_TRACE(
+ "SinglePortSocketListener::%p listening. listener_socket::%p", this,
+ io_state_->listener_socket.get());
+ return y_absl::OkStatus();
+}
+
+void WindowsEventEngineListener::SinglePortSocketListener::
+ OnAcceptCallbackLocked() {
+ auto close_socket_and_restart =
+ [&](bool do_close_socket = true)
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(io_state_->mu) {
+ if (do_close_socket) closesocket(io_state_->accept_socket);
+ io_state_->accept_socket = INVALID_SOCKET;
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("SinglePortSocketListener::Start",
+ StartLocked()));
+ };
+ const auto& overlapped_result =
+ io_state_->listener_socket->read_info()->result();
+ if (overlapped_result.wsa_error != 0) {
+ gpr_log(GPR_ERROR, "%s",
+ GRPC_WSA_ERROR(overlapped_result.wsa_error,
+ "Skipping on_accept due to error")
+ .ToString()
+ .c_str());
+ return close_socket_and_restart();
+ }
+ SOCKET tmp_listener_socket = io_state_->listener_socket->raw_socket();
+ int err =
+ setsockopt(io_state_->accept_socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
+ reinterpret_cast<char*>(&tmp_listener_socket),
+ sizeof(tmp_listener_socket));
+ if (err != 0) {
+ gpr_log(GPR_ERROR, "%s",
+ GRPC_WSA_ERROR(WSAGetLastError(), "setsockopt").ToString().c_str());
+ return close_socket_and_restart();
+ }
+ EventEngine::ResolvedAddress peer_address;
+ int peer_name_len = EventEngine::ResolvedAddress::MAX_SIZE_BYTES;
+ err = getpeername(io_state_->accept_socket,
+ const_cast<sockaddr*>(peer_address.address()),
+ &peer_name_len);
+ if (err != 0) {
+ gpr_log(
+ GPR_ERROR, "%s",
+ GRPC_WSA_ERROR(WSAGetLastError(), "getpeername").ToString().c_str());
+ return close_socket_and_restart();
+ }
+ peer_address =
+ EventEngine::ResolvedAddress(peer_address.address(), peer_name_len);
+ auto addr_uri = ResolvedAddressToURI(peer_address);
+ TString peer_name = "unknown";
+ if (!addr_uri.ok()) {
+ // TODO(hork): test an early exit/restart here with end2end tests
+ gpr_log(GPR_ERROR, "invalid peer name: %s",
+ addr_uri.status().ToString().c_str());
+ } else {
+ peer_name = *addr_uri;
+ }
+ auto endpoint = std::make_unique<WindowsEndpoint>(
+ peer_address, listener_->iocp_->Watch(io_state_->accept_socket),
+ listener_->memory_allocator_factory_->CreateMemoryAllocator(
+ y_absl::StrFormat("listener endpoint %s", peer_name)),
+ listener_->config_, listener_->executor_, listener_->engine_);
+ listener_->accept_cb_(
+ std::move(endpoint),
+ listener_->memory_allocator_factory_->CreateMemoryAllocator(
+ y_absl::StrFormat("listener accept cb for %s", peer_name)));
+ close_socket_and_restart(/*do_close_socket=*/false);
+}
+
+WindowsEventEngineListener::SinglePortSocketListener::SinglePortSocketListener(
+ WindowsEventEngineListener* listener, LPFN_ACCEPTEX AcceptEx,
+ std::unique_ptr<WinSocket> listener_socket, int port,
+ EventEngine::ResolvedAddress hostbyname)
+ : AcceptEx(AcceptEx),
+ listener_(listener),
+ io_state_(
+ std::make_shared<AsyncIOState>(this, std::move(listener_socket))),
+ port_(port),
+ listener_sockname_(hostbyname) {
+ io_state_->on_accept_cb.Prime(io_state_);
+}
+
+y_absl::StatusOr<WindowsEventEngineListener::SinglePortSocketListener::
+ PrepareListenerSocketResult>
+WindowsEventEngineListener::SinglePortSocketListener::PrepareListenerSocket(
+ SOCKET sock, const EventEngine::ResolvedAddress& addr) {
+ auto fail = [&](y_absl::Status error) -> y_absl::Status {
+ GPR_ASSERT(!error.ok());
+ auto addr_uri = ResolvedAddressToURI(addr);
+ error = grpc_error_set_int(
+ grpc_error_set_str(
+ GRPC_ERROR_CREATE_REFERENCING("Failed to prepare server socket",
+ &error, 1),
+ grpc_core::StatusStrProperty::kTargetAddress,
+ addr_uri.ok() ? *addr_uri : addr_uri.status().ToString()),
+ grpc_core::StatusIntProperty::kFd, static_cast<intptr_t>(sock));
+ if (sock != INVALID_SOCKET) closesocket(sock);
+ return error;
+ };
+ auto error = PrepareSocket(sock);
+ if (!error.ok()) return fail(error);
+ if (bind(sock, addr.address(), addr.size()) == SOCKET_ERROR) {
+ return fail(GRPC_WSA_ERROR(WSAGetLastError(), "bind"));
+ }
+ if (listen(sock, SOMAXCONN) == SOCKET_ERROR) {
+ return fail(GRPC_WSA_ERROR(WSAGetLastError(), "listen"));
+ }
+ int sockname_temp_len = sizeof(struct sockaddr_storage);
+ EventEngine::ResolvedAddress sockname_temp;
+ if (getsockname(sock, const_cast<sockaddr*>(sockname_temp.address()),
+ &sockname_temp_len) == SOCKET_ERROR) {
+ return fail(GRPC_WSA_ERROR(WSAGetLastError(), "getsockname"));
+ }
+ sockname_temp =
+ EventEngine::ResolvedAddress(sockname_temp.address(), sockname_temp_len);
+ return PrepareListenerSocketResult{ResolvedAddressGetPort(sockname_temp),
+ sockname_temp};
+}
+
+// ---- WindowsEventEngineListener ----
+
+WindowsEventEngineListener::WindowsEventEngineListener(
+ IOCP* iocp, AcceptCallback accept_cb,
+ y_absl::AnyInvocable<void(y_absl::Status)> on_shutdown,
+ std::unique_ptr<MemoryAllocatorFactory> memory_allocator_factory,
+ std::shared_ptr<EventEngine> engine, Executor* executor,
+ const EndpointConfig& config)
+ : iocp_(iocp),
+ config_(config),
+ engine_(std::move(engine)),
+ executor_(executor),
+ memory_allocator_factory_(std::move(memory_allocator_factory)),
+ accept_cb_(std::move(accept_cb)),
+ on_shutdown_(std::move(on_shutdown)) {}
+
+WindowsEventEngineListener::~WindowsEventEngineListener() {
+ GRPC_EVENT_ENGINE_TRACE(
+ "%s", y_absl::StrFormat("~WindowsEventEngineListener::%p", this).c_str());
+ ShutdownListeners();
+ on_shutdown_(y_absl::OkStatus());
+}
+
+y_absl::StatusOr<int> WindowsEventEngineListener::Bind(
+ const EventEngine::ResolvedAddress& addr) {
+ if (started_.load()) {
+ return y_absl::FailedPreconditionError(
+ y_absl::StrFormat("WindowsEventEngineListener::%p is already started, "
+ "ports can no longer be bound",
+ this));
+ }
+ int out_port = ResolvedAddressGetPort(addr);
+ EventEngine::ResolvedAddress out_addr(addr);
+ EventEngine::ResolvedAddress tmp_addr;
+ // Check if this is a wildcard port, and if so, try to keep the port the same
+ // as some previously created listener.
+ if (out_port == 0) {
+ grpc_core::MutexLock lock(&port_listeners_mu_);
+ for (const auto& port_listener : port_listeners_) {
+ tmp_addr = port_listener->listener_sockname();
+ out_port = ResolvedAddressGetPort(tmp_addr);
+ if (out_port > 0) {
+ ResolvedAddressSetPort(out_addr, out_port);
+ break;
+ }
+ }
+ }
+ if (ResolvedAddressToV4Mapped(out_addr, &tmp_addr)) {
+ out_addr = tmp_addr;
+ }
+ // Treat :: or 0.0.0.0 as a family-agnostic wildcard.
+ if (ResolvedAddressIsWildcard(out_addr)) {
+ out_addr = ResolvedAddressMakeWild6(out_port);
+ }
+ // open the socket
+ SOCKET sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, nullptr, 0,
+ IOCP::GetDefaultSocketFlags());
+ if (sock == INVALID_SOCKET) {
+ auto error = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket");
+ return GRPC_ERROR_CREATE_REFERENCING("Failed to add port to server", &error,
+ 1);
+ }
+ auto port_listener = AddSinglePortSocketListener(sock, out_addr);
+ GRPC_RETURN_IF_ERROR(port_listener.status());
+ return (*port_listener)->port();
+}
+
+y_absl::Status WindowsEventEngineListener::Start() {
+ GPR_ASSERT(!started_.exchange(true));
+ grpc_core::MutexLock lock(&port_listeners_mu_);
+ for (auto& port_listener : port_listeners_) {
+ GRPC_RETURN_IF_ERROR(port_listener->Start());
+ }
+ return y_absl::OkStatus();
+}
+
+void WindowsEventEngineListener::ShutdownListeners() {
+ grpc_core::MutexLock lock(&port_listeners_mu_);
+ if (std::exchange(listeners_shutdown_, true)) return;
+ // Shut down each port listener before destroying this EventEngine::Listener
+ for (auto& port_listener : port_listeners_) {
+ port_listener.reset();
+ }
+}
+
+y_absl::StatusOr<WindowsEventEngineListener::SinglePortSocketListener*>
+WindowsEventEngineListener::AddSinglePortSocketListener(
+ SOCKET sock, EventEngine::ResolvedAddress addr) {
+ auto single_port_listener =
+ SinglePortSocketListener::Create(this, sock, addr);
+ GRPC_RETURN_IF_ERROR(single_port_listener.status());
+ auto* single_port_listener_ptr = single_port_listener->get();
+ grpc_core::MutexLock lock(&port_listeners_mu_);
+ port_listeners_.emplace_back(std::move(*single_port_listener));
+ if (started_.load()) {
+ gpr_log(GPR_ERROR,
+ "WindowsEventEngineListener::%p Bind was called concurrently while "
+ "the Listener was starting. This is invalid usage, all ports must "
+ "be bound before the Listener is started.",
+ this);
+ GRPC_RETURN_IF_ERROR(single_port_listener_ptr->Start());
+ }
+ return single_port_listener_ptr;
+}
+
+} // namespace experimental
+} // namespace grpc_event_engine
+
+#endif // GPR_WINDOWS
diff --git a/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_listener.h b/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_listener.h
new file mode 100644
index 0000000000..5103f87811
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/event_engine/windows/windows_listener.h
@@ -0,0 +1,155 @@
+// Copyright 2023 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef GRPC_SRC_CORE_LIB_EVENT_ENGINE_WINDOWS_WINDOWS_LISTENER_H
+#define GRPC_SRC_CORE_LIB_EVENT_ENGINE_WINDOWS_WINDOWS_LISTENER_H
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_WINDOWS
+
+#include <list>
+
+#include "y_absl/base/thread_annotations.h"
+#include "y_absl/status/statusor.h"
+
+#include <grpc/event_engine/event_engine.h>
+#include <grpc/event_engine/memory_allocator.h>
+
+#include "src/core/lib/event_engine/common_closures.h"
+#include "src/core/lib/event_engine/windows/iocp.h"
+#include "src/core/lib/gprpp/sync.h"
+
+namespace grpc_event_engine {
+namespace experimental {
+
+class WindowsEventEngineListener : public EventEngine::Listener {
+ public:
+ WindowsEventEngineListener(
+ IOCP* iocp, AcceptCallback accept_cb,
+ y_absl::AnyInvocable<void(y_absl::Status)> on_shutdown,
+ std::unique_ptr<MemoryAllocatorFactory> memory_allocator_factory,
+ std::shared_ptr<EventEngine> engine, Executor* executor_,
+ const EndpointConfig& config);
+ ~WindowsEventEngineListener() override;
+ y_absl::StatusOr<int> Bind(const EventEngine::ResolvedAddress& addr) override;
+ y_absl::Status Start() override;
+ // TODO(hork): this may only be needed for the iomgr shim, to accommodate
+ // calls to grpc_tcp_server_shutdown_listeners
+ void ShutdownListeners();
+
+ private:
+ /// Responsible for listening on a single port.
+ class SinglePortSocketListener {
+ public:
+ ~SinglePortSocketListener();
+ // This factory will create a bound, listening WinSocket, registered with
+ // the listener's IOCP poller.
+ static y_absl::StatusOr<std::unique_ptr<SinglePortSocketListener>> Create(
+ WindowsEventEngineListener* listener, SOCKET sock,
+ EventEngine::ResolvedAddress addr);
+
+ // Two-stage initialization, allows creation of all bound sockets before the
+ // listener is started.
+ y_absl::Status Start();
+ y_absl::Status StartLocked() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(io_state_->mu);
+
+ // Accessor methods
+ EventEngine::ResolvedAddress listener_sockname() {
+ return listener_sockname_;
+ };
+ int port() { return port_; }
+
+ private:
+ struct AsyncIOState;
+
+ class OnAcceptCallbackWrapper : public EventEngine::Closure {
+ public:
+ void Run() override;
+ void Prime(std::shared_ptr<AsyncIOState> io_state);
+
+ private:
+ std::shared_ptr<AsyncIOState> io_state_;
+ };
+
+ // A class to manage the data that must outlive the Endpoint.
+ //
+ // Once a listener is done and destroyed, there still may be overlapped
+ // operations pending. To clean up safely, this data must outlive the
+ // Listener, and be destroyed asynchronously when all pending overlapped
+ // events are complete.
+ struct AsyncIOState {
+ AsyncIOState(SinglePortSocketListener* port_listener,
+ std::unique_ptr<WinSocket> listener_socket);
+ ~AsyncIOState();
+ SinglePortSocketListener* const port_listener;
+ OnAcceptCallbackWrapper on_accept_cb;
+ // Synchronize accept handling on the same socket.
+ grpc_core::Mutex mu;
+ // This will hold the socket for the next accept.
+ SOCKET accept_socket Y_ABSL_GUARDED_BY(mu) = INVALID_SOCKET;
+ // The listener winsocket.
+ std::unique_ptr<WinSocket> listener_socket Y_ABSL_GUARDED_BY(mu);
+ };
+
+ SinglePortSocketListener(WindowsEventEngineListener* listener,
+ LPFN_ACCEPTEX AcceptEx,
+ std::unique_ptr<WinSocket> listener_socket,
+ int port, EventEngine::ResolvedAddress hostbyname);
+
+ // Bind a recently-created socket for listening
+ struct PrepareListenerSocketResult {
+ int port;
+ EventEngine::ResolvedAddress hostbyname;
+ };
+ static y_absl::StatusOr<PrepareListenerSocketResult> PrepareListenerSocket(
+ SOCKET sock, const EventEngine::ResolvedAddress& addr);
+
+ void OnAcceptCallbackLocked() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(io_state_->mu);
+
+ // The cached AcceptEx for that port.
+ LPFN_ACCEPTEX AcceptEx;
+ // This seemingly magic number comes from AcceptEx's documentation. each
+ // address buffer needs to have at least 16 more bytes at their end.
+ uint8_t addresses_[(sizeof(sockaddr_in6) + 16) * 2] = {};
+ // The parent listener
+ WindowsEventEngineListener* listener_;
+ // shared state for asynchronous cleanup of overlapped operations
+ std::shared_ptr<AsyncIOState> io_state_;
+ // The actual TCP port number.
+ int port_;
+ EventEngine::ResolvedAddress listener_sockname_;
+ };
+ y_absl::StatusOr<SinglePortSocketListener*> AddSinglePortSocketListener(
+ SOCKET sock, EventEngine::ResolvedAddress addr);
+
+ IOCP* const iocp_;
+ const EndpointConfig& config_;
+ std::shared_ptr<EventEngine> engine_;
+ Executor* executor_;
+ const std::unique_ptr<MemoryAllocatorFactory> memory_allocator_factory_;
+ AcceptCallback accept_cb_;
+ y_absl::AnyInvocable<void(y_absl::Status)> on_shutdown_;
+ std::atomic<bool> started_{false};
+ grpc_core::Mutex port_listeners_mu_;
+ std::list<std::unique_ptr<SinglePortSocketListener>> port_listeners_
+ Y_ABSL_GUARDED_BY(port_listeners_mu_);
+ bool listeners_shutdown_ Y_ABSL_GUARDED_BY(port_listeners_mu_) = false;
+};
+
+} // namespace experimental
+} // namespace grpc_event_engine
+
+#endif
+
+#endif // GRPC_SRC_CORE_LIB_EVENT_ENGINE_WINDOWS_WINDOWS_LISTENER_H
diff --git a/contrib/libs/grpc/src/core/lib/experiments/config.cc b/contrib/libs/grpc/src/core/lib/experiments/config.cc
index d889b6c4ae..ca6c6456fa 100644
--- a/contrib/libs/grpc/src/core/lib/experiments/config.cc
+++ b/contrib/libs/grpc/src/core/lib/experiments/config.cc
@@ -30,17 +30,12 @@
#include <grpc/support/log.h>
+#include "src/core/lib/config/config_vars.h"
#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/gprpp/crash.h" // IWYU pragma: keep
-#include "src/core/lib/gprpp/global_config.h"
-#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/no_destruct.h"
#ifndef GRPC_EXPERIMENTS_ARE_FINAL
-GPR_GLOBAL_CONFIG_DEFINE_STRING(
- grpc_experiments, "",
- "List of grpc experiments to enable (or with a '-' prefix to disable).");
-
namespace grpc_core {
namespace {
@@ -67,11 +62,9 @@ GPR_ATTRIBUTE_NOINLINE Experiments LoadExperimentsFromConfigVariable() {
experiments.enabled[i] = g_forced_experiments[i].value;
}
}
- // Get the global config.
- auto experiments_str = GPR_GLOBAL_CONFIG_GET(grpc_experiments);
// For each comma-separated experiment in the global config:
- for (auto experiment :
- y_absl::StrSplit(y_absl::string_view(experiments_str.get()), ',')) {
+ for (auto experiment : y_absl::StrSplit(
+ y_absl::string_view(ConfigVars::Get().Experiments()), ',')) {
// Strip whitespace.
experiment = y_absl::StripAsciiWhitespace(experiment);
// Handle ",," without crashing.
diff --git a/contrib/libs/grpc/src/core/lib/experiments/experiments.cc b/contrib/libs/grpc/src/core/lib/experiments/experiments.cc
index 9533bc5eb9..098521d226 100644
--- a/contrib/libs/grpc/src/core/lib/experiments/experiments.cc
+++ b/contrib/libs/grpc/src/core/lib/experiments/experiments.cc
@@ -54,6 +54,10 @@ const char* const description_transport_supplies_client_latency =
"opencensus";
const char* const description_event_engine_listener =
"Use EventEngine listeners instead of iomgr's grpc_tcp_server";
+const char* const description_schedule_cancellation_over_write =
+ "Allow cancellation op to be scheduled over a write";
+const char* const description_trace_record_callops =
+ "Enables tracing of call batch initiation and completion.";
} // namespace
namespace grpc_core {
@@ -75,6 +79,9 @@ const ExperimentMetadata g_experiment_metadata[] = {
{"transport_supplies_client_latency",
description_transport_supplies_client_latency, false},
{"event_engine_listener", description_event_engine_listener, false},
+ {"schedule_cancellation_over_write",
+ description_schedule_cancellation_over_write, false},
+ {"trace_record_callops", description_trace_record_callops, false},
};
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/experiments/experiments.h b/contrib/libs/grpc/src/core/lib/experiments/experiments.h
index 893cea5b6a..828a5225f8 100644
--- a/contrib/libs/grpc/src/core/lib/experiments/experiments.h
+++ b/contrib/libs/grpc/src/core/lib/experiments/experiments.h
@@ -72,6 +72,8 @@ inline bool IsFreeLargeAllocatorEnabled() { return false; }
inline bool IsPromiseBasedServerCallEnabled() { return false; }
inline bool IsTransportSuppliesClientLatencyEnabled() { return false; }
inline bool IsEventEngineListenerEnabled() { return false; }
+inline bool IsScheduleCancellationOverWriteEnabled() { return false; }
+inline bool IsTraceRecordCallopsEnabled() { return false; }
#else
#define GRPC_EXPERIMENT_IS_INCLUDED_TCP_FRAME_SIZE_TUNING
inline bool IsTcpFrameSizeTuningEnabled() { return IsExperimentEnabled(0); }
@@ -107,8 +109,14 @@ inline bool IsTransportSuppliesClientLatencyEnabled() {
}
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_LISTENER
inline bool IsEventEngineListenerEnabled() { return IsExperimentEnabled(12); }
+#define GRPC_EXPERIMENT_IS_INCLUDED_SCHEDULE_CANCELLATION_OVER_WRITE
+inline bool IsScheduleCancellationOverWriteEnabled() {
+ return IsExperimentEnabled(13);
+}
+#define GRPC_EXPERIMENT_IS_INCLUDED_TRACE_RECORD_CALLOPS
+inline bool IsTraceRecordCallopsEnabled() { return IsExperimentEnabled(14); }
-constexpr const size_t kNumExperiments = 13;
+constexpr const size_t kNumExperiments = 15;
extern const ExperimentMetadata g_experiment_metadata[kNumExperiments];
#endif
diff --git a/contrib/libs/grpc/src/core/lib/gpr/log_android.cc b/contrib/libs/grpc/src/core/lib/gpr/android/log.cc
index 92d1711536..92d1711536 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/log_android.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/android/log.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/cpu_iphone.cc b/contrib/libs/grpc/src/core/lib/gpr/iphone/cpu.cc
index 26c3726fc1..26c3726fc1 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/cpu_iphone.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/iphone/cpu.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/cpu_linux.cc b/contrib/libs/grpc/src/core/lib/gpr/linux/cpu.cc
index 670ca6551c..670ca6551c 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/cpu_linux.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/linux/cpu.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/log_linux.cc b/contrib/libs/grpc/src/core/lib/gpr/linux/log.cc
index 5ea13442cc..5ea13442cc 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/log_linux.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/linux/log.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/log.cc b/contrib/libs/grpc/src/core/lib/gpr/log.cc
index 6cba545aea..e193019472 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/log.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/log.cc
@@ -21,27 +21,21 @@
#include <stdio.h>
#include <string.h>
+#include "y_absl/strings/match.h"
#include "y_absl/strings/str_cat.h"
#include <grpc/support/alloc.h>
#include <grpc/support/atm.h>
#include <grpc/support/log.h>
+#include "src/core/lib/config/config_vars.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/crash.h"
-#include "src/core/lib/gprpp/global_config.h"
#ifndef GPR_DEFAULT_LOG_VERBOSITY_STRING
#define GPR_DEFAULT_LOG_VERBOSITY_STRING "ERROR"
#endif // !GPR_DEFAULT_LOG_VERBOSITY_STRING
-GPR_GLOBAL_CONFIG_DEFINE_STRING(grpc_verbosity,
- GPR_DEFAULT_LOG_VERBOSITY_STRING,
- "Default gRPC logging verbosity")
-GPR_GLOBAL_CONFIG_DEFINE_STRING(grpc_stacktrace_minloglevel, "",
- "Messages logged at the same or higher level "
- "than this will print stacktrace")
-
static constexpr gpr_atm GPR_LOG_SEVERITY_UNSET = GPR_LOG_SEVERITY_ERROR + 10;
static constexpr gpr_atm GPR_LOG_SEVERITY_NONE = GPR_LOG_SEVERITY_ERROR + 11;
@@ -106,42 +100,35 @@ void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print) {
(gpr_atm)min_severity_to_print);
}
-static gpr_atm parse_log_severity(const char* str, gpr_atm error_value) {
- if (gpr_stricmp(str, "DEBUG") == 0) {
- return GPR_LOG_SEVERITY_DEBUG;
- } else if (gpr_stricmp(str, "INFO") == 0) {
- return GPR_LOG_SEVERITY_INFO;
- } else if (gpr_stricmp(str, "ERROR") == 0) {
- return GPR_LOG_SEVERITY_ERROR;
- } else if (gpr_stricmp(str, "NONE") == 0) {
- return GPR_LOG_SEVERITY_NONE;
- } else {
- return error_value;
- }
+static gpr_atm parse_log_severity(y_absl::string_view str, gpr_atm error_value) {
+ if (y_absl::EqualsIgnoreCase(str, "DEBUG")) return GPR_LOG_SEVERITY_DEBUG;
+ if (y_absl::EqualsIgnoreCase(str, "INFO")) return GPR_LOG_SEVERITY_INFO;
+ if (y_absl::EqualsIgnoreCase(str, "ERROR")) return GPR_LOG_SEVERITY_ERROR;
+ if (y_absl::EqualsIgnoreCase(str, "NONE")) return GPR_LOG_SEVERITY_NONE;
+ return error_value;
}
void gpr_log_verbosity_init() {
// init verbosity when it hasn't been set
if ((gpr_atm_no_barrier_load(&g_min_severity_to_print)) ==
GPR_LOG_SEVERITY_UNSET) {
- grpc_core::UniquePtr<char> verbosity =
- GPR_GLOBAL_CONFIG_GET(grpc_verbosity);
+ auto verbosity = grpc_core::ConfigVars::Get().Verbosity();
gpr_atm min_severity_to_print = GPR_LOG_SEVERITY_ERROR;
- if (strlen(verbosity.get()) > 0) {
+ if (!verbosity.empty()) {
min_severity_to_print =
- parse_log_severity(verbosity.get(), min_severity_to_print);
+ parse_log_severity(verbosity, min_severity_to_print);
}
gpr_atm_no_barrier_store(&g_min_severity_to_print, min_severity_to_print);
}
// init stacktrace_minloglevel when it hasn't been set
if ((gpr_atm_no_barrier_load(&g_min_severity_to_print_stacktrace)) ==
GPR_LOG_SEVERITY_UNSET) {
- grpc_core::UniquePtr<char> stacktrace_minloglevel =
- GPR_GLOBAL_CONFIG_GET(grpc_stacktrace_minloglevel);
+ auto stacktrace_minloglevel =
+ grpc_core::ConfigVars::Get().StacktraceMinloglevel();
gpr_atm min_severity_to_print_stacktrace = GPR_LOG_SEVERITY_NONE;
- if (strlen(stacktrace_minloglevel.get()) > 0) {
+ if (!stacktrace_minloglevel.empty()) {
min_severity_to_print_stacktrace = parse_log_severity(
- stacktrace_minloglevel.get(), min_severity_to_print_stacktrace);
+ stacktrace_minloglevel, min_severity_to_print_stacktrace);
}
gpr_atm_no_barrier_store(&g_min_severity_to_print_stacktrace,
min_severity_to_print_stacktrace);
diff --git a/contrib/libs/grpc/src/core/lib/gpr/tmpfile_msys.cc b/contrib/libs/grpc/src/core/lib/gpr/msys/tmpfile.cc
index e622018dea..e622018dea 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/tmpfile_msys.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/msys/tmpfile.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/cpu_posix.cc b/contrib/libs/grpc/src/core/lib/gpr/posix/cpu.cc
index 4b58d869f6..4b58d869f6 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/cpu_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/posix/cpu.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/log_posix.cc b/contrib/libs/grpc/src/core/lib/gpr/posix/log.cc
index 065a75ed55..065a75ed55 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/log_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/posix/log.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/string_posix.cc b/contrib/libs/grpc/src/core/lib/gpr/posix/string.cc
index 51a16d33cb..51a16d33cb 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/string_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/posix/string.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/sync_posix.cc b/contrib/libs/grpc/src/core/lib/gpr/posix/sync.cc
index c3cf035ba4..c3cf035ba4 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/sync_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/posix/sync.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/time_posix.cc b/contrib/libs/grpc/src/core/lib/gpr/posix/time.cc
index bc4b9be221..bc4b9be221 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/time_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/posix/time.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/tmpfile_posix.cc b/contrib/libs/grpc/src/core/lib/gpr/posix/tmpfile.cc
index 4d838af72b..4d838af72b 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/tmpfile_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/posix/tmpfile.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/cpu_windows.cc b/contrib/libs/grpc/src/core/lib/gpr/windows/cpu.cc
index 94af1e419c..94af1e419c 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/cpu_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/windows/cpu.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/log_windows.cc b/contrib/libs/grpc/src/core/lib/gpr/windows/log.cc
index 300c7d84a2..300c7d84a2 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/log_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/windows/log.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/string_windows.cc b/contrib/libs/grpc/src/core/lib/gpr/windows/string.cc
index 603303120b..603303120b 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/string_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/windows/string.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/string_util_windows.cc b/contrib/libs/grpc/src/core/lib/gpr/windows/string_util.cc
index b56fdd1792..b56fdd1792 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/string_util_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/windows/string_util.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/sync_windows.cc b/contrib/libs/grpc/src/core/lib/gpr/windows/sync.cc
index f06c73efb0..f06c73efb0 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/sync_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/windows/sync.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/time_windows.cc b/contrib/libs/grpc/src/core/lib/gpr/windows/time.cc
index 52b23c421d..52b23c421d 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/time_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/windows/time.cc
diff --git a/contrib/libs/grpc/src/core/lib/gpr/tmpfile_windows.cc b/contrib/libs/grpc/src/core/lib/gpr/windows/tmpfile.cc
index 37ac4f64bc..37ac4f64bc 100644
--- a/contrib/libs/grpc/src/core/lib/gpr/tmpfile_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/gpr/windows/tmpfile.cc
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/fork.cc b/contrib/libs/grpc/src/core/lib/gprpp/fork.cc
index 295b0bbc3c..0372f8f148 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/fork.cc
+++ b/contrib/libs/grpc/src/core/lib/gprpp/fork.cc
@@ -26,8 +26,8 @@
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
+#include "src/core/lib/config/config_vars.h"
#include "src/core/lib/event_engine/thread_local.h"
-#include "src/core/lib/gprpp/global_config_env.h"
#include "src/core/lib/gprpp/no_destruct.h"
//
@@ -35,16 +35,6 @@
// AROUND VERY SPECIFIC USE CASES.
//
-#ifdef GRPC_ENABLE_FORK_SUPPORT
-#define GRPC_ENABLE_FORK_SUPPORT_DEFAULT true
-#else
-#define GRPC_ENABLE_FORK_SUPPORT_DEFAULT false
-#endif // GRPC_ENABLE_FORK_SUPPORT
-
-GPR_GLOBAL_CONFIG_DEFINE_BOOL(grpc_enable_fork_support,
- GRPC_ENABLE_FORK_SUPPORT_DEFAULT,
- "Enable fork support");
-
namespace grpc_core {
namespace {
// The exec_ctx_count has 2 modes, blocked and unblocked.
@@ -69,7 +59,6 @@ class ExecCtxState {
// EventEngine is expected to terminate all threads before fork, and so this
// extra work is unnecessary
if (grpc_event_engine::experimental::ThreadLocal::IsEventEngineThread()) {
- gpr_atm_no_barrier_fetch_add(&count_, 1);
return;
}
gpr_atm count = gpr_atm_no_barrier_load(&count_);
@@ -91,7 +80,12 @@ class ExecCtxState {
}
}
- void DecExecCtxCount() { gpr_atm_no_barrier_fetch_add(&count_, -1); }
+ void DecExecCtxCount() {
+ if (grpc_event_engine::experimental::ThreadLocal::IsEventEngineThread()) {
+ return;
+ }
+ gpr_atm_no_barrier_fetch_add(&count_, -1);
+ }
bool BlockExecCtx() {
// Assumes there is an active ExecCtx when this function is called
@@ -174,7 +168,7 @@ class ThreadState {
void Fork::GlobalInit() {
if (!override_enabled_) {
- support_enabled_.store(GPR_GLOBAL_CONFIG_GET(grpc_enable_fork_support),
+ support_enabled_.store(ConfigVars::Get().EnableForkSupport(),
std::memory_order_relaxed);
}
}
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/global_config.h b/contrib/libs/grpc/src/core/lib/gprpp/global_config.h
deleted file mode 100644
index 4f2be88d57..0000000000
--- a/contrib/libs/grpc/src/core/lib/gprpp/global_config.h
+++ /dev/null
@@ -1,93 +0,0 @@
-//
-//
-// Copyright 2019 gRPC authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//
-
-#ifndef GRPC_SRC_CORE_LIB_GPRPP_GLOBAL_CONFIG_H
-#define GRPC_SRC_CORE_LIB_GPRPP_GLOBAL_CONFIG_H
-
-#include <grpc/support/port_platform.h>
-
-// --------------------------------------------------------------------
-// How to use global configuration variables:
-//
-// Defining config variables of a specified type:
-// GPR_GLOBAL_CONFIG_DEFINE_*TYPE*(name, default_value, help);
-//
-// Supported TYPEs: BOOL, INT32, STRING
-//
-// It's recommended to use lowercase letters for 'name' like
-// regular variables. The builtin configuration system uses
-// environment variable and the name is converted to uppercase
-// when looking up the value. For example,
-// GPR_GLOBAL_CONFIG_DEFINE(grpc_latency) looks up the value with the
-// name, "GRPC_LATENCY".
-//
-// The variable initially has the specified 'default_value'
-// which must be an expression convertible to 'Type'.
-// 'default_value' may be evaluated 0 or more times,
-// and at an unspecified time; keep it
-// simple and usually free of side-effects.
-//
-// GPR_GLOBAL_CONFIG_DEFINE_*TYPE* should not be called in a C++ header.
-// It should be called at the top-level (outside any namespaces)
-// in a .cc file.
-//
-// Getting the variables:
-// GPR_GLOBAL_CONFIG_GET(name)
-//
-// If error happens during getting variables, error messages will
-// be logged and default value will be returned.
-//
-// Setting the variables with new value:
-// GPR_GLOBAL_CONFIG_SET(name, new_value)
-//
-// Declaring config variables for other modules to access:
-// GPR_GLOBAL_CONFIG_DECLARE_*TYPE*(name)
-//
-// * Caveat for setting global configs at runtime
-//
-// Setting global configs at runtime multiple times is safe but it doesn't
-// mean that it will have a valid effect on the module depending configs.
-// In unit tests, it may be unpredictable to set different global configs
-// between test cases because grpc init and shutdown can ignore changes.
-// It's considered safe to set global configs before the first call to
-// grpc_init().
-
-// --------------------------------------------------------------------
-// How to customize the global configuration system:
-//
-// How to read and write configuration value can be customized.
-// Builtin system uses environment variables but it can be extended to
-// support command-line flag, file, etc.
-//
-// To customize it, following macros should be redefined.
-//
-// GPR_GLOBAL_CONFIG_DEFINE_BOOL
-// GPR_GLOBAL_CONFIG_DEFINE_INT32
-// GPR_GLOBAL_CONFIG_DEFINE_STRING
-//
-// These macros should define functions for getting and setting variable.
-// For example, GPR_GLOBAL_CONFIG_DEFINE_BOOL(test, ...) would define two
-// functions.
-//
-// bool gpr_global_config_get_test();
-// void gpr_global_config_set_test(bool value);
-
-#include "src/core/lib/gprpp/global_config_custom.h" // IWYU pragma: export
-#include "src/core/lib/gprpp/global_config_env.h" // IWYU pragma: export
-
-#endif // GRPC_SRC_CORE_LIB_GPRPP_GLOBAL_CONFIG_H
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/global_config_env.cc b/contrib/libs/grpc/src/core/lib/gprpp/global_config_env.cc
deleted file mode 100644
index b1903929b9..0000000000
--- a/contrib/libs/grpc/src/core/lib/gprpp/global_config_env.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-//
-//
-// Copyright 2019 gRPC authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/lib/gprpp/global_config_env.h"
-
-#include <ctype.h>
-#include <stdlib.h>
-
-#include <initializer_list>
-#include <memory>
-#include <util/generic/string.h>
-#include <util/string/cast.h>
-#include <type_traits>
-
-#include "y_absl/strings/str_format.h"
-#include "y_absl/types/optional.h"
-
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gprpp/env.h"
-
-namespace grpc_core {
-
-namespace {
-
-void DefaultGlobalConfigEnvErrorFunction(const char* error_message) {
- gpr_log(GPR_ERROR, "%s", error_message);
-}
-
-GlobalConfigEnvErrorFunctionType g_global_config_env_error_func =
- DefaultGlobalConfigEnvErrorFunction;
-
-void LogParsingError(const char* name, const char* value) {
- TString error_message = y_absl::StrFormat(
- "Illegal value '%s' specified for environment variable '%s'", value,
- name);
- (*g_global_config_env_error_func)(error_message.c_str());
-}
-
-} // namespace
-
-void SetGlobalConfigEnvErrorFunction(GlobalConfigEnvErrorFunctionType func) {
- g_global_config_env_error_func = func;
-}
-
-UniquePtr<char> GlobalConfigEnv::GetValue() {
- auto env = GetEnv(GetName());
- return UniquePtr<char>(env.has_value() ? gpr_strdup(env.value().c_str())
- : nullptr);
-}
-
-void GlobalConfigEnv::SetValue(const char* value) { SetEnv(GetName(), value); }
-
-void GlobalConfigEnv::Unset() { UnsetEnv(GetName()); }
-
-char* GlobalConfigEnv::GetName() {
- // This makes sure that name_ is in a canonical form having uppercase
- // letters. This is okay to be called serveral times.
- for (char* c = name_; *c != 0; ++c) {
- *c = toupper(*c);
- }
- return name_;
-}
-static_assert(std::is_trivially_destructible<GlobalConfigEnvBool>::value,
- "GlobalConfigEnvBool needs to be trivially destructible.");
-
-bool GlobalConfigEnvBool::Get() {
- UniquePtr<char> str = GetValue();
- if (str == nullptr) {
- return default_value_;
- }
- // parsing given value string.
- bool result = false;
- if (!gpr_parse_bool_value(str.get(), &result)) {
- LogParsingError(GetName(), str.get());
- result = default_value_;
- }
- return result;
-}
-
-void GlobalConfigEnvBool::Set(bool value) {
- SetValue(value ? "true" : "false");
-}
-
-static_assert(std::is_trivially_destructible<GlobalConfigEnvInt32>::value,
- "GlobalConfigEnvInt32 needs to be trivially destructible.");
-
-int32_t GlobalConfigEnvInt32::Get() {
- UniquePtr<char> str = GetValue();
- if (str == nullptr) {
- return default_value_;
- }
- // parsing given value string.
- char* end = str.get();
- long result = strtol(str.get(), &end, 10);
- if (*end != 0) {
- LogParsingError(GetName(), str.get());
- result = default_value_;
- }
- return static_cast<int32_t>(result);
-}
-
-void GlobalConfigEnvInt32::Set(int32_t value) {
- char buffer[GPR_LTOA_MIN_BUFSIZE];
- gpr_ltoa(value, buffer);
- SetValue(buffer);
-}
-
-static_assert(std::is_trivially_destructible<GlobalConfigEnvString>::value,
- "GlobalConfigEnvString needs to be trivially destructible.");
-
-UniquePtr<char> GlobalConfigEnvString::Get() {
- UniquePtr<char> str = GetValue();
- if (str == nullptr) {
- return UniquePtr<char>(gpr_strdup(default_value_));
- }
- return str;
-}
-
-void GlobalConfigEnvString::Set(const char* value) { SetValue(value); }
-
-} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/global_config_env.h b/contrib/libs/grpc/src/core/lib/gprpp/global_config_env.h
deleted file mode 100644
index faa7a6bd44..0000000000
--- a/contrib/libs/grpc/src/core/lib/gprpp/global_config_env.h
+++ /dev/null
@@ -1,133 +0,0 @@
-//
-//
-// Copyright 2019 gRPC authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//
-
-#ifndef GRPC_SRC_CORE_LIB_GPRPP_GLOBAL_CONFIG_ENV_H
-#define GRPC_SRC_CORE_LIB_GPRPP_GLOBAL_CONFIG_ENV_H
-
-#include <grpc/support/port_platform.h>
-
-#include <stdint.h>
-
-#include "src/core/lib/gprpp/global_config_generic.h" // IWYU pragma: export
-#include "src/core/lib/gprpp/memory.h"
-
-namespace grpc_core {
-
-typedef void (*GlobalConfigEnvErrorFunctionType)(const char* error_message);
-
-//
-// Set global_config_env_error_function which is called when config system
-// encounters errors such as parsing error. What the default function does
-// is logging error message.
-//
-void SetGlobalConfigEnvErrorFunction(GlobalConfigEnvErrorFunctionType func);
-
-// Base class for all classes to access environment variables.
-class GlobalConfigEnv {
- protected:
- // `name` should be writable and alive after constructor is called.
- constexpr explicit GlobalConfigEnv(char* name) : name_(name) {}
-
- public:
- // Returns the value of `name` variable.
- UniquePtr<char> GetValue();
-
- // Sets the value of `name` variable.
- void SetValue(const char* value);
-
- // Unsets `name` variable.
- void Unset();
-
- protected:
- char* GetName();
-
- private:
- char* name_;
-};
-
-class GlobalConfigEnvBool : public GlobalConfigEnv {
- public:
- constexpr GlobalConfigEnvBool(char* name, bool default_value)
- : GlobalConfigEnv(name), default_value_(default_value) {}
-
- bool Get();
- void Set(bool value);
-
- private:
- bool default_value_;
-};
-
-class GlobalConfigEnvInt32 : public GlobalConfigEnv {
- public:
- constexpr GlobalConfigEnvInt32(char* name, int32_t default_value)
- : GlobalConfigEnv(name), default_value_(default_value) {}
-
- int32_t Get();
- void Set(int32_t value);
-
- private:
- int32_t default_value_;
-};
-
-class GlobalConfigEnvString : public GlobalConfigEnv {
- public:
- constexpr GlobalConfigEnvString(char* name, const char* default_value)
- : GlobalConfigEnv(name), default_value_(default_value) {}
-
- UniquePtr<char> Get();
- void Set(const char* value);
-
- private:
- const char* default_value_;
-};
-
-} // namespace grpc_core
-
-// Macros for defining global config instances using environment variables.
-// This defines a GlobalConfig*Type* instance with arguments for
-// mutable variable name and default value.
-// Mutable name (g_env_str_##name) is here for having an array
-// for the canonical name without dynamic allocation.
-// `help` argument is ignored for this implementation.
-
-#define GPR_GLOBAL_CONFIG_DEFINE_BOOL(name, default_value, help) \
- static char g_env_str_##name[] = #name; \
- static ::grpc_core::GlobalConfigEnvBool g_env_##name(g_env_str_##name, \
- default_value); \
- bool gpr_global_config_get_##name() { return g_env_##name.Get(); } \
- void gpr_global_config_set_##name(bool value) { g_env_##name.Set(value); }
-
-#define GPR_GLOBAL_CONFIG_DEFINE_INT32(name, default_value, help) \
- static char g_env_str_##name[] = #name; \
- static ::grpc_core::GlobalConfigEnvInt32 g_env_##name(g_env_str_##name, \
- default_value); \
- int32_t gpr_global_config_get_##name() { return g_env_##name.Get(); } \
- void gpr_global_config_set_##name(int32_t value) { g_env_##name.Set(value); }
-
-#define GPR_GLOBAL_CONFIG_DEFINE_STRING(name, default_value, help) \
- static char g_env_str_##name[] = #name; \
- static ::grpc_core::GlobalConfigEnvString g_env_##name(g_env_str_##name, \
- default_value); \
- ::grpc_core::UniquePtr<char> gpr_global_config_get_##name() { \
- return g_env_##name.Get(); \
- } \
- void gpr_global_config_set_##name(const char* value) { \
- g_env_##name.Set(value); \
- }
-
-#endif // GRPC_SRC_CORE_LIB_GPRPP_GLOBAL_CONFIG_ENV_H
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/global_config_generic.h b/contrib/libs/grpc/src/core/lib/gprpp/global_config_generic.h
deleted file mode 100644
index adebb1c810..0000000000
--- a/contrib/libs/grpc/src/core/lib/gprpp/global_config_generic.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-//
-// Copyright 2019 gRPC authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//
-
-#ifndef GRPC_SRC_CORE_LIB_GPRPP_GLOBAL_CONFIG_GENERIC_H
-#define GRPC_SRC_CORE_LIB_GPRPP_GLOBAL_CONFIG_GENERIC_H
-
-#include <grpc/support/port_platform.h>
-
-#define GPR_GLOBAL_CONFIG_GET(name) gpr_global_config_get_##name()
-
-#define GPR_GLOBAL_CONFIG_SET(name, value) gpr_global_config_set_##name(value)
-
-#define GPR_GLOBAL_CONFIG_DECLARE_BOOL(name) \
- extern bool gpr_global_config_get_##name(); \
- extern void gpr_global_config_set_##name(bool value)
-
-#define GPR_GLOBAL_CONFIG_DECLARE_INT32(name) \
- extern int32_t gpr_global_config_get_##name(); \
- extern void gpr_global_config_set_##name(int32_t value)
-
-#define GPR_GLOBAL_CONFIG_DECLARE_STRING(name) \
- extern grpc_core::UniquePtr<char> gpr_global_config_get_##name(); \
- extern void gpr_global_config_set_##name(const char* value)
-
-#endif // GRPC_SRC_CORE_LIB_GPRPP_GLOBAL_CONFIG_GENERIC_H
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/env_linux.cc b/contrib/libs/grpc/src/core/lib/gprpp/linux/env.cc
index 255a616562..255a616562 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/env_linux.cc
+++ b/contrib/libs/grpc/src/core/lib/gprpp/linux/env.cc
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/orphanable.h b/contrib/libs/grpc/src/core/lib/gprpp/orphanable.h
index b9b291317d..a2f24cb54c 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/orphanable.h
+++ b/contrib/libs/grpc/src/core/lib/gprpp/orphanable.h
@@ -69,7 +69,7 @@ inline OrphanablePtr<T> MakeOrphanable(Args&&... args) {
}
// A type of Orphanable with internal ref-counting.
-template <typename Child, UnrefBehavior UnrefBehaviorArg = kUnrefDelete>
+template <typename Child, typename UnrefBehavior = UnrefDelete>
class InternallyRefCounted : public Orphanable {
public:
// Not copyable nor movable.
@@ -99,12 +99,12 @@ class InternallyRefCounted : public Orphanable {
void Unref() {
if (GPR_UNLIKELY(refs_.Unref())) {
- internal::Delete<Child, UnrefBehaviorArg>(static_cast<Child*>(this));
+ unref_behavior_(static_cast<Child*>(this));
}
}
void Unref(const DebugLocation& location, const char* reason) {
if (GPR_UNLIKELY(refs_.Unref(location, reason))) {
- internal::Delete<Child, UnrefBehaviorArg>(static_cast<Child*>(this));
+ unref_behavior_(static_cast<Child*>(this));
}
}
@@ -115,6 +115,7 @@ class InternallyRefCounted : public Orphanable {
}
RefCount refs_;
+ GPR_NO_UNIQUE_ADDRESS UnrefBehavior unref_behavior_;
};
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/per_cpu.h b/contrib/libs/grpc/src/core/lib/gprpp/per_cpu.h
index 116c9e215a..2476b6f370 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/per_cpu.h
+++ b/contrib/libs/grpc/src/core/lib/gprpp/per_cpu.h
@@ -17,7 +17,9 @@
#include <grpc/support/port_platform.h>
+#include <algorithm>
#include <cstddef>
+#include <limits>
#include <memory>
#include <grpc/support/cpu.h>
@@ -29,7 +31,11 @@ namespace grpc_core {
template <typename T>
class PerCpu {
public:
- T& this_cpu() { return data_[ExecCtx::Get()->starting_cpu()]; }
+ explicit PerCpu(size_t max = std::numeric_limits<size_t>::max())
+ : cpus_(std::min<size_t>(max, gpr_cpu_num_cores())),
+ data_{new T[cpus_]} {}
+
+ T& this_cpu() { return data_[ExecCtx::Get()->starting_cpu() % cpus_]; }
T* begin() { return data_.get(); }
T* end() { return data_.get() + cpus_; }
@@ -37,8 +43,8 @@ class PerCpu {
const T* end() const { return data_.get() + cpus_; }
private:
- const size_t cpus_ = gpr_cpu_num_cores();
- std::unique_ptr<T[]> data_{new T[cpus_]};
+ const size_t cpus_;
+ std::unique_ptr<T[]> data_;
};
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/env_posix.cc b/contrib/libs/grpc/src/core/lib/gprpp/posix/env.cc
index f66151550b..f66151550b 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/env_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/gprpp/posix/env.cc
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/stat_posix.cc b/contrib/libs/grpc/src/core/lib/gprpp/posix/stat.cc
index db08110402..db08110402 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/stat_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/gprpp/posix/stat.cc
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/thd_posix.cc b/contrib/libs/grpc/src/core/lib/gprpp/posix/thd.cc
index 0d93748dbe..3e3d258ead 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/thd_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/gprpp/posix/thd.cc
@@ -21,6 +21,9 @@
#include <grpc/support/port_platform.h>
#include <util/system/thread.h>
+#include <util/generic/string.h>
+#include <util/string/cast.h>
+
#include <grpc/support/time.h>
#ifdef GPR_POSIX_SYNC
@@ -35,7 +38,9 @@
#include <grpc/support/thd_id.h>
#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/gprpp/fork.h"
+#include "src/core/lib/gprpp/strerror.h"
#include "src/core/lib/gprpp/thd.h"
namespace grpc_core {
@@ -107,37 +112,40 @@ class ThreadInternalsPosix : public internal::ThreadInternalsInterface {
GPR_ASSERT(pthread_attr_setstacksize(&attr, stack_size) == 0);
}
- *success = (pthread_create(
- &pthread_id_, &attr,
- [](void* v) -> void* {
- thd_arg arg = *static_cast<thd_arg*>(v);
- free(v);
- if (arg.name != nullptr) {
- TThread::SetCurrentThreadName(arg.name);
- }
-
- gpr_mu_lock(&arg.thread->mu_);
- while (!arg.thread->started_) {
- gpr_cv_wait(&arg.thread->ready_, &arg.thread->mu_,
- gpr_inf_future(GPR_CLOCK_MONOTONIC));
- }
- gpr_mu_unlock(&arg.thread->mu_);
-
- if (!arg.joinable) {
- delete arg.thread;
- }
-
- (*arg.body)(arg.arg);
- if (arg.tracked) {
- Fork::DecThreadCount();
- }
- return nullptr;
- },
- info) == 0);
+ int pthread_create_err = pthread_create(
+ &pthread_id_, &attr,
+ [](void* v) -> void* {
+ thd_arg arg = *static_cast<thd_arg*>(v);
+ free(v);
+ if (arg.name != nullptr) {
+ TThread::SetCurrentThreadName(arg.name);
+ }
+
+ gpr_mu_lock(&arg.thread->mu_);
+ while (!arg.thread->started_) {
+ gpr_cv_wait(&arg.thread->ready_, &arg.thread->mu_,
+ gpr_inf_future(GPR_CLOCK_MONOTONIC));
+ }
+ gpr_mu_unlock(&arg.thread->mu_);
+
+ if (!arg.joinable) {
+ delete arg.thread;
+ }
+
+ (*arg.body)(arg.arg);
+ if (arg.tracked) {
+ Fork::DecThreadCount();
+ }
+ return nullptr;
+ },
+ info);
+ *success = (pthread_create_err == 0);
GPR_ASSERT(pthread_attr_destroy(&attr) == 0);
if (!(*success)) {
+ gpr_log(GPR_ERROR, "pthread_create failed: %s",
+ StrError(pthread_create_err).c_str());
// don't use gpr_free, as this was allocated using malloc (see above)
free(info);
if (options.tracked()) {
@@ -158,7 +166,12 @@ class ThreadInternalsPosix : public internal::ThreadInternalsInterface {
gpr_mu_unlock(&mu_);
}
- void Join() override { pthread_join(pthread_id_, nullptr); }
+ void Join() override {
+ int pthread_join_err = pthread_join(pthread_id_, nullptr);
+ if (pthread_join_err != 0) {
+ Crash("pthread_join failed: " + StrError(pthread_join_err));
+ }
+ }
private:
gpr_mu mu_;
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/ref_counted.h b/contrib/libs/grpc/src/core/lib/gprpp/ref_counted.h
index 066791929b..96fe288ff6 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/ref_counted.h
+++ b/contrib/libs/grpc/src/core/lib/gprpp/ref_counted.h
@@ -213,41 +213,34 @@ class NonPolymorphicRefCount {
};
// Behavior of RefCounted<> upon ref count reaching 0.
-enum UnrefBehavior {
- // Default behavior: Delete the object.
- kUnrefDelete,
- // Do not delete the object upon unref. This is useful in cases where all
- // existing objects must be tracked in a registry but the object's entry in
- // the registry cannot be removed from the object's dtor due to
- // synchronization issues. In this case, the registry can be cleaned up
- // later by identifying entries for which RefIfNonZero() returns null.
- kUnrefNoDelete,
- // Call the object's dtor but do not delete it. This is useful for cases
- // where the object is stored in memory allocated elsewhere (e.g., the call
- // arena).
- kUnrefCallDtor,
-};
-
-namespace internal {
-template <typename T, UnrefBehavior UnrefBehaviorArg>
-class Delete;
-template <typename T>
-class Delete<T, kUnrefDelete> {
- public:
- explicit Delete(T* t) { delete t; }
+// Default behavior: Delete the object.
+struct UnrefDelete {
+ template <typename T>
+ void operator()(T* p) {
+ delete p;
+ }
};
-template <typename T>
-class Delete<T, kUnrefNoDelete> {
- public:
- explicit Delete(T* /*t*/) {}
+
+// Do not delete the object upon unref. This is useful in cases where all
+// existing objects must be tracked in a registry but the object's entry in
+// the registry cannot be removed from the object's dtor due to
+// synchronization issues. In this case, the registry can be cleaned up
+// later by identifying entries for which RefIfNonZero() returns null.
+struct UnrefNoDelete {
+ template <typename T>
+ void operator()(T* /*p*/) {}
};
-template <typename T>
-class Delete<T, kUnrefCallDtor> {
- public:
- explicit Delete(T* t) { t->~T(); }
+
+// Call the object's dtor but do not delete it. This is useful for cases
+// where the object is stored in memory allocated elsewhere (e.g., the call
+// arena).
+struct UnrefCallDtor {
+ template <typename T>
+ void operator()(T* p) {
+ p->~T();
+ }
};
-} // namespace internal
// A base class for reference-counted objects.
// New objects should be created via new and start with a refcount of 1.
@@ -276,7 +269,7 @@ class Delete<T, kUnrefCallDtor> {
// ch->Unref();
//
template <typename Child, typename Impl = PolymorphicRefCount,
- UnrefBehavior UnrefBehaviorArg = kUnrefDelete>
+ typename UnrefBehavior = UnrefDelete>
class RefCounted : public Impl {
public:
using RefCountedChildType = Child;
@@ -301,12 +294,12 @@ class RefCounted : public Impl {
// friend of this class.
void Unref() {
if (GPR_UNLIKELY(refs_.Unref())) {
- internal::Delete<Child, UnrefBehaviorArg>(static_cast<Child*>(this));
+ unref_behavior_(static_cast<Child*>(this));
}
}
void Unref(const DebugLocation& location, const char* reason) {
if (GPR_UNLIKELY(refs_.Unref(location, reason))) {
- internal::Delete<Child, UnrefBehaviorArg>(static_cast<Child*>(this));
+ unref_behavior_(static_cast<Child*>(this));
}
}
@@ -331,6 +324,11 @@ class RefCounted : public Impl {
intptr_t initial_refcount = 1)
: refs_(initial_refcount, trace) {}
+ // Note: Tracing is a no-op on non-debug builds.
+ explicit RefCounted(UnrefBehavior b, const char* trace = nullptr,
+ intptr_t initial_refcount = 1)
+ : refs_(initial_refcount, trace), unref_behavior_(b) {}
+
private:
// Allow RefCountedPtr<> to access IncrementRefCount().
template <typename T>
@@ -342,6 +340,7 @@ class RefCounted : public Impl {
}
RefCount refs_;
+ GPR_NO_UNIQUE_ADDRESS UnrefBehavior unref_behavior_;
};
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/thd.h b/contrib/libs/grpc/src/core/lib/gprpp/thd.h
index 16a9188d79..1398f2adc3 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/thd.h
+++ b/contrib/libs/grpc/src/core/lib/gprpp/thd.h
@@ -25,6 +25,11 @@
#include <stddef.h>
+#include <memory>
+#include <utility>
+
+#include "y_absl/functional/any_invocable.h"
+
#include <grpc/support/log.h>
namespace grpc_core {
@@ -86,6 +91,17 @@ class Thread {
Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg,
bool* success = nullptr, const Options& options = Options());
+ Thread(const char* thd_name, y_absl::AnyInvocable<void()> fn,
+ bool* success = nullptr, const Options& options = Options())
+ : Thread(
+ thd_name,
+ [](void* p) {
+ std::unique_ptr<y_absl::AnyInvocable<void()>> fn_from_p(
+ static_cast<y_absl::AnyInvocable<void()>*>(p));
+ (*fn_from_p)();
+ },
+ new y_absl::AnyInvocable<void()>(std::move(fn)), success, options) {}
+
/// Move constructor for thread. After this is called, the other thread
/// no longer represents a living thread object
Thread(Thread&& other) noexcept
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/time.cc b/contrib/libs/grpc/src/core/lib/gprpp/time.cc
index dd315bb7d6..2896a63a89 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/time.cc
+++ b/contrib/libs/grpc/src/core/lib/gprpp/time.cc
@@ -26,6 +26,7 @@
#include "y_absl/strings/str_format.h"
+#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include "src/core/lib/gprpp/no_destruct.h"
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/time.h b/contrib/libs/grpc/src/core/lib/gprpp/time.h
index 2cf6a1c651..bbc8eeff30 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/time.h
+++ b/contrib/libs/grpc/src/core/lib/gprpp/time.h
@@ -27,20 +27,20 @@
#include "y_absl/types/optional.h"
#include <grpc/event_engine/event_engine.h>
-#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include "src/core/lib/gpr/time_precise.h"
#include "src/core/lib/gpr/useful.h"
-#define GRPC_LOG_EVERY_N_SEC(n, format, ...) \
+#define GRPC_LOG_EVERY_N_SEC(n, severity, format, ...) \
do { \
static std::atomic<uint64_t> prev{0}; \
uint64_t now = grpc_core::Timestamp::FromTimespecRoundDown( \
gpr_now(GPR_CLOCK_MONOTONIC)) \
.milliseconds_after_process_epoch(); \
- if ((now - prev.exchange(now)) > (n)*1000) { \
- gpr_log(GPR_INFO, format, __VA_ARGS__); \
+ uint64_t prev_tsamp = prev.exchange(now); \
+ if (prev_tsamp == 0 || now - prev_tsamp > (n)*1000) { \
+ gpr_log(severity, format, __VA_ARGS__); \
} \
} while (0)
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/env_windows.cc b/contrib/libs/grpc/src/core/lib/gprpp/windows/env.cc
index c1ff97706d..c1ff97706d 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/env_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/gprpp/windows/env.cc
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/stat_windows.cc b/contrib/libs/grpc/src/core/lib/gprpp/windows/stat.cc
index b3b46db77f..b3b46db77f 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/stat_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/gprpp/windows/stat.cc
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/thd_windows.cc b/contrib/libs/grpc/src/core/lib/gprpp/windows/thd.cc
index 8bd310ff35..58efa7e183 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/thd_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/gprpp/windows/thd.cc
@@ -146,8 +146,8 @@ class ThreadInternalsWindows
namespace grpc_core {
-Thread::Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg,
- bool* success, const Options& options)
+Thread::Thread(const char* /* thd_name */, void (*thd_body)(void* arg),
+ void* arg, bool* success, const Options& options)
: options_(options) {
bool outcome = false;
impl_ = new ThreadInternalsWindows(thd_body, arg, &outcome, options);
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/call_combiner.h b/contrib/libs/grpc/src/core/lib/iomgr/call_combiner.h
index 7aa096890f..b1fac8d14d 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/call_combiner.h
+++ b/contrib/libs/grpc/src/core/lib/iomgr/call_combiner.h
@@ -171,8 +171,8 @@ class CallCombinerClosureList {
if (GRPC_TRACE_FLAG_ENABLED(grpc_call_combiner_trace)) {
gpr_log(GPR_INFO,
"CallCombinerClosureList executing closure while already "
- "holding call_combiner %p: closure=%p error=%s reason=%s",
- call_combiner, closures_[0].closure,
+ "holding call_combiner %p: closure=%s error=%s reason=%s",
+ call_combiner, closures_[0].closure->DebugString().c_str(),
StatusToString(closures_[0].error).c_str(), closures_[0].reason);
}
// This will release the call combiner.
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/endpoint_cfstream.cc b/contrib/libs/grpc/src/core/lib/iomgr/endpoint_cfstream.cc
index 52e9e7cbd5..4b471d0868 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/endpoint_cfstream.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/endpoint_cfstream.cc
@@ -113,7 +113,8 @@ static grpc_error_handle CFStreamAnnotateError(grpc_error_handle src_error,
}
static void CallReadCb(CFStreamEndpoint* ep, grpc_error_handle error) {
- if (grpc_tcp_trace.enabled()) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace) &&
+ gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
gpr_log(GPR_DEBUG, "CFStream endpoint:%p call_read_cb %p %p:%p", ep,
ep->read_cb, ep->read_cb->cb, ep->read_cb->cb_arg);
size_t i;
@@ -225,7 +226,8 @@ static void WriteAction(void* arg, grpc_error_handle error) {
EP_UNREF(ep, "write");
}
- if (grpc_tcp_trace.enabled()) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace) &&
+ gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
grpc_slice trace_slice = grpc_slice_sub(slice, 0, write_size);
char* dump = grpc_dump_slice(trace_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "WRITE %p (peer=%s): %s", ep, ep->peer_string.c_str(),
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/ev_posix.cc b/contrib/libs/grpc/src/core/lib/iomgr/ev_posix.cc
index 15115db077..eb10657770 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/ev_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/ev_posix.cc
@@ -27,26 +27,21 @@
#include <string.h>
#include "y_absl/strings/str_format.h"
+#include "y_absl/strings/str_split.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
+#include "src/core/lib/config/config_vars.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/crash.h"
-#include "src/core/lib/gprpp/global_config.h"
#include "src/core/lib/iomgr/ev_epoll1_linux.h"
#include "src/core/lib/iomgr/ev_poll_posix.h"
#include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/iomgr/internal_errqueue.h"
-GPR_GLOBAL_CONFIG_DEFINE_STRING(
- grpc_poll_strategy, "all",
- "Declares which polling engines to try when starting gRPC. "
- "This is a comma-separated list of engines, which are tried in priority "
- "order first -> last.")
-
grpc_core::DebugOnlyTraceFlag grpc_polling_trace(
false, "polling"); // Disabled by default
@@ -106,40 +101,14 @@ static const grpc_event_engine_vtable* g_vtables[] = {
nullptr,
};
-static void add(const char* beg, const char* end, char*** ss, size_t* ns) {
- size_t n = *ns;
- size_t np = n + 1;
- char* s;
- size_t len;
- GPR_ASSERT(end >= beg);
- len = static_cast<size_t>(end - beg);
- s = static_cast<char*>(gpr_malloc(len + 1));
- memcpy(s, beg, len);
- s[len] = 0;
- *ss = static_cast<char**>(gpr_realloc(*ss, sizeof(char**) * np));
- (*ss)[n] = s;
- *ns = np;
-}
-
-static void split(const char* s, char*** ss, size_t* ns) {
- const char* c = strchr(s, ',');
- if (c == nullptr) {
- add(s, s + strlen(s), ss, ns);
- } else {
- add(s, c, ss, ns);
- split(c + 1, ss, ns);
- }
-}
-
-static bool is(const char* want, const char* have) {
- return 0 == strcmp(want, "all") || 0 == strcmp(want, have);
+static bool is(y_absl::string_view want, y_absl::string_view have) {
+ return want == "all" || want == have;
}
-static void try_engine(const char* engine) {
+static void try_engine(y_absl::string_view engine) {
for (size_t i = 0; i < GPR_ARRAY_SIZE(g_vtables); i++) {
if (g_vtables[i] != nullptr && is(engine, g_vtables[i]->name) &&
- g_vtables[i]->check_engine_available(
- 0 == strcmp(engine, g_vtables[i]->name))) {
+ g_vtables[i]->check_engine_available(engine == g_vtables[i]->name)) {
g_event_engine = g_vtables[i];
gpr_log(GPR_DEBUG, "Using polling engine: %s", g_event_engine->name);
return;
@@ -173,25 +142,16 @@ const char* grpc_get_poll_strategy_name() { return g_event_engine->name; }
void grpc_event_engine_init(void) {
gpr_once_init(&g_choose_engine, []() {
- grpc_core::UniquePtr<char> value =
- GPR_GLOBAL_CONFIG_GET(grpc_poll_strategy);
-
- char** strings = nullptr;
- size_t nstrings = 0;
- split(value.get(), &strings, &nstrings);
-
- for (size_t i = 0; g_event_engine == nullptr && i < nstrings; i++) {
- try_engine(strings[i]);
- }
-
- for (size_t i = 0; i < nstrings; i++) {
- gpr_free(strings[i]);
+ auto value = grpc_core::ConfigVars::Get().PollStrategy();
+ for (auto trial : y_absl::StrSplit(value, ',')) {
+ try_engine(trial);
+ if (g_event_engine != nullptr) return;
}
- gpr_free(strings);
if (g_event_engine == nullptr) {
- grpc_core::Crash(y_absl::StrFormat(
- "No event engine could be initialized from %s", value.get()));
+ grpc_core::Crash(
+ y_absl::StrFormat("No event engine could be initialized from %s",
+ TString(value).c_str()));
}
});
g_event_engine->init_engine();
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/ev_posix.h b/contrib/libs/grpc/src/core/lib/iomgr/ev_posix.h
index 4e8db6daca..d7d84879f4 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/ev_posix.h
+++ b/contrib/libs/grpc/src/core/lib/iomgr/ev_posix.h
@@ -24,14 +24,11 @@
#include <poll.h>
#include "src/core/lib/debug/trace.h"
-#include "src/core/lib/gprpp/global_config.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/iomgr/pollset_set.h"
#include "src/core/lib/iomgr/wakeup_fd_posix.h"
-GPR_GLOBAL_CONFIG_DECLARE_STRING(grpc_poll_strategy);
-
extern grpc_core::DebugOnlyTraceFlag grpc_fd_trace; // Disabled by default
extern grpc_core::DebugOnlyTraceFlag grpc_polling_trace; // Disabled by default
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/event_engine_shims/endpoint.cc b/contrib/libs/grpc/src/core/lib/iomgr/event_engine_shims/endpoint.cc
index 1e0d004893..9394dd18c9 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/event_engine_shims/endpoint.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/event_engine_shims/endpoint.cc
@@ -33,6 +33,8 @@
#include "src/core/lib/event_engine/tcp_socket_utils.h"
#include "src/core/lib/event_engine/trace.h"
#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gprpp/construct_destruct.h"
+#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/endpoint.h"
@@ -94,15 +96,101 @@ class EventEngineEndpointWrapper {
grpc_endpoint* GetGrpcEndpoint() { return &eeep_->base; }
// Read using the underlying EventEngine endpoint object.
- void Read(y_absl::AnyInvocable<void(y_absl::Status)> on_read, SliceBuffer* buffer,
+ bool Read(grpc_closure* read_cb, grpc_slice_buffer* pending_read_buffer,
const EventEngine::Endpoint::ReadArgs* args) {
- endpoint_->Read(std::move(on_read), buffer, args);
+ Ref();
+ pending_read_cb_ = read_cb;
+ pending_read_buffer_ = pending_read_buffer;
+ // TODO(vigneshbabu): Use SliceBufferCast<> here.
+ grpc_core::Construct(reinterpret_cast<SliceBuffer*>(&eeep_->read_buffer),
+ SliceBuffer::TakeCSliceBuffer(*pending_read_buffer_));
+ SliceBuffer* read_buffer =
+ reinterpret_cast<SliceBuffer*>(&eeep_->read_buffer);
+ read_buffer->Clear();
+ return endpoint_->Read(
+ [this](y_absl::Status status) { FinishPendingRead(status); }, read_buffer,
+ args);
+ }
+
+ void FinishPendingRead(y_absl::Status status) {
+ auto* read_buffer = reinterpret_cast<SliceBuffer*>(&eeep_->read_buffer);
+ grpc_slice_buffer_move_into(read_buffer->c_slice_buffer(),
+ pending_read_buffer_);
+ read_buffer->~SliceBuffer();
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
+ size_t i;
+ gpr_log(GPR_INFO, "TCP: %p READ (peer=%s) error=%s", eeep_->wrapper,
+ TString(eeep_->wrapper->PeerAddress()).c_str(),
+ status.ToString().c_str());
+ if (gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
+ for (i = 0; i < pending_read_buffer_->count; i++) {
+ char* dump = grpc_dump_slice(pending_read_buffer_->slices[i],
+ GPR_DUMP_HEX | GPR_DUMP_ASCII);
+ gpr_log(GPR_DEBUG, "READ DATA: %s", dump);
+ gpr_free(dump);
+ }
+ }
+ }
+ pending_read_buffer_ = nullptr;
+ grpc_closure* cb = pending_read_cb_;
+ pending_read_cb_ = nullptr;
+ if (grpc_core::ExecCtx::Get() == nullptr) {
+ grpc_core::ApplicationCallbackExecCtx app_ctx;
+ grpc_core::ExecCtx exec_ctx;
+ grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, status);
+ } else {
+ grpc_core::Closure::Run(DEBUG_LOCATION, cb, status);
+ }
+ // For the ref taken in EventEngineEndpointWrapper::Read().
+ Unref();
}
// Write using the underlying EventEngine endpoint object
- void Write(y_absl::AnyInvocable<void(y_absl::Status)> on_writable,
- SliceBuffer* data, const EventEngine::Endpoint::WriteArgs* args) {
- endpoint_->Write(std::move(on_writable), data, args);
+ bool Write(grpc_closure* write_cb, grpc_slice_buffer* slices,
+ const EventEngine::Endpoint::WriteArgs* args) {
+ Ref();
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
+ size_t i;
+ gpr_log(GPR_INFO, "TCP: %p WRITE (peer=%s)", this,
+ TString(PeerAddress()).c_str());
+ if (gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
+ for (i = 0; i < slices->count; i++) {
+ char* dump =
+ grpc_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
+ gpr_log(GPR_DEBUG, "WRITE DATA: %s", dump);
+ gpr_free(dump);
+ }
+ }
+ }
+ // TODO(vigneshbabu): Use SliceBufferCast<> here.
+ grpc_core::Construct(reinterpret_cast<SliceBuffer*>(&eeep_->write_buffer),
+ SliceBuffer::TakeCSliceBuffer(*slices));
+ SliceBuffer* write_buffer =
+ reinterpret_cast<SliceBuffer*>(&eeep_->write_buffer);
+ pending_write_cb_ = write_cb;
+ return endpoint_->Write(
+ [this](y_absl::Status status) { FinishPendingWrite(status); },
+ write_buffer, args);
+ }
+
+ void FinishPendingWrite(y_absl::Status status) {
+ auto* write_buffer = reinterpret_cast<SliceBuffer*>(&eeep_->write_buffer);
+ write_buffer->~SliceBuffer();
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
+ gpr_log(GPR_INFO, "TCP: %p WRITE (peer=%s) error=%s", this,
+ TString(PeerAddress()).c_str(), status.ToString().c_str());
+ }
+ grpc_closure* cb = pending_write_cb_;
+ pending_write_cb_ = nullptr;
+ if (grpc_core::ExecCtx::Get() == nullptr) {
+ grpc_core::ApplicationCallbackExecCtx app_ctx;
+ grpc_core::ExecCtx exec_ctx;
+ grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, status);
+ } else {
+ grpc_core::Closure::Run(DEBUG_LOCATION, cb, status);
+ }
+ // For the ref taken in EventEngineEndpointWrapper::Write().
+ Unref();
}
// Returns true if the endpoint is not yet shutdown. In that case, it also
@@ -186,6 +274,9 @@ class EventEngineEndpointWrapper {
std::atomic<int64_t> shutdown_ref_{1};
y_absl::AnyInvocable<void(y_absl::StatusOr<int>)> on_release_fd_;
grpc_core::Mutex mu_;
+ grpc_closure* pending_read_cb_;
+ grpc_closure* pending_write_cb_;
+ grpc_slice_buffer* pending_read_buffer_;
TString peer_address_;
TString local_address_;
int fd_{-1};
@@ -204,41 +295,11 @@ void EndpointRead(grpc_endpoint* ep, grpc_slice_buffer* slices,
return;
}
- eeep->wrapper->Ref();
EventEngine::Endpoint::ReadArgs read_args = {min_progress_size};
-
- // TODO(vigneshbabu): Use SliceBufferCast<> here.
- SliceBuffer* read_buffer = new (&eeep->read_buffer)
- SliceBuffer(SliceBuffer::TakeCSliceBuffer(*slices));
- read_buffer->Clear();
- eeep->wrapper->Read(
- [eeep, cb, slices](y_absl::Status status) {
- auto* read_buffer = reinterpret_cast<SliceBuffer*>(&eeep->read_buffer);
- grpc_slice_buffer_move_into(read_buffer->c_slice_buffer(), slices);
- read_buffer->~SliceBuffer();
- if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
- size_t i;
- gpr_log(GPR_INFO, "TCP: %p READ (peer=%s) error=%s", eeep->wrapper,
- TString(eeep->wrapper->PeerAddress()).c_str(),
- status.ToString().c_str());
- if (gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
- for (i = 0; i < slices->count; i++) {
- char* dump = grpc_dump_slice(slices->slices[i],
- GPR_DUMP_HEX | GPR_DUMP_ASCII);
- gpr_log(GPR_DEBUG, "READ DATA: %s", dump);
- gpr_free(dump);
- }
- }
- }
- {
- grpc_core::ApplicationCallbackExecCtx app_ctx;
- grpc_core::ExecCtx exec_ctx;
- grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, status);
- }
- // For the ref taken in EndpointRead
- eeep->wrapper->Unref();
- },
- read_buffer, &read_args);
+ if (eeep->wrapper->Read(cb, slices, &read_args)) {
+ // Read succeeded immediately. Run the callback inline.
+ eeep->wrapper->FinishPendingRead(y_absl::OkStatus());
+ }
eeep->wrapper->ShutdownUnref();
}
@@ -256,45 +317,11 @@ void EndpointWrite(grpc_endpoint* ep, grpc_slice_buffer* slices,
return;
}
- eeep->wrapper->Ref();
EventEngine::Endpoint::WriteArgs write_args = {arg, max_frame_size};
- if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
- size_t i;
- gpr_log(GPR_INFO, "TCP: %p WRITE (peer=%s)", eeep->wrapper,
- TString(eeep->wrapper->PeerAddress()).c_str());
- if (gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) {
- for (i = 0; i < slices->count; i++) {
- char* dump =
- grpc_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
- gpr_log(GPR_DEBUG, "WRITE DATA: %s", dump);
- gpr_free(dump);
- }
- }
+ if (eeep->wrapper->Write(cb, slices, &write_args)) {
+ // Write succeeded immediately. Run the callback inline.
+ eeep->wrapper->FinishPendingWrite(y_absl::OkStatus());
}
-
- // TODO(vigneshbabu): Use SliceBufferCast<> here.
- SliceBuffer* write_buffer = new (&eeep->write_buffer)
- SliceBuffer(SliceBuffer::TakeCSliceBuffer(*slices));
- eeep->wrapper->Write(
- [eeep, cb](y_absl::Status status) {
- auto* write_buffer =
- reinterpret_cast<SliceBuffer*>(&eeep->write_buffer);
- write_buffer->~SliceBuffer();
- if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
- gpr_log(GPR_INFO, "TCP: %p WRITE (peer=%s) error=%s", eeep->wrapper,
- TString(eeep->wrapper->PeerAddress()).c_str(),
- status.ToString().c_str());
- }
- {
- grpc_core::ApplicationCallbackExecCtx app_ctx;
- grpc_core::ExecCtx exec_ctx;
- grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, status);
- }
- // For the ref taken in EndpointWrite
- eeep->wrapper->Unref();
- },
- write_buffer, &write_args);
-
eeep->wrapper->ShutdownUnref();
}
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/iomgr.cc b/contrib/libs/grpc/src/core/lib/iomgr/iomgr.cc
index 08c51cdd65..b6fefdc2b4 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/iomgr.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/iomgr.cc
@@ -29,10 +29,10 @@
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
+#include "src/core/lib/config/config_vars.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/crash.h"
-#include "src/core/lib/gprpp/global_config.h"
#include "src/core/lib/gprpp/thd.h"
#include "src/core/lib/iomgr/buffer_list.h"
#include "src/core/lib/iomgr/exec_ctx.h"
@@ -42,15 +42,10 @@
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/timer_manager.h"
-GPR_GLOBAL_CONFIG_DEFINE_BOOL(grpc_abort_on_leaks, false,
- "A debugging aid to cause a call to abort() when "
- "gRPC objects are leaked past grpc_shutdown()");
-
static gpr_mu g_mu;
static gpr_cv g_rcv;
static int g_shutdown;
static grpc_iomgr_object g_root_object;
-static bool g_grpc_abort_on_leaks;
void grpc_iomgr_init() {
grpc_core::ExecCtx exec_ctx;
@@ -65,7 +60,6 @@ void grpc_iomgr_init() {
g_root_object.name = const_cast<char*>("root");
grpc_iomgr_platform_init();
grpc_timer_list_init();
- g_grpc_abort_on_leaks = GPR_GLOBAL_CONFIG_GET(grpc_abort_on_leaks);
}
void grpc_iomgr_start() { grpc_timer_manager_init(); }
@@ -198,4 +192,6 @@ void grpc_iomgr_unregister_object(grpc_iomgr_object* obj) {
gpr_free(obj->name);
}
-bool grpc_iomgr_abort_on_leaks(void) { return g_grpc_abort_on_leaks; }
+bool grpc_iomgr_abort_on_leaks(void) {
+ return grpc_core::ConfigVars::Get().AbortOnLeaks();
+}
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/iomgr_windows.cc b/contrib/libs/grpc/src/core/lib/iomgr/iomgr_windows.cc
index b3a4a74107..29bb9ea471 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/iomgr_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/iomgr_windows.cc
@@ -24,6 +24,7 @@
#include <grpc/support/log.h>
+#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/iomgr/iocp_windows.h"
#include "src/core/lib/iomgr/iomgr.h"
@@ -37,6 +38,7 @@
#include "src/core/lib/iomgr/timer.h"
extern grpc_tcp_server_vtable grpc_windows_tcp_server_vtable;
+extern grpc_tcp_server_vtable grpc_windows_event_engine_tcp_server_vtable;
extern grpc_tcp_client_vtable grpc_windows_tcp_client_vtable;
extern grpc_timer_vtable grpc_generic_timer_vtable;
extern grpc_pollset_vtable grpc_windows_pollset_vtable;
@@ -81,7 +83,7 @@ static bool iomgr_platform_is_any_background_poller_thread(void) {
}
static bool iomgr_platform_add_closure_to_background_poller(
- grpc_closure* closure, grpc_error_handle error) {
+ grpc_closure* /* closure */, grpc_error_handle /* error */) {
return false;
}
@@ -95,7 +97,11 @@ static grpc_iomgr_platform_vtable vtable = {
void grpc_set_default_iomgr_platform() {
grpc_set_tcp_client_impl(&grpc_windows_tcp_client_vtable);
- grpc_set_tcp_server_impl(&grpc_windows_tcp_server_vtable);
+ if (grpc_core::IsEventEngineListenerEnabled()) {
+ grpc_set_tcp_server_impl(&grpc_windows_event_engine_tcp_server_vtable);
+ } else {
+ grpc_set_tcp_server_impl(&grpc_windows_tcp_server_vtable);
+ }
grpc_set_timer_impl(&grpc_generic_timer_vtable);
grpc_set_pollset_vtable(&grpc_windows_pollset_vtable);
grpc_set_pollset_set_vtable(&grpc_windows_pollset_set_vtable);
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/pollset_set_windows.cc b/contrib/libs/grpc/src/core/lib/iomgr/pollset_set_windows.cc
index dc28d520d6..e3ba5aedd0 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/pollset_set_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/pollset_set_windows.cc
@@ -30,19 +30,19 @@ static grpc_pollset_set* pollset_set_create(void) {
return (grpc_pollset_set*)((intptr_t)0xdeafbeef);
}
-static void pollset_set_destroy(grpc_pollset_set* pollset_set) {}
+static void pollset_set_destroy(grpc_pollset_set* /* pollset_set */) {}
-static void pollset_set_add_pollset(grpc_pollset_set* pollset_set,
- grpc_pollset* pollset) {}
+static void pollset_set_add_pollset(grpc_pollset_set* /* pollset_set */,
+ grpc_pollset* /* pollset */) {}
-static void pollset_set_del_pollset(grpc_pollset_set* pollset_set,
- grpc_pollset* pollset) {}
+static void pollset_set_del_pollset(grpc_pollset_set* /* pollset_set */,
+ grpc_pollset* /* pollset */) {}
-static void pollset_set_add_pollset_set(grpc_pollset_set* bag,
- grpc_pollset_set* item) {}
+static void pollset_set_add_pollset_set(grpc_pollset_set* /* bag */,
+ grpc_pollset_set* /* item */) {}
-static void pollset_set_del_pollset_set(grpc_pollset_set* bag,
- grpc_pollset_set* item) {}
+static void pollset_set_del_pollset_set(grpc_pollset_set* /* bag */,
+ grpc_pollset_set* /* item */) {}
grpc_pollset_set_vtable grpc_windows_pollset_set_vtable = {
pollset_set_create, pollset_set_destroy,
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/pollset_windows.cc b/contrib/libs/grpc/src/core/lib/iomgr/pollset_windows.cc
index cf2c6b1f52..bbe7705899 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/pollset_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/pollset_windows.cc
@@ -105,7 +105,7 @@ static void pollset_shutdown(grpc_pollset* pollset, grpc_closure* closure) {
}
}
-static void pollset_destroy(grpc_pollset* pollset) {}
+static void pollset_destroy(grpc_pollset* /* pollset */) {}
static grpc_error_handle pollset_work(grpc_pollset* pollset,
grpc_pollset_worker** worker_hdl,
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/socket_utils_common_posix.cc b/contrib/libs/grpc/src/core/lib/iomgr/socket_utils_common_posix.cc
index 0b76f749c2..ca89ecd2c1 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/socket_utils_common_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/socket_utils_common_posix.cc
@@ -449,9 +449,22 @@ grpc_error_handle grpc_create_dualstack_socket(
static int create_socket(grpc_socket_factory* factory, int domain, int type,
int protocol) {
- return (factory != nullptr)
- ? grpc_socket_factory_socket(factory, domain, type, protocol)
- : socket(domain, type, protocol);
+ int res = (factory != nullptr)
+ ? grpc_socket_factory_socket(factory, domain, type, protocol)
+ : socket(domain, type, protocol);
+ if (res < 0 && errno == EMFILE) {
+ int saved_errno = errno;
+ GRPC_LOG_EVERY_N_SEC(
+ 10, GPR_ERROR,
+ "socket(%d, %d, %d) returned %d with error: |%s|. This process "
+ "might not have a sufficient file descriptor limit for the number "
+ "of connections grpc wants to open (which is generally a function of "
+ "the number of grpc channels, the lb policy of each channel, and the "
+ "number of backends each channel is load balancing across).",
+ domain, type, protocol, res, grpc_core::StrError(errno).c_str());
+ errno = saved_errno;
+ }
+ return res;
}
grpc_error_handle grpc_create_dualstack_socket_using_factory(
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/tcp_client_windows.cc b/contrib/libs/grpc/src/core/lib/iomgr/tcp_client_windows.cc
index 819d867663..d1ecee8b0b 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/tcp_client_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/tcp_client_windows.cc
@@ -69,7 +69,7 @@ static void async_connect_unlock_and_cleanup(async_connect* ac,
if (socket != NULL) grpc_winsocket_destroy(socket);
}
-static void on_alarm(void* acp, grpc_error_handle error) {
+static void on_alarm(void* acp, grpc_error_handle /* error */) {
async_connect* ac = (async_connect*)acp;
gpr_mu_lock(&ac->mu);
grpc_winsocket* socket = ac->socket;
@@ -124,7 +124,7 @@ static void on_connect(void* acp, grpc_error_handle error) {
// Tries to issue one async connection, then schedules both an IOCP
// notification request for the connection, and one timeout alert.
static int64_t tcp_connect(grpc_closure* on_done, grpc_endpoint** endpoint,
- grpc_pollset_set* interested_parties,
+ grpc_pollset_set* /* interested_parties */,
const EndpointConfig& config,
const grpc_resolved_address* addr,
grpc_core::Timestamp deadline) {
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/tcp_posix.cc b/contrib/libs/grpc/src/core/lib/iomgr/tcp_posix.cc
index deab1fbffb..0e73612db4 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/tcp_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/tcp_posix.cc
@@ -20,7 +20,6 @@
#include <grpc/impl/grpc_types.h>
-#include "src/core/lib/gprpp/global_config_generic.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/port.h"
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_posix.cc b/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_posix.cc
index cd2a523729..dad424584a 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_posix.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_posix.cc
@@ -54,6 +54,7 @@
#include "src/core/lib/address_utils/sockaddr_utils.h"
#include "src/core/lib/event_engine/default_event_engine.h"
+#include "src/core/lib/event_engine/memory_allocator_factory.h"
#include "src/core/lib/event_engine/resolved_address_internal.h"
#include "src/core/lib/event_engine/shim.h"
#include "src/core/lib/event_engine/tcp_socket_utils.h"
@@ -80,24 +81,10 @@ static std::atomic<int64_t> num_dropped_connections{0};
using ::grpc_event_engine::experimental::EndpointConfig;
using ::grpc_event_engine::experimental::EventEngine;
using ::grpc_event_engine::experimental::MemoryAllocator;
+using ::grpc_event_engine::experimental::MemoryQuotaBasedMemoryAllocatorFactory;
using ::grpc_event_engine::experimental::PosixEventEngineWithFdSupport;
using ::grpc_event_engine::experimental::SliceBuffer;
-class MemoryAllocatorFactoryWrapper
- : public grpc_event_engine::experimental::MemoryAllocatorFactory {
- public:
- explicit MemoryAllocatorFactoryWrapper(
- grpc_core::MemoryQuotaRefPtr memory_quota)
- : memory_quota_(std::move(memory_quota)) {}
-
- MemoryAllocator CreateMemoryAllocator(y_absl::string_view name) override {
- return memory_quota_->CreateMemoryAllocator(name);
- }
-
- private:
- grpc_core::MemoryQuotaRefPtr memory_quota_;
-};
-
static grpc_error_handle CreateEventEngineListener(
grpc_tcp_server* s, grpc_closure* shutdown_complete,
const EndpointConfig& config, grpc_tcp_server** server) {
@@ -191,7 +178,9 @@ static grpc_error_handle CreateEventEngineListener(
delete s->fd_handler;
delete s;
},
- config, std::make_unique<MemoryAllocatorFactoryWrapper>(s->memory_quota));
+ config,
+ std::make_unique<MemoryQuotaBasedMemoryAllocatorFactory>(
+ s->memory_quota));
if (!listener.ok()) {
delete s;
*server = nullptr;
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_windows.cc b/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_windows.cc
index 552af7d096..edb9f1a746 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_windows.cc
@@ -30,6 +30,8 @@
#include "y_absl/strings/str_cat.h"
#include <grpc/event_engine/endpoint_config.h>
+#include <grpc/event_engine/event_engine.h>
+#include <grpc/event_engine/memory_allocator.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/log_windows.h>
@@ -38,7 +40,15 @@
#include <grpc/support/time.h>
#include "src/core/lib/address_utils/sockaddr_utils.h"
+#include "src/core/lib/event_engine/memory_allocator_factory.h"
+#include "src/core/lib/event_engine/resolved_address_internal.h"
+#include "src/core/lib/event_engine/tcp_socket_utils.h"
+#include "src/core/lib/event_engine/windows/windows_engine.h"
+#include "src/core/lib/event_engine/windows/windows_listener.h"
#include "src/core/lib/gprpp/crash.h"
+#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/event_engine_shims/closure.h"
+#include "src/core/lib/iomgr/event_engine_shims/endpoint.h"
#include "src/core/lib/iomgr/iocp_windows.h"
#include "src/core/lib/iomgr/pollset_windows.h"
#include "src/core/lib/iomgr/resolve_address.h"
@@ -47,11 +57,23 @@
#include "src/core/lib/iomgr/tcp_server.h"
#include "src/core/lib/iomgr/tcp_windows.h"
#include "src/core/lib/resource_quota/api.h"
+#include "src/core/lib/resource_quota/resource_quota.h"
#include "src/core/lib/slice/slice_internal.h"
#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
+namespace {
+using ::grpc_event_engine::experimental::CreateResolvedAddress;
using ::grpc_event_engine::experimental::EndpointConfig;
+using ::grpc_event_engine::experimental::EventEngine;
+using ::grpc_event_engine::experimental::grpc_event_engine_endpoint_create;
+using ::grpc_event_engine::experimental::MemoryAllocator;
+using ::grpc_event_engine::experimental::MemoryQuotaBasedMemoryAllocatorFactory;
+using ::grpc_event_engine::experimental::ResolvedAddressSetPort;
+using ::grpc_event_engine::experimental::RunEventEngineClosure;
+using ::grpc_event_engine::experimental::WindowsEventEngine;
+using ::grpc_event_engine::experimental::WindowsEventEngineListener;
+} // namespace
// one listening port
typedef struct grpc_tcp_listener grpc_tcp_listener;
@@ -98,12 +120,15 @@ struct grpc_tcp_server {
// shutdown callback
grpc_closure* shutdown_complete;
+
+ // used for the EventEngine shim
+ WindowsEventEngineListener* ee_listener;
};
// Public function. Allocates the proper data structures to hold a
// grpc_tcp_server.
static grpc_error_handle tcp_server_create(grpc_closure* shutdown_complete,
- const EndpointConfig& config,
+ const EndpointConfig& /* config */,
grpc_tcp_server_cb on_accept_cb,
void* on_accept_cb_arg,
grpc_tcp_server** server) {
@@ -122,7 +147,7 @@ static grpc_error_handle tcp_server_create(grpc_closure* shutdown_complete,
return y_absl::OkStatus();
}
-static void destroy_server(void* arg, grpc_error_handle error) {
+static void destroy_server(void* arg, grpc_error_handle /* error */) {
grpc_tcp_server* s = (grpc_tcp_server*)arg;
// Now that the accepts have been aborted, we can destroy the sockets.
@@ -533,27 +558,169 @@ static void tcp_server_start(grpc_tcp_server* s,
gpr_mu_unlock(&s->mu);
}
-static unsigned tcp_server_port_fd_count(grpc_tcp_server* s,
- unsigned port_index) {
+static unsigned tcp_server_port_fd_count(grpc_tcp_server* /* s */,
+ unsigned /* port_index */) {
return 0;
}
-static int tcp_server_port_fd(grpc_tcp_server* s, unsigned port_index,
- unsigned fd_index) {
+static int tcp_server_port_fd(grpc_tcp_server* /* s */,
+ unsigned /* port_index */,
+ unsigned /* fd_index */) {
return -1;
}
static grpc_core::TcpServerFdHandler* tcp_server_create_fd_handler(
- grpc_tcp_server* s) {
+ grpc_tcp_server* /* s */) {
return nullptr;
}
-static void tcp_server_shutdown_listeners(grpc_tcp_server* s) {}
+static void tcp_server_shutdown_listeners(grpc_tcp_server* /* s */) {}
+
+static int tcp_pre_allocated_fd(grpc_tcp_server* /* s */) { return -1; }
+
+static void tcp_set_pre_allocated_fd(grpc_tcp_server* /* s */, int /* fd */) {}
grpc_tcp_server_vtable grpc_windows_tcp_server_vtable = {
tcp_server_create, tcp_server_start,
tcp_server_add_port, tcp_server_create_fd_handler,
tcp_server_port_fd_count, tcp_server_port_fd,
tcp_server_ref, tcp_server_shutdown_starting_add,
- tcp_server_unref, tcp_server_shutdown_listeners};
+ tcp_server_unref, tcp_server_shutdown_listeners,
+ tcp_pre_allocated_fd, tcp_set_pre_allocated_fd};
+
+// ---- EventEngine shim ------------------------------------------------------
+
+namespace {
+
+static grpc_error_handle event_engine_create(grpc_closure* shutdown_complete,
+ const EndpointConfig& config,
+ grpc_tcp_server_cb on_accept_cb,
+ void* on_accept_cb_arg,
+ grpc_tcp_server** server) {
+ // On Windows, the event_engine_listener experiment only supports the
+ // default engine
+ WindowsEventEngine* engine_ptr = reinterpret_cast<WindowsEventEngine*>(
+ config.GetVoidPointer(GRPC_INTERNAL_ARG_EVENT_ENGINE));
+ grpc_tcp_server* s = (grpc_tcp_server*)gpr_malloc(sizeof(grpc_tcp_server));
+ GPR_ASSERT(on_accept_cb != nullptr);
+ auto accept_cb = [s, on_accept_cb, on_accept_cb_arg](
+ std::unique_ptr<EventEngine::Endpoint> endpoint,
+ MemoryAllocator memory_allocator) {
+ grpc_core::ApplicationCallbackExecCtx app_ctx;
+ grpc_core::ExecCtx exec_ctx;
+ grpc_tcp_server_acceptor* acceptor =
+ static_cast<grpc_tcp_server_acceptor*>(gpr_malloc(sizeof(*acceptor)));
+ acceptor->from_server = s;
+ acceptor->port_index = -1;
+ acceptor->fd_index = -1;
+ acceptor->external_connection = false;
+ on_accept_cb(on_accept_cb_arg,
+ grpc_event_engine_endpoint_create(std::move(endpoint)),
+ nullptr, acceptor);
+ };
+ auto on_shutdown = [shutdown_complete](y_absl::Status status) {
+ RunEventEngineClosure(shutdown_complete, status);
+ };
+ grpc_core::RefCountedPtr<grpc_core::ResourceQuota> resource_quota;
+ {
+ void* tmp_quota = config.GetVoidPointer(GRPC_ARG_RESOURCE_QUOTA);
+ GPR_ASSERT(tmp_quota != nullptr);
+ resource_quota =
+ reinterpret_cast<grpc_core::ResourceQuota*>(tmp_quota)->Ref();
+ }
+ gpr_ref_init(&s->refs, 1);
+ gpr_mu_init(&s->mu);
+ s->ee_listener = new WindowsEventEngineListener(
+ engine_ptr->poller(), std::move(accept_cb), std::move(on_shutdown),
+ std::make_unique<MemoryQuotaBasedMemoryAllocatorFactory>(
+ resource_quota->memory_quota()),
+ engine_ptr->shared_from_this(), engine_ptr->executor(), config);
+ s->active_ports = -1;
+ s->on_accept_cb = [](void* /* arg */, grpc_endpoint* /* ep */,
+ grpc_pollset* /* accepting_pollset */,
+ grpc_tcp_server_acceptor* /* acceptor */) {
+ grpc_core::Crash("iomgr on_accept_cb callback should be unused");
+ };
+ s->on_accept_cb_arg = nullptr;
+ s->head = nullptr;
+ s->tail = nullptr;
+ s->shutdown_starting.head = nullptr;
+ s->shutdown_starting.tail = nullptr;
+ s->shutdown_complete = grpc_core::NewClosure([](y_absl::Status) {
+ grpc_core::Crash("iomgr shutdown_complete callback should be unused");
+ });
+ *server = s;
+ return y_absl::OkStatus();
+}
+
+static void event_engine_start(grpc_tcp_server* s,
+ const std::vector<grpc_pollset*>* /*pollsets*/) {
+ GPR_ASSERT(s->ee_listener->Start().ok());
+}
+
+static grpc_error_handle event_engine_add_port(
+ grpc_tcp_server* s, const grpc_resolved_address* addr, int* port) {
+ GPR_ASSERT(addr != nullptr);
+ GPR_ASSERT(port != nullptr);
+ auto ee_addr = CreateResolvedAddress(*addr);
+ auto out_port = s->ee_listener->Bind(ee_addr);
+ *port = out_port.ok() ? *out_port : -1;
+ return out_port.status();
+}
+
+static grpc_core::TcpServerFdHandler* event_engine_create_fd_handler(
+ grpc_tcp_server* /* s */) {
+ return nullptr;
+}
+
+static unsigned event_engine_port_fd_count(grpc_tcp_server* /* s */,
+ unsigned /* port_index */) {
+ return 0;
+}
+
+static int event_engine_port_fd(grpc_tcp_server* /* s */,
+ unsigned /* port_index */,
+ unsigned /* fd_index */) {
+ return -1;
+}
+
+static grpc_tcp_server* event_engine_ref(grpc_tcp_server* s) {
+ gpr_ref_non_zero(&s->refs);
+ return s;
+}
+
+static void event_engine_shutdown_listeners(grpc_tcp_server* s) {
+ s->ee_listener->ShutdownListeners();
+}
+
+static void event_engine_unref(grpc_tcp_server* s) {
+ if (gpr_unref(&s->refs)) {
+ event_engine_shutdown_listeners(s);
+ gpr_mu_lock(&s->mu);
+ grpc_core::ExecCtx::RunList(DEBUG_LOCATION, &s->shutdown_starting);
+ gpr_mu_unlock(&s->mu);
+ gpr_mu_destroy(&s->mu);
+ delete s->ee_listener;
+ gpr_free(s);
+ }
+}
+
+static void event_engine_shutdown_starting_add(
+ grpc_tcp_server* s, grpc_closure* shutdown_starting) {
+ gpr_mu_lock(&s->mu);
+ grpc_closure_list_append(&s->shutdown_starting, shutdown_starting,
+ y_absl::OkStatus());
+ gpr_mu_unlock(&s->mu);
+}
+
+} // namespace
+
+grpc_tcp_server_vtable grpc_windows_event_engine_tcp_server_vtable = {
+ event_engine_create, event_engine_start,
+ event_engine_add_port, event_engine_create_fd_handler,
+ event_engine_port_fd_count, event_engine_port_fd,
+ event_engine_ref, event_engine_shutdown_starting_add,
+ event_engine_unref, event_engine_shutdown_listeners,
+ tcp_pre_allocated_fd, tcp_set_pre_allocated_fd};
+
#endif // GRPC_WINSOCK_SOCKET
diff --git a/contrib/libs/grpc/src/core/lib/iomgr/tcp_windows.cc b/contrib/libs/grpc/src/core/lib/iomgr/tcp_windows.cc
index d15175c1fd..3bea3c766a 100644
--- a/contrib/libs/grpc/src/core/lib/iomgr/tcp_windows.cc
+++ b/contrib/libs/grpc/src/core/lib/iomgr/tcp_windows.cc
@@ -203,7 +203,8 @@ static void on_read(void* tcpp, grpc_error_handle error) {
}
GPR_ASSERT((size_t)info->bytes_transferred == tcp->read_slices->length);
- if (grpc_tcp_trace.enabled()) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace) &&
+ gpr_should_log(GPR_LOG_SEVERITY_INFO)) {
size_t i;
for (i = 0; i < tcp->read_slices->count; i++) {
char* dump = grpc_dump_slice(tcp->read_slices->slices[i],
@@ -236,7 +237,8 @@ static void on_read(void* tcpp, grpc_error_handle error) {
#define DEFAULT_TARGET_READ_SIZE 8192
#define MAX_WSABUF_COUNT 16
static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices,
- grpc_closure* cb, bool urgent, int /*min_progress_size*/) {
+ grpc_closure* cb, bool /* urgent */,
+ int /* min_progress_size */) {
grpc_tcp* tcp = (grpc_tcp*)ep;
grpc_winsocket* handle = tcp->socket;
grpc_winsocket_callback_info* info = &handle->read_info;
@@ -341,7 +343,8 @@ static void on_write(void* tcpp, grpc_error_handle error) {
// Initiates a write.
static void win_write(grpc_endpoint* ep, grpc_slice_buffer* slices,
- grpc_closure* cb, void* arg, int /*max_frame_size*/) {
+ grpc_closure* cb, void* /* arg */,
+ int /* max_frame_size */) {
grpc_tcp* tcp = (grpc_tcp*)ep;
grpc_winsocket* socket = tcp->socket;
grpc_winsocket_callback_info* info = &socket->write_info;
@@ -353,7 +356,8 @@ static void win_write(grpc_endpoint* ep, grpc_slice_buffer* slices,
WSABUF* buffers = local_buffers;
size_t len, async_buffers_offset = 0;
- if (grpc_tcp_trace.enabled()) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace) &&
+ gpr_should_log(GPR_LOG_SEVERITY_INFO)) {
size_t i;
for (i = 0; i < slices->count; i++) {
char* data =
@@ -466,8 +470,8 @@ static void win_add_to_pollset_set(grpc_endpoint* ep, grpc_pollset_set* pss) {
grpc_iocp_add_socket(tcp->socket);
}
-static void win_delete_from_pollset_set(grpc_endpoint* ep,
- grpc_pollset_set* pss) {}
+static void win_delete_from_pollset_set(grpc_endpoint* /* ep */,
+ grpc_pollset_set* /* pss */) {}
// Initiates a shutdown of the TCP endpoint. This will queue abort callbacks
// for the potential read and write operations. It is up to the caller to
@@ -504,9 +508,9 @@ static y_absl::string_view win_get_local_address(grpc_endpoint* ep) {
return tcp->local_address;
}
-static int win_get_fd(grpc_endpoint* ep) { return -1; }
+static int win_get_fd(grpc_endpoint* /* ep */) { return -1; }
-static bool win_can_track_err(grpc_endpoint* ep) { return false; }
+static bool win_can_track_err(grpc_endpoint* /* ep */) { return false; }
static grpc_endpoint_vtable vtable = {win_read,
win_write,
diff --git a/contrib/libs/grpc/src/core/lib/load_balancing/lb_policy.cc b/contrib/libs/grpc/src/core/lib/load_balancing/lb_policy.cc
index acb5fc3969..7344536ec2 100644
--- a/contrib/libs/grpc/src/core/lib/load_balancing/lb_policy.cc
+++ b/contrib/libs/grpc/src/core/lib/load_balancing/lb_policy.cc
@@ -69,19 +69,15 @@ LoadBalancingPolicy::SubchannelPicker::SubchannelPicker()
LoadBalancingPolicy::PickResult LoadBalancingPolicy::QueuePicker::Pick(
PickArgs /*args*/) {
// We invoke the parent's ExitIdleLocked() via a closure instead
- // of doing it directly here, for two reasons:
- // 1. ExitIdleLocked() may cause the policy's state to change and
- // a new picker to be delivered to the channel. If that new
- // picker is delivered before ExitIdleLocked() returns, then by
- // the time this function returns, the pick will already have
- // been processed, and we'll be trying to re-process the same
- // pick again, leading to a crash.
- // 2. We are currently running in the data plane mutex, but we
- // need to bounce into the control plane work_serializer to call
- // ExitIdleLocked().
- if (!exit_idle_called_ && parent_ != nullptr) {
- exit_idle_called_ = true;
- auto* parent = parent_->Ref().release(); // ref held by lambda.
+ // of doing it directly here because ExitIdleLocked() may cause the
+ // policy's state to change and a new picker to be delivered to the
+ // channel. If that new picker is delivered before ExitIdleLocked()
+ // returns, then by the time this function returns, the pick will already
+ // have been processed, and we'll be trying to re-process the same pick
+ // again, leading to a crash.
+ MutexLock lock(&mu_);
+ if (parent_ != nullptr) {
+ auto* parent = parent_.release(); // ref held by lambda.
ExecCtx::Run(DEBUG_LOCATION,
GRPC_CLOSURE_CREATE(
[](void* arg, grpc_error_handle /*error*/) {
diff --git a/contrib/libs/grpc/src/core/lib/load_balancing/lb_policy.h b/contrib/libs/grpc/src/core/lib/load_balancing/lb_policy.h
index c6977a1540..c6b52e7ddf 100644
--- a/contrib/libs/grpc/src/core/lib/load_balancing/lb_policy.h
+++ b/contrib/libs/grpc/src/core/lib/load_balancing/lb_policy.h
@@ -28,6 +28,7 @@
#include <utility>
#include <vector>
+#include "y_absl/base/thread_annotations.h"
#include "y_absl/status/status.h"
#include "y_absl/status/statusor.h"
#include "y_absl/strings/string_view.h"
@@ -45,6 +46,7 @@
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/gprpp/work_serializer.h"
#include "src/core/lib/iomgr/iomgr_fwd.h"
#include "src/core/lib/load_balancing/subchannel_interface.h"
@@ -393,8 +395,8 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
PickResult Pick(PickArgs args) override;
private:
- RefCountedPtr<LoadBalancingPolicy> parent_;
- bool exit_idle_called_ = false;
+ Mutex mu_;
+ RefCountedPtr<LoadBalancingPolicy> parent_ Y_ABSL_GUARDED_BY(&mu_);
};
// A picker that returns PickResult::Fail for all picks.
diff --git a/contrib/libs/grpc/src/core/lib/promise/activity.cc b/contrib/libs/grpc/src/core/lib/promise/activity.cc
index 46a4396b76..cfd3169697 100644
--- a/contrib/libs/grpc/src/core/lib/promise/activity.cc
+++ b/contrib/libs/grpc/src/core/lib/promise/activity.cc
@@ -19,8 +19,11 @@
#include <stddef.h>
#include <initializer_list>
+#include <vector>
+#include "y_absl/strings/str_cat.h"
#include "y_absl/strings/str_format.h"
+#include "y_absl/strings/str_join.h"
#include "src/core/lib/gprpp/atomic_utils.h"
@@ -36,7 +39,9 @@ namespace promise_detail {
///////////////////////////////////////////////////////////////////////////////
// HELPER TYPES
-TString Unwakeable::ActivityDebugTag(void*) const { return "<unknown>"; }
+TString Unwakeable::ActivityDebugTag(WakeupMask) const {
+ return "<unknown>";
+}
// Weak handle to an Activity.
// Handle can persist while Activity goes away.
@@ -58,7 +63,7 @@ class FreestandingActivity::Handle final : public Wakeable {
// Activity needs to wake up (if it still exists!) - wake it up, and drop the
// ref that was kept for this handle.
- void Wakeup(void*) override Y_ABSL_LOCKS_EXCLUDED(mu_) {
+ void Wakeup(WakeupMask) override Y_ABSL_LOCKS_EXCLUDED(mu_) {
mu_.Lock();
// Note that activity refcount can drop to zero, but we could win the lock
// against DropActivity, so we need to only increase activities refcount if
@@ -68,7 +73,7 @@ class FreestandingActivity::Handle final : public Wakeable {
mu_.Unlock();
// Activity still exists and we have a reference: wake it up, which will
// drop the ref.
- activity->Wakeup(nullptr);
+ activity->Wakeup(0);
} else {
// Could not get the activity - it's either gone or going. No need to wake
// it up!
@@ -78,9 +83,9 @@ class FreestandingActivity::Handle final : public Wakeable {
Unref();
}
- void Drop(void*) override { Unref(); }
+ void Drop(WakeupMask) override { Unref(); }
- TString ActivityDebugTag(void*) const override {
+ TString ActivityDebugTag(WakeupMask) const override {
MutexLock lock(&mu_);
return activity_ == nullptr ? "<unknown>" : activity_->DebugTag();
}
@@ -124,7 +129,7 @@ void FreestandingActivity::DropHandle() {
Waker FreestandingActivity::MakeNonOwningWaker() {
mu_.AssertHeld();
- return Waker(RefHandle(), nullptr);
+ return Waker(RefHandle(), 0);
}
} // namespace promise_detail
@@ -133,4 +138,15 @@ TString Activity::DebugTag() const {
return y_absl::StrFormat("ACTIVITY[%p]", this);
}
+///////////////////////////////////////////////////////////////////////////////
+// INTRA ACTIVITY WAKER IMPLEMENTATION
+
+TString IntraActivityWaiter::DebugString() const {
+ std::vector<int> bits;
+ for (size_t i = 0; i < 8 * sizeof(WakeupMask); i++) {
+ if (wakeups_ & (1 << i)) bits.push_back(i);
+ }
+ return y_absl::StrCat("{", y_absl::StrJoin(bits, ","), "}");
+}
+
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/promise/activity.h b/contrib/libs/grpc/src/core/lib/promise/activity.h
index 4046bf5779..552b8e48aa 100644
--- a/contrib/libs/grpc/src/core/lib/promise/activity.h
+++ b/contrib/libs/grpc/src/core/lib/promise/activity.h
@@ -39,24 +39,29 @@
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/detail/promise_factory.h"
#include "src/core/lib/promise/detail/status.h"
+#include "src/core/lib/promise/poll.h"
namespace grpc_core {
class Activity;
+// WakeupMask is a bitfield representing which parts of an activity should be
+// woken up.
+using WakeupMask = uint16_t;
+
// A Wakeable object is used by queues to wake activities.
class Wakeable {
public:
// Wake up the underlying activity.
// After calling, this Wakeable cannot be used again.
- // arg comes from the Waker object and allows one Wakeable instance to be used
- // for multiple disjoint subparts of an Activity.
- virtual void Wakeup(void* arg) = 0;
+ // WakeupMask comes from the activity that created this Wakeable and specifies
+ // the set of promises that should be awoken.
+ virtual void Wakeup(WakeupMask wakeup_mask) = 0;
// Drop this wakeable without waking up the underlying activity.
- virtual void Drop(void* arg) = 0;
+ virtual void Drop(WakeupMask wakeup_mask) = 0;
// Return the underlying activity debug tag, or "<unknown>" if not available.
- virtual TString ActivityDebugTag(void* arg) const = 0;
+ virtual TString ActivityDebugTag(WakeupMask wakeup_mask) const = 0;
protected:
inline ~Wakeable() {}
@@ -64,9 +69,9 @@ class Wakeable {
namespace promise_detail {
struct Unwakeable final : public Wakeable {
- void Wakeup(void*) override {}
- void Drop(void*) override {}
- TString ActivityDebugTag(void*) const override;
+ void Wakeup(WakeupMask) override {}
+ void Drop(WakeupMask) override {}
+ TString ActivityDebugTag(WakeupMask) const override;
};
static Unwakeable* unwakeable() {
return NoDestructSingleton<Unwakeable>::Get();
@@ -77,8 +82,9 @@ static Unwakeable* unwakeable() {
// This type is non-copyable but movable.
class Waker {
public:
- Waker(Wakeable* wakeable, void* arg) : wakeable_and_arg_{wakeable, arg} {}
- Waker() : Waker(promise_detail::unwakeable(), nullptr) {}
+ Waker(Wakeable* wakeable, WakeupMask wakeup_mask)
+ : wakeable_and_arg_{wakeable, wakeup_mask} {}
+ Waker() : Waker(promise_detail::unwakeable(), 0) {}
~Waker() { wakeable_and_arg_.Drop(); }
Waker(const Waker&) = delete;
Waker& operator=(const Waker&) = delete;
@@ -94,7 +100,7 @@ class Waker {
template <typename H>
friend H AbslHashValue(H h, const Waker& w) {
return H::combine(H::combine(std::move(h), w.wakeable_and_arg_.wakeable),
- w.wakeable_and_arg_.arg);
+ w.wakeable_and_arg_.wakeup_mask);
}
bool operator==(const Waker& other) const noexcept {
@@ -117,27 +123,42 @@ class Waker {
private:
struct WakeableAndArg {
Wakeable* wakeable;
- void* arg;
+ WakeupMask wakeup_mask;
- void Wakeup() { wakeable->Wakeup(arg); }
- void Drop() { wakeable->Drop(arg); }
+ void Wakeup() { wakeable->Wakeup(wakeup_mask); }
+ void Drop() { wakeable->Drop(wakeup_mask); }
TString ActivityDebugTag() const {
return wakeable == nullptr ? "<unknown>"
- : wakeable->ActivityDebugTag(arg);
+ : wakeable->ActivityDebugTag(wakeup_mask);
}
bool operator==(const WakeableAndArg& other) const noexcept {
- return wakeable == other.wakeable && arg == other.arg;
+ return wakeable == other.wakeable && wakeup_mask == other.wakeup_mask;
}
};
WakeableAndArg Take() {
- return std::exchange(wakeable_and_arg_,
- {promise_detail::unwakeable(), nullptr});
+ return std::exchange(wakeable_and_arg_, {promise_detail::unwakeable(), 0});
}
WakeableAndArg wakeable_and_arg_;
};
+// Helper type to track wakeups between objects in the same activity.
+// Can be fairly fast as no ref counting or locking needs to occur.
+class IntraActivityWaiter {
+ public:
+ // Register for wakeup, return Pending(). If state is not ready to proceed,
+ // Promises should bottom out here.
+ Pending pending();
+ // Wake the activity
+ void Wake();
+
+ TString DebugString() const;
+
+ private:
+ WakeupMask wakeups_ = 0;
+};
+
// An Activity tracks execution of a single promise.
// It executes the promise under a mutex.
// When the promise stalls, it registers the containing activity to be woken up
@@ -157,7 +178,13 @@ class Activity : public Orphanable {
void ForceWakeup() { MakeOwningWaker().Wakeup(); }
// Force the current activity to immediately repoll if it doesn't complete.
- virtual void ForceImmediateRepoll() = 0;
+ virtual void ForceImmediateRepoll(WakeupMask mask) = 0;
+ // Legacy version of ForceImmediateRepoll() that uses the current participant.
+ // Will go away once Party gets merged with Activity. New usage is banned.
+ void ForceImmediateRepoll() { ForceImmediateRepoll(CurrentParticipant()); }
+
+ // Return the current part of the activity as a bitmask
+ virtual WakeupMask CurrentParticipant() const { return 1; }
// Return the current activity.
// Additionally:
@@ -285,7 +312,7 @@ class FreestandingActivity : public Activity, private Wakeable {
public:
Waker MakeOwningWaker() final {
Ref();
- return Waker(this, nullptr);
+ return Waker(this, 0);
}
Waker MakeNonOwningWaker() final;
@@ -294,7 +321,7 @@ class FreestandingActivity : public Activity, private Wakeable {
Unref();
}
- void ForceImmediateRepoll() final {
+ void ForceImmediateRepoll(WakeupMask) final {
mu_.AssertHeld();
SetActionDuringRun(ActionDuringRun::kWakeup);
}
@@ -334,7 +361,7 @@ class FreestandingActivity : public Activity, private Wakeable {
Mutex* mu() Y_ABSL_LOCK_RETURNED(mu_) { return &mu_; }
- TString ActivityDebugTag(void*) const override { return DebugTag(); }
+ TString ActivityDebugTag(WakeupMask) const override { return DebugTag(); }
private:
class Handle;
@@ -468,7 +495,7 @@ class PromiseActivity final
// the activity to an external threadpool to run. If the activity is already
// running on this thread, a note is taken of such and the activity is
// repolled if it doesn't complete.
- void Wakeup(void*) final {
+ void Wakeup(WakeupMask) final {
// If there is an active activity, but hey it's us, flag that and we'll loop
// in RunLoop (that's calling from above here!).
if (Activity::is_current()) {
@@ -487,7 +514,7 @@ class PromiseActivity final
}
// Drop a wakeup
- void Drop(void*) final { this->WakeupComplete(); }
+ void Drop(WakeupMask) final { this->WakeupComplete(); }
// Notification that we're no longer executing - it's ok to destruct the
// promise.
@@ -594,6 +621,16 @@ ActivityPtr MakeActivity(Factory promise_factory,
std::move(on_done), std::forward<Contexts>(contexts)...));
}
+inline Pending IntraActivityWaiter::pending() {
+ wakeups_ |= Activity::current()->CurrentParticipant();
+ return Pending();
+}
+
+inline void IntraActivityWaiter::Wake() {
+ if (wakeups_ == 0) return;
+ Activity::current()->ForceImmediateRepoll(std::exchange(wakeups_, 0));
+}
+
} // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_PROMISE_ACTIVITY_H
diff --git a/contrib/libs/grpc/src/core/lib/promise/cancel_callback.h b/contrib/libs/grpc/src/core/lib/promise/cancel_callback.h
new file mode 100644
index 0000000000..9e2e5bed67
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/promise/cancel_callback.h
@@ -0,0 +1,77 @@
+// Copyright 2022 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef GRPC_SRC_CORE_LIB_PROMISE_CANCEL_CALLBACK_H
+#define GRPC_SRC_CORE_LIB_PROMISE_CANCEL_CALLBACK_H
+
+#include <grpc/support/port_platform.h>
+
+#include <utility>
+
+#include "src/core/lib/promise/detail/promise_like.h"
+
+namespace grpc_core {
+
+namespace cancel_callback_detail {
+
+template <typename Fn>
+class Handler {
+ public:
+ explicit Handler(Fn fn) : fn_(std::move(fn)) {}
+ Handler(const Handler&) = delete;
+ Handler& operator=(const Handler&) = delete;
+ ~Handler() {
+ if (!done_) {
+ fn_();
+ }
+ }
+ Handler(Handler&& other) noexcept
+ : fn_(std::move(other.fn_)), done_(other.done_) {
+ other.done_ = true;
+ }
+ Handler& operator=(Handler&& other) noexcept {
+ fn_ = std::move(other.fn_);
+ done_ = other.done_;
+ other.done_ = true;
+ }
+
+ void Done() { done_ = true; }
+
+ private:
+ Fn fn_;
+ bool done_ = false;
+};
+
+} // namespace cancel_callback_detail
+
+// Wrap main_fn so that it calls cancel_fn if the promise is destroyed prior to
+// completion.
+// Returns a promise with the same result type as main_fn.
+template <typename MainFn, typename CancelFn>
+auto OnCancel(MainFn main_fn, CancelFn cancel_fn) {
+ return [on_cancel =
+ cancel_callback_detail::Handler<CancelFn>(std::move(cancel_fn)),
+ main_fn = promise_detail::PromiseLike<MainFn>(
+ std::move(main_fn))]() mutable {
+ auto r = main_fn();
+ if (r.ready()) {
+ on_cancel.Done();
+ }
+ return r;
+ };
+}
+
+} // namespace grpc_core
+
+#endif // GRPC_SRC_CORE_LIB_PROMISE_CANCEL_CALLBACK_H
diff --git a/contrib/libs/grpc/src/core/lib/promise/detail/basic_seq.h b/contrib/libs/grpc/src/core/lib/promise/detail/basic_seq.h
index d0d393b852..2286bd4b27 100644
--- a/contrib/libs/grpc/src/core/lib/promise/detail/basic_seq.h
+++ b/contrib/libs/grpc/src/core/lib/promise/detail/basic_seq.h
@@ -167,7 +167,7 @@ auto CallNext(SeqState<Traits, I, Fs...>* state, T&& arg)
&state->next_factory, std::forward<T>(arg));
}
-// A sequence under stome traits for some set of callables Fs.
+// A sequence under some traits for some set of callables Fs.
// Fs[0] should be a promise-like object that yields a value.
// Fs[1..] should be promise-factory-like objects that take the value from the
// previous step and yield a promise. Note that most of the machinery in
diff --git a/contrib/libs/grpc/src/core/lib/promise/detail/promise_factory.h b/contrib/libs/grpc/src/core/lib/promise/detail/promise_factory.h
index 420c97ee9b..5d51a3b574 100644
--- a/contrib/libs/grpc/src/core/lib/promise/detail/promise_factory.h
+++ b/contrib/libs/grpc/src/core/lib/promise/detail/promise_factory.h
@@ -17,6 +17,7 @@
#include <grpc/support/port_platform.h>
+#include <memory>
#include <type_traits>
#include <utility>
@@ -106,6 +107,9 @@ class Curried {
private:
GPR_NO_UNIQUE_ADDRESS F f_;
GPR_NO_UNIQUE_ADDRESS Arg arg_;
+#ifndef NDEBUG
+ std::unique_ptr<int> asan_canary_ = std::make_unique<int>(0);
+#endif
};
// Promote a callable(A) -> T | Poll<T> to a PromiseFactory(A) -> Promise<T> by
diff --git a/contrib/libs/grpc/src/core/lib/promise/for_each.h b/contrib/libs/grpc/src/core/lib/promise/for_each.h
new file mode 100644
index 0000000000..91ebabcb47
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/promise/for_each.h
@@ -0,0 +1,177 @@
+// Copyright 2021 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef GRPC_SRC_CORE_LIB_PROMISE_FOR_EACH_H
+#define GRPC_SRC_CORE_LIB_PROMISE_FOR_EACH_H
+
+#include <grpc/support/port_platform.h>
+
+#include <stdint.h>
+
+#include <util/generic/string.h>
+#include <util/string/cast.h>
+#include <type_traits>
+#include <utility>
+
+#include "y_absl/status/status.h"
+#include "y_absl/strings/str_cat.h"
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/gprpp/construct_destruct.h"
+#include "src/core/lib/promise/activity.h"
+#include "src/core/lib/promise/detail/promise_factory.h"
+#include "src/core/lib/promise/poll.h"
+#include "src/core/lib/promise/trace.h"
+
+namespace grpc_core {
+
+namespace for_each_detail {
+
+// Done creates statuses for the end of the iteration. It's templated on the
+// type of the result of the ForEach loop, so that we can introduce new types
+// easily.
+template <typename T>
+struct Done;
+
+template <>
+struct Done<y_absl::Status> {
+ static y_absl::Status Make() { return y_absl::OkStatus(); }
+};
+
+template <typename Reader, typename Action>
+class ForEach {
+ private:
+ using ReaderNext = decltype(std::declval<Reader>().Next());
+ using ReaderResult =
+ typename PollTraits<decltype(std::declval<ReaderNext>()())>::Type;
+ using ReaderResultValue = typename ReaderResult::value_type;
+ using ActionFactory =
+ promise_detail::RepeatedPromiseFactory<ReaderResultValue, Action>;
+ using ActionPromise = typename ActionFactory::Promise;
+
+ public:
+ using Result =
+ typename PollTraits<decltype(std::declval<ActionPromise>()())>::Type;
+ ForEach(Reader reader, Action action)
+ : reader_(std::move(reader)), action_factory_(std::move(action)) {
+ Construct(&reader_next_, reader_.Next());
+ }
+ ~ForEach() {
+ if (reading_next_) {
+ Destruct(&reader_next_);
+ } else {
+ Destruct(&in_action_);
+ }
+ }
+
+ ForEach(const ForEach&) = delete;
+ ForEach& operator=(const ForEach&) = delete;
+ ForEach(ForEach&& other) noexcept
+ : reader_(std::move(other.reader_)),
+ action_factory_(std::move(other.action_factory_)) {
+ GPR_DEBUG_ASSERT(reading_next_);
+ GPR_DEBUG_ASSERT(other.reading_next_);
+ Construct(&reader_next_, std::move(other.reader_next_));
+ }
+ ForEach& operator=(ForEach&& other) noexcept {
+ GPR_DEBUG_ASSERT(reading_next_);
+ GPR_DEBUG_ASSERT(other.reading_next_);
+ reader_ = std::move(other.reader_);
+ action_factory_ = std::move(other.action_factory_);
+ reader_next_ = std::move(other.reader_next_);
+ return *this;
+ }
+
+ Poll<Result> operator()() {
+ if (reading_next_) return PollReaderNext();
+ return PollAction();
+ }
+
+ private:
+ struct InAction {
+ InAction(ActionPromise promise, ReaderResult result)
+ : promise(std::move(promise)), result(std::move(result)) {}
+ ActionPromise promise;
+ ReaderResult result;
+ };
+
+ TString DebugTag() {
+ return y_absl::StrCat(Activity::current()->DebugTag(), " FOR_EACH[0x",
+ reinterpret_cast<uintptr_t>(this), "]: ");
+ }
+
+ Poll<Result> PollReaderNext() {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_DEBUG, "%s PollReaderNext", DebugTag().c_str());
+ }
+ auto r = reader_next_();
+ if (auto* p = r.value_if_ready()) {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_DEBUG, "%s PollReaderNext: got has_value=%s",
+ DebugTag().c_str(), p->has_value() ? "true" : "false");
+ }
+ if (p->has_value()) {
+ Destruct(&reader_next_);
+ auto action = action_factory_.Make(std::move(**p));
+ Construct(&in_action_, std::move(action), std::move(*p));
+ reading_next_ = false;
+ return PollAction();
+ } else {
+ return Done<Result>::Make();
+ }
+ }
+ return Pending();
+ }
+
+ Poll<Result> PollAction() {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_DEBUG, "%s PollAction", DebugTag().c_str());
+ }
+ auto r = in_action_.promise();
+ if (auto* p = r.value_if_ready()) {
+ if (p->ok()) {
+ Destruct(&in_action_);
+ Construct(&reader_next_, reader_.Next());
+ reading_next_ = true;
+ return PollReaderNext();
+ } else {
+ return std::move(*p);
+ }
+ }
+ return Pending();
+ }
+
+ GPR_NO_UNIQUE_ADDRESS Reader reader_;
+ GPR_NO_UNIQUE_ADDRESS ActionFactory action_factory_;
+ bool reading_next_ = true;
+ union {
+ ReaderNext reader_next_;
+ InAction in_action_;
+ };
+};
+
+} // namespace for_each_detail
+
+/// For each item acquired by calling Reader::Next, run the promise Action.
+template <typename Reader, typename Action>
+for_each_detail::ForEach<Reader, Action> ForEach(Reader reader, Action action) {
+ return for_each_detail::ForEach<Reader, Action>(std::move(reader),
+ std::move(action));
+}
+
+} // namespace grpc_core
+
+#endif // GRPC_SRC_CORE_LIB_PROMISE_FOR_EACH_H
diff --git a/contrib/libs/grpc/src/core/lib/promise/if.h b/contrib/libs/grpc/src/core/lib/promise/if.h
index b3810fd42c..89ccbf4bba 100644
--- a/contrib/libs/grpc/src/core/lib/promise/if.h
+++ b/contrib/libs/grpc/src/core/lib/promise/if.h
@@ -17,7 +17,9 @@
#include <grpc/support/port_platform.h>
+#include <memory>
#include <type_traits>
+#include <utility>
#include "y_absl/status/statusor.h"
#include "y_absl/types/variant.h"
@@ -162,6 +164,9 @@ class If<bool, T, F> {
}
Poll<Result> operator()() {
+#ifndef NDEBUG
+ asan_canary_ = std::make_unique<int>(1 + *asan_canary_);
+#endif
if (condition_) {
return if_true_();
} else {
@@ -175,6 +180,10 @@ class If<bool, T, F> {
TruePromise if_true_;
FalsePromise if_false_;
};
+ // Make failure to destruct show up in ASAN builds.
+#ifndef NDEBUG
+ std::unique_ptr<int> asan_canary_ = std::make_unique<int>(0);
+#endif
};
} // namespace promise_detail
diff --git a/contrib/libs/grpc/src/core/lib/promise/interceptor_list.h b/contrib/libs/grpc/src/core/lib/promise/interceptor_list.h
index 8fb903d4c9..e4b3cbe331 100644
--- a/contrib/libs/grpc/src/core/lib/promise/interceptor_list.h
+++ b/contrib/libs/grpc/src/core/lib/promise/interceptor_list.h
@@ -90,6 +90,10 @@ class InterceptorList {
public:
RunPromise(size_t memory_required, Map* factory, y_absl::optional<T> value) {
if (!value.has_value() || factory == nullptr) {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_DEBUG,
+ "InterceptorList::RunPromise[%p]: create immediate", this);
+ }
is_immediately_resolved_ = true;
Construct(&result_, std::move(value));
} else {
@@ -97,10 +101,18 @@ class InterceptorList {
Construct(&async_resolution_, memory_required);
factory->MakePromise(std::move(*value), async_resolution_.space.get());
async_resolution_.current_factory = factory;
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_DEBUG,
+ "InterceptorList::RunPromise[%p]: create async; mem=%p", this,
+ async_resolution_.space.get());
+ }
}
}
~RunPromise() {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_DEBUG, "InterceptorList::RunPromise[%p]: destroy", this);
+ }
if (is_immediately_resolved_) {
Destruct(&result_);
} else {
@@ -117,6 +129,10 @@ class InterceptorList {
RunPromise(RunPromise&& other) noexcept
: is_immediately_resolved_(other.is_immediately_resolved_) {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_DEBUG, "InterceptorList::RunPromise[%p]: move from %p",
+ this, &other);
+ }
if (is_immediately_resolved_) {
Construct(&result_, std::move(other.result_));
} else {
@@ -128,7 +144,7 @@ class InterceptorList {
Poll<y_absl::optional<T>> operator()() {
if (grpc_trace_promise_primitives.enabled()) {
- gpr_log(GPR_DEBUG, "InterceptorList::RunPromise: %s",
+ gpr_log(GPR_DEBUG, "InterceptorList::RunPromise[%p]: %s", this,
DebugString().c_str());
}
if (is_immediately_resolved_) return std::move(result_);
@@ -140,7 +156,12 @@ class InterceptorList {
async_resolution_.space.get());
async_resolution_.current_factory =
async_resolution_.current_factory->next();
- if (async_resolution_.current_factory == nullptr || !p->has_value()) {
+ if (!p->has_value()) async_resolution_.current_factory = nullptr;
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_DEBUG, "InterceptorList::RunPromise[%p]: %s", this,
+ DebugString().c_str());
+ }
+ if (async_resolution_.current_factory == nullptr) {
return std::move(*p);
}
async_resolution_.current_factory->MakePromise(
diff --git a/contrib/libs/grpc/src/core/lib/promise/intra_activity_waiter.h b/contrib/libs/grpc/src/core/lib/promise/intra_activity_waiter.h
deleted file mode 100644
index 1e46621c95..0000000000
--- a/contrib/libs/grpc/src/core/lib/promise/intra_activity_waiter.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2021 gRPC authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef GRPC_SRC_CORE_LIB_PROMISE_INTRA_ACTIVITY_WAITER_H
-#define GRPC_SRC_CORE_LIB_PROMISE_INTRA_ACTIVITY_WAITER_H
-
-#include <grpc/support/port_platform.h>
-
-#include <util/generic/string.h>
-#include <util/string/cast.h>
-
-#include "src/core/lib/promise/activity.h"
-#include "src/core/lib/promise/poll.h"
-
-namespace grpc_core {
-
-// Helper type to track wakeups between objects in the same activity.
-// Can be fairly fast as no ref counting or locking needs to occur.
-class IntraActivityWaiter {
- public:
- // Register for wakeup, return Pending(). If state is not ready to proceed,
- // Promises should bottom out here.
- Pending pending() {
- waiting_ = true;
- return Pending();
- }
- // Wake the activity
- void Wake() {
- if (waiting_) {
- waiting_ = false;
- Activity::current()->ForceImmediateRepoll();
- }
- }
-
- TString DebugString() const {
- return waiting_ ? "WAITING" : "NOT_WAITING";
- }
-
- private:
- bool waiting_ = false;
-};
-
-} // namespace grpc_core
-
-#endif // GRPC_SRC_CORE_LIB_PROMISE_INTRA_ACTIVITY_WAITER_H
diff --git a/contrib/libs/grpc/src/core/lib/promise/latch.h b/contrib/libs/grpc/src/core/lib/promise/latch.h
index 19b18b5f05..882e0d63ca 100644
--- a/contrib/libs/grpc/src/core/lib/promise/latch.h
+++ b/contrib/libs/grpc/src/core/lib/promise/latch.h
@@ -19,6 +19,7 @@
#include <stdint.h>
+#include <atomic>
#include <util/generic/string.h>
#include <util/string/cast.h>
#include <type_traits>
@@ -30,7 +31,6 @@
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/promise/activity.h"
-#include "src/core/lib/promise/intra_activity_waiter.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/trace.h"
@@ -62,13 +62,14 @@ class Latch {
}
// Produce a promise to wait for a value from this latch.
+ // Moves the result out of the latch.
auto Wait() {
#ifndef NDEBUG
has_had_waiters_ = true;
#endif
return [this]() -> Poll<T> {
if (grpc_trace_promise_primitives.enabled()) {
- gpr_log(GPR_INFO, "%sPollWait %s", DebugTag().c_str(),
+ gpr_log(GPR_INFO, "%sWait %s", DebugTag().c_str(),
StateString().c_str());
}
if (has_value_) {
@@ -79,6 +80,25 @@ class Latch {
};
}
+ // Produce a promise to wait for a value from this latch.
+ // Copies the result out of the latch.
+ auto WaitAndCopy() {
+#ifndef NDEBUG
+ has_had_waiters_ = true;
+#endif
+ return [this]() -> Poll<T> {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_INFO, "%sWaitAndCopy %s", DebugTag().c_str(),
+ StateString().c_str());
+ }
+ if (has_value_) {
+ return value_;
+ } else {
+ return waiter_.pending();
+ }
+ };
+ }
+
// Set the value of the latch. Can only be called once.
void Set(T value) {
if (grpc_trace_promise_primitives.enabled()) {
@@ -90,6 +110,8 @@ class Latch {
waiter_.Wake();
}
+ bool is_set() const { return has_value_; }
+
private:
TString DebugTag() {
return y_absl::StrCat(Activity::current()->DebugTag(), " LATCH[0x",
@@ -166,7 +188,7 @@ class Latch<void> {
private:
TString DebugTag() {
- return y_absl::StrCat(Activity::current()->DebugTag(), " LATCH[0x",
+ return y_absl::StrCat(Activity::current()->DebugTag(), " LATCH(void)[0x",
reinterpret_cast<uintptr_t>(this), "]: ");
}
@@ -184,6 +206,70 @@ class Latch<void> {
IntraActivityWaiter waiter_;
};
+// A Latch that can have its value observed by outside threads, but only waited
+// upon from inside a single activity.
+template <typename T>
+class ExternallyObservableLatch;
+
+template <>
+class ExternallyObservableLatch<void> {
+ public:
+ ExternallyObservableLatch() = default;
+ ExternallyObservableLatch(const ExternallyObservableLatch&) = delete;
+ ExternallyObservableLatch& operator=(const ExternallyObservableLatch&) =
+ delete;
+
+ // Produce a promise to wait for this latch.
+ auto Wait() {
+ return [this]() -> Poll<Empty> {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_INFO, "%sPollWait %s", DebugTag().c_str(),
+ StateString().c_str());
+ }
+ if (IsSet()) {
+ return Empty{};
+ } else {
+ return waiter_.pending();
+ }
+ };
+ }
+
+ // Set the latch.
+ void Set() {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_INFO, "%sSet %s", DebugTag().c_str(), StateString().c_str());
+ }
+ is_set_.store(true, std::memory_order_relaxed);
+ waiter_.Wake();
+ }
+
+ bool IsSet() const { return is_set_.load(std::memory_order_relaxed); }
+
+ void Reset() {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_INFO, "%sReset %s", DebugTag().c_str(),
+ StateString().c_str());
+ }
+ is_set_.store(false, std::memory_order_relaxed);
+ }
+
+ private:
+ TString DebugTag() {
+ return y_absl::StrCat(Activity::current()->DebugTag(), " LATCH(void)[0x",
+ reinterpret_cast<uintptr_t>(this), "]: ");
+ }
+
+ TString StateString() {
+ return y_absl::StrCat(
+ "is_set:", is_set_.load(std::memory_order_relaxed) ? "true" : "false",
+ " waiter:", waiter_.DebugString());
+ }
+
+ // True if we have a value set, false otherwise.
+ std::atomic<bool> is_set_{false};
+ IntraActivityWaiter waiter_;
+};
+
template <typename T>
using LatchWaitPromise = decltype(std::declval<Latch<T>>().Wait());
diff --git a/contrib/libs/grpc/src/core/lib/promise/loop.h b/contrib/libs/grpc/src/core/lib/promise/loop.h
index b552a721c1..338b0aaa28 100644
--- a/contrib/libs/grpc/src/core/lib/promise/loop.h
+++ b/contrib/libs/grpc/src/core/lib/promise/loop.h
@@ -17,14 +17,13 @@
#include <grpc/support/port_platform.h>
-#include <new>
#include <type_traits>
-#include <utility>
#include "y_absl/status/status.h"
#include "y_absl/status/statusor.h"
#include "y_absl/types/variant.h"
+#include "src/core/lib/gprpp/construct_destruct.h"
#include "src/core/lib/promise/detail/promise_factory.h"
#include "src/core/lib/promise/poll.h"
@@ -83,17 +82,21 @@ class Loop {
public:
using Result = typename LoopTraits<PromiseResult>::Result;
- explicit Loop(F f) : factory_(std::move(f)), promise_(factory_.Make()) {}
- ~Loop() { promise_.~PromiseType(); }
+ explicit Loop(F f) : factory_(std::move(f)) {}
+ ~Loop() {
+ if (started_) Destruct(&promise_);
+ }
- Loop(Loop&& loop) noexcept
- : factory_(std::move(loop.factory_)),
- promise_(std::move(loop.promise_)) {}
+ Loop(Loop&& loop) noexcept : factory_(std::move(loop.factory_)) {}
Loop(const Loop& loop) = delete;
Loop& operator=(const Loop& loop) = delete;
Poll<Result> operator()() {
+ if (!started_) {
+ started_ = true;
+ Construct(&promise_, factory_.Make());
+ }
while (true) {
// Poll the inner promise.
auto promise_result = promise_();
@@ -103,8 +106,8 @@ class Loop {
// from our factory.
auto lc = LoopTraits<PromiseResult>::ToLoopCtl(*p);
if (y_absl::holds_alternative<Continue>(lc)) {
- promise_.~PromiseType();
- new (&promise_) PromiseType(factory_.Make());
+ Destruct(&promise_);
+ Construct(&promise_, factory_.Make());
continue;
}
// - otherwise there's our result... return it out.
@@ -121,6 +124,7 @@ class Loop {
GPR_NO_UNIQUE_ADDRESS union {
GPR_NO_UNIQUE_ADDRESS PromiseType promise_;
};
+ bool started_ = false;
};
} // namespace promise_detail
diff --git a/contrib/libs/grpc/src/core/lib/promise/map.h b/contrib/libs/grpc/src/core/lib/promise/map.h
index a3088d9f6f..44e19bb96a 100644
--- a/contrib/libs/grpc/src/core/lib/promise/map.h
+++ b/contrib/libs/grpc/src/core/lib/promise/map.h
@@ -39,6 +39,13 @@ class Map {
Map(Promise promise, Fn fn)
: promise_(std::move(promise)), fn_(std::move(fn)) {}
+ Map(const Map&) = delete;
+ Map& operator=(const Map&) = delete;
+ // NOLINTNEXTLINE(performance-noexcept-move-constructor): clang6 bug
+ Map(Map&& other) = default;
+ // NOLINTNEXTLINE(performance-noexcept-move-constructor): clang6 bug
+ Map& operator=(Map&& other) = default;
+
using PromiseResult = typename PromiseLike<Promise>::Result;
using Result =
RemoveCVRef<decltype(std::declval<Fn>()(std::declval<PromiseResult>()))>;
diff --git a/contrib/libs/grpc/src/core/lib/promise/party.cc b/contrib/libs/grpc/src/core/lib/promise/party.cc
new file mode 100644
index 0000000000..7ee7ef90b8
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/promise/party.cc
@@ -0,0 +1,286 @@
+// Copyright 2023 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/promise/party.h"
+
+#include <atomic>
+#include <initializer_list>
+
+#include "y_absl/base/thread_annotations.h"
+#include "y_absl/strings/str_format.h"
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/gprpp/sync.h"
+#include "src/core/lib/promise/activity.h"
+#include "src/core/lib/promise/trace.h"
+
+// #define GRPC_PARTY_MAXIMIZE_THREADS
+
+#ifdef GRPC_PARTY_MAXIMIZE_THREADS
+#include "src/core/lib/gprpp/thd.h" // IWYU pragma: keep
+#include "src/core/lib/iomgr/exec_ctx.h" // IWYU pragma: keep
+#endif
+
+namespace grpc_core {
+
+///////////////////////////////////////////////////////////////////////////////
+// PartySyncUsingAtomics
+
+GRPC_MUST_USE_RESULT bool PartySyncUsingAtomics::RefIfNonZero() {
+ auto count = state_.load(std::memory_order_relaxed);
+ do {
+ // If zero, we are done (without an increment). If not, we must do a CAS
+ // to maintain the contract: do not increment the counter if it is already
+ // zero
+ if (count == 0) {
+ return false;
+ }
+ } while (!state_.compare_exchange_weak(count, count + kOneRef,
+ std::memory_order_acq_rel,
+ std::memory_order_relaxed));
+ return true;
+}
+
+bool PartySyncUsingAtomics::UnreffedLast() {
+ uint64_t prev_state =
+ state_.fetch_or(kDestroying | kLocked, std::memory_order_acq_rel);
+ return (prev_state & kLocked) == 0;
+}
+
+bool PartySyncUsingAtomics::ScheduleWakeup(WakeupMask mask) {
+ // Or in the wakeup bit for the participant, AND the locked bit.
+ uint64_t prev_state = state_.fetch_or((mask & kWakeupMask) | kLocked,
+ std::memory_order_acq_rel);
+ // If the lock was not held now we hold it, so we need to run.
+ return ((prev_state & kLocked) == 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// PartySyncUsingMutex
+
+bool PartySyncUsingMutex::ScheduleWakeup(WakeupMask mask) {
+ MutexLock lock(&mu_);
+ wakeups_ |= mask;
+ return !std::exchange(locked_, true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Party::Handle
+
+// Weak handle to a Party.
+// Handle can persist while Party goes away.
+class Party::Handle final : public Wakeable {
+ public:
+ explicit Handle(Party* party) : party_(party) {}
+
+ // Ref the Handle (not the activity).
+ void Ref() { refs_.fetch_add(1, std::memory_order_relaxed); }
+
+ // Activity is going away... drop its reference and sever the connection back.
+ void DropActivity() Y_ABSL_LOCKS_EXCLUDED(mu_) {
+ mu_.Lock();
+ GPR_ASSERT(party_ != nullptr);
+ party_ = nullptr;
+ mu_.Unlock();
+ Unref();
+ }
+
+ // Activity needs to wake up (if it still exists!) - wake it up, and drop the
+ // ref that was kept for this handle.
+ void Wakeup(WakeupMask wakeup_mask) override Y_ABSL_LOCKS_EXCLUDED(mu_) {
+ mu_.Lock();
+ // Note that activity refcount can drop to zero, but we could win the lock
+ // against DropActivity, so we need to only increase activities refcount if
+ // it is non-zero.
+ Party* party = party_;
+ if (party != nullptr && party->RefIfNonZero()) {
+ mu_.Unlock();
+ // Activity still exists and we have a reference: wake it up, which will
+ // drop the ref.
+ party->Wakeup(wakeup_mask);
+ } else {
+ // Could not get the activity - it's either gone or going. No need to wake
+ // it up!
+ mu_.Unlock();
+ }
+ // Drop the ref to the handle (we have one ref = one wakeup semantics).
+ Unref();
+ }
+
+ void Drop(WakeupMask) override { Unref(); }
+
+ TString ActivityDebugTag(WakeupMask) const override {
+ MutexLock lock(&mu_);
+ return party_ == nullptr ? "<unknown>" : party_->DebugTag();
+ }
+
+ private:
+ // Unref the Handle (not the activity).
+ void Unref() {
+ if (1 == refs_.fetch_sub(1, std::memory_order_acq_rel)) {
+ delete this;
+ }
+ }
+
+ // Two initial refs: one for the waiter that caused instantiation, one for the
+ // party.
+ std::atomic<size_t> refs_{2};
+ mutable Mutex mu_;
+ Party* party_ Y_ABSL_GUARDED_BY(mu_);
+};
+
+Wakeable* Party::Participant::MakeNonOwningWakeable(Party* party) {
+ if (handle_ == nullptr) {
+ handle_ = new Handle(party);
+ return handle_;
+ }
+ handle_->Ref();
+ return handle_;
+}
+
+Party::Participant::~Participant() {
+ if (handle_ != nullptr) {
+ handle_->DropActivity();
+ }
+}
+
+Party::~Party() {}
+
+void Party::CancelRemainingParticipants() {
+ ScopedActivity activity(this);
+ promise_detail::Context<Arena> arena_ctx(arena_);
+ for (size_t i = 0; i < party_detail::kMaxParticipants; i++) {
+ if (auto* p =
+ participants_[i].exchange(nullptr, std::memory_order_acquire)) {
+ p->Destroy();
+ }
+ }
+}
+
+TString Party::ActivityDebugTag(WakeupMask wakeup_mask) const {
+ return y_absl::StrFormat("%s [parts:%x]", DebugTag(), wakeup_mask);
+}
+
+Waker Party::MakeOwningWaker() {
+ GPR_DEBUG_ASSERT(currently_polling_ != kNotPolling);
+ IncrementRefCount();
+ return Waker(this, 1u << currently_polling_);
+}
+
+Waker Party::MakeNonOwningWaker() {
+ GPR_DEBUG_ASSERT(currently_polling_ != kNotPolling);
+ return Waker(participants_[currently_polling_]
+ .load(std::memory_order_relaxed)
+ ->MakeNonOwningWakeable(this),
+ 1u << currently_polling_);
+}
+
+void Party::ForceImmediateRepoll(WakeupMask mask) {
+ GPR_DEBUG_ASSERT(is_current());
+ sync_.ForceImmediateRepoll(mask);
+}
+
+void Party::RunLocked() {
+ auto body = [this]() {
+ if (RunParty()) {
+ ScopedActivity activity(this);
+ PartyOver();
+ }
+ };
+#ifdef GRPC_PARTY_MAXIMIZE_THREADS
+ Thread thd(
+ "RunParty",
+ [body]() {
+ ApplicationCallbackExecCtx app_exec_ctx;
+ ExecCtx exec_ctx;
+ body();
+ },
+ nullptr, Thread::Options().set_joinable(false));
+ thd.Start();
+#else
+ body();
+#endif
+}
+
+bool Party::RunParty() {
+ ScopedActivity activity(this);
+ promise_detail::Context<Arena> arena_ctx(arena_);
+ return sync_.RunParty([this](int i) {
+ // If the participant is null, skip.
+ // This allows participants to complete whilst wakers still exist
+ // somewhere.
+ auto* participant = participants_[i].load(std::memory_order_acquire);
+ if (participant == nullptr) {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[party] wakeup %d already complete",
+ DebugTag().c_str(), i);
+ }
+ return false;
+ }
+ y_absl::string_view name;
+ if (grpc_trace_promise_primitives.enabled()) {
+ name = participant->name();
+ gpr_log(GPR_DEBUG, "%s[%s] begin job %d", DebugTag().c_str(),
+ TString(name).c_str(), i);
+ }
+ // Poll the participant.
+ currently_polling_ = i;
+ bool done = participant->Poll();
+ currently_polling_ = kNotPolling;
+ if (done) {
+ if (!name.empty()) {
+ gpr_log(GPR_DEBUG, "%s[%s] end poll and finish job %d",
+ DebugTag().c_str(), TString(name).c_str(), i);
+ }
+ participants_[i].store(nullptr, std::memory_order_relaxed);
+ } else if (!name.empty()) {
+ gpr_log(GPR_DEBUG, "%s[%s] end poll", DebugTag().c_str(),
+ TString(name).c_str());
+ }
+ return done;
+ });
+}
+
+void Party::AddParticipants(Participant** participants, size_t count) {
+ bool run_party = sync_.AddParticipantsAndRef(count, [this, participants,
+ count](size_t* slots) {
+ for (size_t i = 0; i < count; i++) {
+ participants_[slots[i]].store(participants[i], std::memory_order_release);
+ }
+ });
+ if (run_party) RunLocked();
+ Unref();
+}
+
+void Party::ScheduleWakeup(WakeupMask mask) {
+ if (sync_.ScheduleWakeup(mask)) RunLocked();
+}
+
+void Party::Wakeup(WakeupMask wakeup_mask) {
+ ScheduleWakeup(wakeup_mask);
+ Unref();
+}
+
+void Party::Drop(WakeupMask) { Unref(); }
+
+void Party::PartyIsOver() {
+ ScopedActivity activity(this);
+ PartyOver();
+}
+
+} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/promise/party.h b/contrib/libs/grpc/src/core/lib/promise/party.h
new file mode 100644
index 0000000000..48be20ebfe
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/promise/party.h
@@ -0,0 +1,500 @@
+// Copyright 2023 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef GRPC_SRC_CORE_LIB_PROMISE_PARTY_H
+#define GRPC_SRC_CORE_LIB_PROMISE_PARTY_H
+
+#include <grpc/support/port_platform.h>
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+#include <util/generic/string.h>
+#include <util/string/cast.h>
+#include <utility>
+
+#include "y_absl/base/thread_annotations.h"
+#include "y_absl/strings/string_view.h"
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/gprpp/construct_destruct.h"
+#include "src/core/lib/gprpp/crash.h"
+#include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/gprpp/sync.h"
+#include "src/core/lib/promise/activity.h"
+#include "src/core/lib/promise/context.h"
+#include "src/core/lib/promise/detail/promise_factory.h"
+#include "src/core/lib/resource_quota/arena.h"
+
+// Two implementations of party synchronization are provided: one using a single
+// atomic, the other using a mutex and a set of state variables.
+// Originally the atomic implementation was implemented, but we found some race
+// conditions on Arm that were not reported by our default TSAN implementation.
+// The mutex implementation was added to see if it would fix the problem, and
+// it did. Later we found the race condition, so there's no known reason to use
+// the mutex version - however we keep it around as a just in case measure.
+// There's a thought of fuzzing the two implementations against each other as
+// a correctness check of both, but that's not implemented yet.
+
+#define GRPC_PARTY_SYNC_USING_ATOMICS
+// #define GRPC_PARTY_SYNC_USING_MUTEX
+
+#if defined(GRPC_PARTY_SYNC_USING_ATOMICS) + \
+ defined(GRPC_PARTY_SYNC_USING_MUTEX) != \
+ 1
+#error Must define a party sync mechanism
+#endif
+
+namespace grpc_core {
+
+namespace party_detail {
+
+// Number of bits reserved for wakeups gives us the maximum number of
+// participants.
+static constexpr size_t kMaxParticipants = 16;
+
+} // namespace party_detail
+
+class PartySyncUsingAtomics {
+ public:
+ explicit PartySyncUsingAtomics(size_t initial_refs)
+ : state_(kOneRef * initial_refs) {}
+
+ void IncrementRefCount() {
+ state_.fetch_add(kOneRef, std::memory_order_relaxed);
+ }
+ GRPC_MUST_USE_RESULT bool RefIfNonZero();
+ // Returns true if the ref count is now zero and the caller should call
+ // PartyOver
+ GRPC_MUST_USE_RESULT bool Unref() {
+ uint64_t prev_state = state_.fetch_sub(kOneRef, std::memory_order_acq_rel);
+ if ((prev_state & kRefMask) == kOneRef) {
+ return UnreffedLast();
+ }
+ return false;
+ }
+ void ForceImmediateRepoll(WakeupMask mask) {
+ // Or in the bit for the currently polling participant.
+ // Will be grabbed next round to force a repoll of this promise.
+ state_.fetch_or(mask, std::memory_order_relaxed);
+ }
+
+ // Run the update loop: poll_one_participant is called with an integral index
+ // for the participant that should be polled. It should return true if the
+ // participant completed and should be removed from the allocated set.
+ template <typename F>
+ GRPC_MUST_USE_RESULT bool RunParty(F poll_one_participant) {
+ uint64_t prev_state;
+ do {
+ // Grab the current state, and clear the wakeup bits & add flag.
+ prev_state = state_.fetch_and(kRefMask | kLocked | kAllocatedMask,
+ std::memory_order_acquire);
+ GPR_ASSERT(prev_state & kLocked);
+ if (prev_state & kDestroying) return true;
+ // From the previous state, extract which participants we're to wakeup.
+ uint64_t wakeups = prev_state & kWakeupMask;
+ // Now update prev_state to be what we want the CAS to see below.
+ prev_state &= kRefMask | kLocked | kAllocatedMask;
+ // For each wakeup bit...
+ for (size_t i = 0; wakeups != 0; i++, wakeups >>= 1) {
+ // If the bit is not set, skip.
+ if ((wakeups & 1) == 0) continue;
+ if (poll_one_participant(i)) {
+ const uint64_t allocated_bit = (1u << i << kAllocatedShift);
+ prev_state &= ~allocated_bit;
+ state_.fetch_and(~allocated_bit, std::memory_order_release);
+ }
+ }
+ // Try to CAS the state we expected to have (with no wakeups or adds)
+ // back to unlocked (by masking in only the ref mask - sans locked bit).
+ // If this succeeds then no wakeups were added, no adds were added, and we
+ // have successfully unlocked.
+ // Otherwise, we need to loop again.
+ // Note that if an owning waker is created or the weak cas spuriously
+ // fails we will also loop again, but in that case see no wakeups or adds
+ // and so will get back here fairly quickly.
+ // TODO(ctiller): consider mitigations for the accidental wakeup on owning
+ // waker creation case -- I currently expect this will be more expensive
+ // than this quick loop.
+ } while (!state_.compare_exchange_weak(
+ prev_state, (prev_state & (kRefMask | kAllocatedMask)),
+ std::memory_order_acq_rel, std::memory_order_acquire));
+ return false;
+ }
+
+ // Add new participants to the party. Returns true if the caller should run
+ // the party. store is called with an array of indices of the new
+ // participants. Adds a ref that should be dropped by the caller after
+ // RunParty has been called (if that was required).
+ template <typename F>
+ GRPC_MUST_USE_RESULT bool AddParticipantsAndRef(size_t count, F store) {
+ uint64_t state = state_.load(std::memory_order_acquire);
+ uint64_t allocated;
+
+ size_t slots[party_detail::kMaxParticipants];
+
+ // Find slots for each new participant, ordering them from lowest available
+ // slot upwards to ensure the same poll ordering as presentation ordering to
+ // this function.
+ WakeupMask wakeup_mask;
+ do {
+ wakeup_mask = 0;
+ allocated = (state & kAllocatedMask) >> kAllocatedShift;
+ size_t n = 0;
+ for (size_t bit = 0; n < count && bit < party_detail::kMaxParticipants;
+ bit++) {
+ if (allocated & (1 << bit)) continue;
+ wakeup_mask |= (1 << bit);
+ slots[n++] = bit;
+ allocated |= 1 << bit;
+ }
+ GPR_ASSERT(n == count);
+ // Try to allocate this slot and take a ref (atomically).
+ // Ref needs to be taken because once we store the participant it could be
+ // spuriously woken up and unref the party.
+ } while (!state_.compare_exchange_weak(
+ state, (state | (allocated << kAllocatedShift)) + kOneRef,
+ std::memory_order_acq_rel, std::memory_order_acquire));
+
+ store(slots);
+
+ // Now we need to wake up the party.
+ state = state_.fetch_or(wakeup_mask | kLocked, std::memory_order_release);
+
+ // If the party was already locked, we're done.
+ return ((state & kLocked) == 0);
+ }
+
+ // Schedule a wakeup for the given participant.
+ // Returns true if the caller should run the party.
+ GRPC_MUST_USE_RESULT bool ScheduleWakeup(WakeupMask mask);
+
+ private:
+ bool UnreffedLast();
+
+ // State bits:
+ // The atomic state_ field is composed of the following:
+ // - 24 bits for ref counts
+ // 1 is owned by the party prior to Orphan()
+ // All others are owned by owning wakers
+ // - 1 bit to indicate whether the party is locked
+ // The first thread to set this owns the party until it is unlocked
+ // That thread will run the main loop until no further work needs to
+ // be done.
+ // - 1 bit to indicate whether there are participants waiting to be
+ // added
+ // - 16 bits, one per participant, indicating which participants have
+ // been
+ // woken up and should be polled next time the main loop runs.
+
+ // clang-format off
+ // Bits used to store 16 bits of wakeups
+ static constexpr uint64_t kWakeupMask = 0x0000'0000'0000'ffff;
+ // Bits used to store 16 bits of allocated participant slots.
+ static constexpr uint64_t kAllocatedMask = 0x0000'0000'ffff'0000;
+ // Bit indicating destruction has begun (refs went to zero)
+ static constexpr uint64_t kDestroying = 0x0000'0001'0000'0000;
+ // Bit indicating locked or not
+ static constexpr uint64_t kLocked = 0x0000'0008'0000'0000;
+ // Bits used to store 24 bits of ref counts
+ static constexpr uint64_t kRefMask = 0xffff'ff00'0000'0000;
+ // clang-format on
+
+ // Shift to get from a participant mask to an allocated mask.
+ static constexpr size_t kAllocatedShift = 16;
+ // How far to shift to get the refcount
+ static constexpr size_t kRefShift = 40;
+ // One ref count
+ static constexpr uint64_t kOneRef = 1ull << kRefShift;
+
+ std::atomic<uint64_t> state_;
+};
+
+class PartySyncUsingMutex {
+ public:
+ explicit PartySyncUsingMutex(size_t initial_refs) : refs_(initial_refs) {}
+
+ void IncrementRefCount() { refs_.Ref(); }
+ GRPC_MUST_USE_RESULT bool RefIfNonZero() { return refs_.RefIfNonZero(); }
+ GRPC_MUST_USE_RESULT bool Unref() { return refs_.Unref(); }
+ void ForceImmediateRepoll(WakeupMask mask) {
+ MutexLock lock(&mu_);
+ wakeups_ |= mask;
+ }
+ template <typename F>
+ GRPC_MUST_USE_RESULT bool RunParty(F poll_one_participant) {
+ WakeupMask freed = 0;
+ while (true) {
+ ReleasableMutexLock lock(&mu_);
+ GPR_ASSERT(locked_);
+ allocated_ &= ~std::exchange(freed, 0);
+ auto wakeup = std::exchange(wakeups_, 0);
+ if (wakeup == 0) {
+ locked_ = false;
+ return false;
+ }
+ lock.Release();
+ for (size_t i = 0; wakeup != 0; i++, wakeup >>= 1) {
+ if ((wakeup & 1) == 0) continue;
+ if (poll_one_participant(i)) freed |= 1 << i;
+ }
+ }
+ }
+
+ template <typename F>
+ GRPC_MUST_USE_RESULT bool AddParticipantsAndRef(size_t count, F store) {
+ IncrementRefCount();
+ MutexLock lock(&mu_);
+ size_t slots[party_detail::kMaxParticipants];
+ WakeupMask wakeup_mask = 0;
+ size_t n = 0;
+ for (size_t bit = 0; n < count && bit < party_detail::kMaxParticipants;
+ bit++) {
+ if (allocated_ & (1 << bit)) continue;
+ slots[n++] = bit;
+ wakeup_mask |= 1 << bit;
+ allocated_ |= 1 << bit;
+ }
+ GPR_ASSERT(n == count);
+ store(slots);
+ wakeups_ |= wakeup_mask;
+ return !std::exchange(locked_, true);
+ }
+
+ GRPC_MUST_USE_RESULT bool ScheduleWakeup(WakeupMask mask);
+
+ private:
+ RefCount refs_;
+ Mutex mu_;
+ WakeupMask allocated_ Y_ABSL_GUARDED_BY(mu_) = 0;
+ WakeupMask wakeups_ Y_ABSL_GUARDED_BY(mu_) = 0;
+ bool locked_ Y_ABSL_GUARDED_BY(mu_) = false;
+};
+
+// A Party is an Activity with multiple participant promises.
+class Party : public Activity, private Wakeable {
+ private:
+ // Non-owning wakeup handle.
+ class Handle;
+
+ // One participant in the party.
+ class Participant {
+ public:
+ explicit Participant(y_absl::string_view name) : name_(name) {}
+ // Poll the participant. Return true if complete.
+ // Participant should take care of its own deallocation in this case.
+ virtual bool Poll() = 0;
+
+ // Destroy the participant before finishing.
+ virtual void Destroy() = 0;
+
+ // Return a Handle instance for this participant.
+ Wakeable* MakeNonOwningWakeable(Party* party);
+
+ y_absl::string_view name() const { return name_; }
+
+ protected:
+ ~Participant();
+
+ private:
+ Handle* handle_ = nullptr;
+ y_absl::string_view name_;
+ };
+
+ public:
+ Party(const Party&) = delete;
+ Party& operator=(const Party&) = delete;
+
+ // Spawn one promise into the party.
+ // The promise will be polled until it is resolved, or until the party is shut
+ // down.
+ // The on_complete callback will be called with the result of the promise if
+ // it completes.
+ // A maximum of sixteen promises can be spawned onto a party.
+ template <typename Factory, typename OnComplete>
+ void Spawn(y_absl::string_view name, Factory promise_factory,
+ OnComplete on_complete);
+
+ void Orphan() final { Crash("unused"); }
+
+ // Activity implementation: not allowed to be overridden by derived types.
+ void ForceImmediateRepoll(WakeupMask mask) final;
+ WakeupMask CurrentParticipant() const final {
+ GPR_DEBUG_ASSERT(currently_polling_ != kNotPolling);
+ return 1u << currently_polling_;
+ }
+ Waker MakeOwningWaker() final;
+ Waker MakeNonOwningWaker() final;
+ TString ActivityDebugTag(WakeupMask wakeup_mask) const final;
+
+ void IncrementRefCount() { sync_.IncrementRefCount(); }
+ void Unref() {
+ if (sync_.Unref()) PartyIsOver();
+ }
+ RefCountedPtr<Party> Ref() {
+ IncrementRefCount();
+ return RefCountedPtr<Party>(this);
+ }
+
+ Arena* arena() const { return arena_; }
+
+ class BulkSpawner {
+ public:
+ explicit BulkSpawner(Party* party) : party_(party) {}
+ ~BulkSpawner() {
+ party_->AddParticipants(participants_, num_participants_);
+ }
+
+ template <typename Factory, typename OnComplete>
+ void Spawn(y_absl::string_view name, Factory promise_factory,
+ OnComplete on_complete);
+
+ private:
+ Party* const party_;
+ size_t num_participants_ = 0;
+ Participant* participants_[party_detail::kMaxParticipants];
+ };
+
+ protected:
+ explicit Party(Arena* arena, size_t initial_refs)
+ : sync_(initial_refs), arena_(arena) {}
+ ~Party() override;
+
+ // Main run loop. Must be locked.
+ // Polls participants and drains the add queue until there is no work left to
+ // be done.
+ // Derived types will likely want to override this to set up their
+ // contexts before polling.
+ // Should not be called by derived types except as a tail call to the base
+ // class RunParty when overriding this method to add custom context.
+ // Returns true if the party is over.
+ virtual bool RunParty() GRPC_MUST_USE_RESULT;
+
+ bool RefIfNonZero() { return sync_.RefIfNonZero(); }
+
+ // Destroy any remaining participants.
+ // Should be called by derived types in response to PartyOver.
+ // Needs to have normal context setup before calling.
+ void CancelRemainingParticipants();
+
+ private:
+ // Concrete implementation of a participant for some promise & oncomplete
+ // type.
+ template <typename SuppliedFactory, typename OnComplete>
+ class ParticipantImpl final : public Participant {
+ using Factory = promise_detail::OncePromiseFactory<void, SuppliedFactory>;
+ using Promise = typename Factory::Promise;
+
+ public:
+ ParticipantImpl(y_absl::string_view name, SuppliedFactory promise_factory,
+ OnComplete on_complete)
+ : Participant(name), on_complete_(std::move(on_complete)) {
+ Construct(&factory_, std::move(promise_factory));
+ }
+ ~ParticipantImpl() {
+ if (!started_) {
+ Destruct(&factory_);
+ } else {
+ Destruct(&promise_);
+ }
+ }
+
+ bool Poll() override {
+ if (!started_) {
+ auto p = factory_.Make();
+ Destruct(&factory_);
+ Construct(&promise_, std::move(p));
+ started_ = true;
+ }
+ auto p = promise_();
+ if (auto* r = p.value_if_ready()) {
+ on_complete_(std::move(*r));
+ GetContext<Arena>()->DeletePooled(this);
+ return true;
+ }
+ return false;
+ }
+
+ void Destroy() override { GetContext<Arena>()->DeletePooled(this); }
+
+ private:
+ union {
+ GPR_NO_UNIQUE_ADDRESS Factory factory_;
+ GPR_NO_UNIQUE_ADDRESS Promise promise_;
+ };
+ GPR_NO_UNIQUE_ADDRESS OnComplete on_complete_;
+ bool started_ = false;
+ };
+
+ // Notification that the party has finished and this instance can be deleted.
+ // Derived types should arrange to call CancelRemainingParticipants during
+ // this sequence.
+ virtual void PartyOver() = 0;
+
+ // Run the locked part of the party until it is unlocked.
+ void RunLocked();
+ // Called in response to Unref() hitting zero - ultimately calls PartyOver,
+ // but needs to set some stuff up.
+ // Here so it gets compiled out of line.
+ void PartyIsOver();
+
+ // Wakeable implementation
+ void Wakeup(WakeupMask wakeup_mask) final;
+ void Drop(WakeupMask wakeup_mask) final;
+
+ // Organize to wake up some participants.
+ void ScheduleWakeup(WakeupMask mask);
+ // Add a participant (backs Spawn, after type erasure to ParticipantFactory).
+ void AddParticipants(Participant** participant, size_t count);
+
+ // Sentinal value for currently_polling_ when no participant is being polled.
+ static constexpr uint8_t kNotPolling = 255;
+
+#ifdef GRPC_PARTY_SYNC_USING_ATOMICS
+ PartySyncUsingAtomics sync_;
+#elif defined(GRPC_PARTY_SYNC_USING_MUTEX)
+ PartySyncUsingMutex sync_;
+#else
+#error No synchronization method defined
+#endif
+
+ Arena* const arena_;
+ uint8_t currently_polling_ = kNotPolling;
+ // All current participants, using a tagged format.
+ // If the lower bit is unset, then this is a Participant*.
+ // If the lower bit is set, then this is a ParticipantFactory*.
+ std::atomic<Participant*> participants_[party_detail::kMaxParticipants] = {};
+};
+
+template <typename Factory, typename OnComplete>
+void Party::BulkSpawner::Spawn(y_absl::string_view name, Factory promise_factory,
+ OnComplete on_complete) {
+ participants_[num_participants_++] =
+ party_->arena_->NewPooled<ParticipantImpl<Factory, OnComplete>>(
+ name, std::move(promise_factory), std::move(on_complete));
+}
+
+template <typename Factory, typename OnComplete>
+void Party::Spawn(y_absl::string_view name, Factory promise_factory,
+ OnComplete on_complete) {
+ BulkSpawner(this).Spawn(name, std::move(promise_factory),
+ std::move(on_complete));
+}
+
+} // namespace grpc_core
+
+#endif // GRPC_SRC_CORE_LIB_PROMISE_PARTY_H
diff --git a/contrib/libs/grpc/src/core/lib/promise/pipe.h b/contrib/libs/grpc/src/core/lib/promise/pipe.h
index 2a7bc1a0a7..dc1b197e77 100644
--- a/contrib/libs/grpc/src/core/lib/promise/pipe.h
+++ b/contrib/libs/grpc/src/core/lib/promise/pipe.h
@@ -26,7 +26,6 @@
#include <type_traits>
#include <utility>
-#include "y_absl/base/attributes.h"
#include "y_absl/strings/str_cat.h"
#include "y_absl/types/optional.h"
#include "y_absl/types/variant.h"
@@ -40,7 +39,6 @@
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/if.h"
#include "src/core/lib/promise/interceptor_list.h"
-#include "src/core/lib/promise/intra_activity_waiter.h"
#include "src/core/lib/promise/map.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/seq.h"
@@ -161,9 +159,11 @@ class Center : public InterceptorList<T> {
case ValueState::kClosed:
case ValueState::kReadyClosed:
case ValueState::kCancelled:
+ case ValueState::kWaitingForAckAndClosed:
return false;
case ValueState::kReady:
case ValueState::kAcked:
+ case ValueState::kWaitingForAck:
return on_empty_.pending();
case ValueState::kEmpty:
value_state_ = ValueState::kReady;
@@ -181,11 +181,14 @@ class Center : public InterceptorList<T> {
GPR_DEBUG_ASSERT(refs_ != 0);
switch (value_state_) {
case ValueState::kClosed:
- case ValueState::kReadyClosed:
+ return true;
case ValueState::kCancelled:
return false;
case ValueState::kReady:
+ case ValueState::kReadyClosed:
case ValueState::kEmpty:
+ case ValueState::kWaitingForAck:
+ case ValueState::kWaitingForAckAndClosed:
return on_empty_.pending();
case ValueState::kAcked:
value_state_ = ValueState::kEmpty;
@@ -207,12 +210,14 @@ class Center : public InterceptorList<T> {
switch (value_state_) {
case ValueState::kEmpty:
case ValueState::kAcked:
+ case ValueState::kWaitingForAck:
+ case ValueState::kWaitingForAckAndClosed:
return on_full_.pending();
case ValueState::kReadyClosed:
- this->ResetInterceptorList();
- value_state_ = ValueState::kClosed;
- Y_ABSL_FALLTHROUGH_INTENDED;
+ value_state_ = ValueState::kWaitingForAckAndClosed;
+ return std::move(value_);
case ValueState::kReady:
+ value_state_ = ValueState::kWaitingForAck;
return std::move(value_);
case ValueState::kClosed:
case ValueState::kCancelled:
@@ -221,18 +226,89 @@ class Center : public InterceptorList<T> {
GPR_UNREACHABLE_CODE(return y_absl::nullopt);
}
+ // Check if the pipe is closed for sending (if there is a value still queued
+ // but the pipe is closed, reports closed).
+ Poll<bool> PollClosedForSender() {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_INFO, "%s", DebugOpString("PollClosedForSender").c_str());
+ }
+ GPR_DEBUG_ASSERT(refs_ != 0);
+ switch (value_state_) {
+ case ValueState::kEmpty:
+ case ValueState::kAcked:
+ case ValueState::kReady:
+ case ValueState::kWaitingForAck:
+ return on_closed_.pending();
+ case ValueState::kWaitingForAckAndClosed:
+ case ValueState::kReadyClosed:
+ case ValueState::kClosed:
+ return false;
+ case ValueState::kCancelled:
+ return true;
+ }
+ GPR_UNREACHABLE_CODE(return true);
+ }
+
+ // Check if the pipe is closed for receiving (if there is a value still queued
+ // but the pipe is closed, reports open).
+ Poll<bool> PollClosedForReceiver() {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_INFO, "%s", DebugOpString("PollClosedForReceiver").c_str());
+ }
+ GPR_DEBUG_ASSERT(refs_ != 0);
+ switch (value_state_) {
+ case ValueState::kEmpty:
+ case ValueState::kAcked:
+ case ValueState::kReady:
+ case ValueState::kReadyClosed:
+ case ValueState::kWaitingForAck:
+ case ValueState::kWaitingForAckAndClosed:
+ return on_closed_.pending();
+ case ValueState::kClosed:
+ return false;
+ case ValueState::kCancelled:
+ return true;
+ }
+ GPR_UNREACHABLE_CODE(return true);
+ }
+
+ Poll<Empty> PollEmpty() {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_INFO, "%s", DebugOpString("PollEmpty").c_str());
+ }
+ GPR_DEBUG_ASSERT(refs_ != 0);
+ switch (value_state_) {
+ case ValueState::kReady:
+ case ValueState::kReadyClosed:
+ return on_empty_.pending();
+ case ValueState::kWaitingForAck:
+ case ValueState::kWaitingForAckAndClosed:
+ case ValueState::kAcked:
+ case ValueState::kEmpty:
+ case ValueState::kClosed:
+ case ValueState::kCancelled:
+ return Empty{};
+ }
+ GPR_UNREACHABLE_CODE(return Empty{});
+ }
+
void AckNext() {
if (grpc_trace_promise_primitives.enabled()) {
gpr_log(GPR_INFO, "%s", DebugOpString("AckNext").c_str());
}
switch (value_state_) {
case ValueState::kReady:
+ case ValueState::kWaitingForAck:
value_state_ = ValueState::kAcked;
on_empty_.Wake();
break;
case ValueState::kReadyClosed:
+ case ValueState::kWaitingForAckAndClosed:
this->ResetInterceptorList();
value_state_ = ValueState::kClosed;
+ on_closed_.Wake();
+ on_empty_.Wake();
+ on_full_.Wake();
break;
case ValueState::kClosed:
case ValueState::kCancelled:
@@ -252,14 +328,22 @@ class Center : public InterceptorList<T> {
case ValueState::kAcked:
this->ResetInterceptorList();
value_state_ = ValueState::kClosed;
+ on_empty_.Wake();
on_full_.Wake();
+ on_closed_.Wake();
break;
case ValueState::kReady:
value_state_ = ValueState::kReadyClosed;
+ on_closed_.Wake();
+ break;
+ case ValueState::kWaitingForAck:
+ value_state_ = ValueState::kWaitingForAckAndClosed;
+ on_closed_.Wake();
break;
case ValueState::kReadyClosed:
case ValueState::kClosed:
case ValueState::kCancelled:
+ case ValueState::kWaitingForAckAndClosed:
break;
}
}
@@ -273,13 +357,15 @@ class Center : public InterceptorList<T> {
case ValueState::kAcked:
case ValueState::kReady:
case ValueState::kReadyClosed:
+ case ValueState::kWaitingForAck:
+ case ValueState::kWaitingForAckAndClosed:
this->ResetInterceptorList();
value_state_ = ValueState::kCancelled;
+ on_empty_.Wake();
on_full_.Wake();
+ on_closed_.Wake();
break;
case ValueState::kClosed:
- value_state_ = ValueState::kCancelled;
- break;
case ValueState::kCancelled:
break;
}
@@ -306,6 +392,8 @@ class Center : public InterceptorList<T> {
kEmpty,
// Value has been pushed but not acked, it's possible to receive.
kReady,
+ // Value has been read and not acked, both send/receive blocked until ack.
+ kWaitingForAck,
// Value has been received and acked, we can unblock senders and transition
// to empty.
kAcked,
@@ -314,6 +402,9 @@ class Center : public InterceptorList<T> {
// Pipe is closed successfully, no more values can be sent
// (but one value is queued and ready to be received)
kReadyClosed,
+ // Pipe is closed successfully, no more values can be sent
+ // (but one value is queued and waiting to be acked)
+ kWaitingForAckAndClosed,
// Pipe is closed unsuccessfully, no more values can be sent
kCancelled,
};
@@ -322,7 +413,8 @@ class Center : public InterceptorList<T> {
return y_absl::StrCat(DebugTag(), op, " refs=", refs_,
" value_state=", ValueStateName(value_state_),
" on_empty=", on_empty_.DebugString().c_str(),
- " on_full=", on_full_.DebugString().c_str());
+ " on_full=", on_full_.DebugString().c_str(),
+ " on_closed=", on_closed_.DebugString().c_str());
}
static const char* ValueStateName(ValueState state) {
@@ -337,6 +429,10 @@ class Center : public InterceptorList<T> {
return "Closed";
case ValueState::kReadyClosed:
return "ReadyClosed";
+ case ValueState::kWaitingForAck:
+ return "WaitingForAck";
+ case ValueState::kWaitingForAckAndClosed:
+ return "WaitingForAckAndClosed";
case ValueState::kCancelled:
return "Cancelled";
}
@@ -350,6 +446,7 @@ class Center : public InterceptorList<T> {
ValueState value_state_;
IntraActivityWaiter on_empty_;
IntraActivityWaiter on_full_;
+ IntraActivityWaiter on_closed_;
// Make failure to destruct show up in ASAN builds.
#ifndef NDEBUG
@@ -389,11 +486,25 @@ class PipeSender {
// receiver is either closed or able to receive another message.
PushType Push(T value);
+ // Return a promise that resolves when the receiver is closed.
+ // The resolved value is a bool - true if the pipe was cancelled, false if it
+ // was closed successfully.
+ // Checks closed from the senders perspective: that is, if there is a value in
+ // the pipe but the pipe is closed, reports closed.
+ auto AwaitClosed() {
+ return [center = center_]() { return center->PollClosedForSender(); };
+ }
+
+ // Interject PromiseFactory f into the pipeline.
+ // f will be called with the current value traversing the pipe, and should
+ // return a value to replace it with.
+ // Interjects at the Push end of the pipe.
template <typename Fn>
void InterceptAndMap(Fn f, DebugLocation from = {}) {
center_->PrependMap(std::move(f), from);
}
+ // Per above, but calls cleanup_fn when the pipe is closed.
template <typename Fn, typename OnHalfClose>
void InterceptAndMap(Fn f, OnHalfClose cleanup_fn, DebugLocation from = {}) {
center_->PrependMapWithCleanup(std::move(f), std::move(cleanup_fn), from);
@@ -410,6 +521,31 @@ class PipeSender {
#endif
};
+template <typename T>
+class PipeReceiver;
+
+namespace pipe_detail {
+
+// Implementation of PipeReceiver::Next promise.
+template <typename T>
+class Next {
+ public:
+ Next(const Next&) = delete;
+ Next& operator=(const Next&) = delete;
+ Next(Next&& other) noexcept = default;
+ Next& operator=(Next&& other) noexcept = default;
+
+ Poll<y_absl::optional<T>> operator()() { return center_->Next(); }
+
+ private:
+ friend class PipeReceiver<T>;
+ explicit Next(RefCountedPtr<Center<T>> center) : center_(std::move(center)) {}
+
+ RefCountedPtr<Center<T>> center_;
+};
+
+} // namespace pipe_detail
+
// Receive end of a Pipe.
template <typename T>
class PipeReceiver {
@@ -419,7 +555,7 @@ class PipeReceiver {
PipeReceiver(PipeReceiver&& other) noexcept = default;
PipeReceiver& operator=(PipeReceiver&& other) noexcept = default;
~PipeReceiver() {
- if (center_ != nullptr) center_->MarkClosed();
+ if (center_ != nullptr) center_->MarkCancelled();
}
void Swap(PipeReceiver<T>* other) { std::swap(center_, other->center_); }
@@ -429,13 +565,55 @@ class PipeReceiver {
// message was received, or no value if the other end of the pipe was closed.
// Blocks the promise until the receiver is either closed or a message is
// available.
- auto Next();
+ auto Next() {
+ return Seq(
+ pipe_detail::Next<T>(center_->Ref()),
+ [center = center_->Ref()](y_absl::optional<T> value) {
+ bool open = value.has_value();
+ bool cancelled = center->cancelled();
+ return If(
+ open,
+ [center = std::move(center), value = std::move(value)]() mutable {
+ auto run = center->Run(std::move(value));
+ return Map(std::move(run),
+ [center = std::move(center)](
+ y_absl::optional<T> value) mutable {
+ if (value.has_value()) {
+ center->value() = std::move(*value);
+ return NextResult<T>(std::move(center));
+ } else {
+ center->MarkCancelled();
+ return NextResult<T>(true);
+ }
+ });
+ },
+ [cancelled]() { return NextResult<T>(cancelled); });
+ });
+ }
+ // Return a promise that resolves when the receiver is closed.
+ // The resolved value is a bool - true if the pipe was cancelled, false if it
+ // was closed successfully.
+ // Checks closed from the receivers perspective: that is, if there is a value
+ // in the pipe but the pipe is closed, reports open until that value is read.
+ auto AwaitClosed() {
+ return [center = center_]() { return center->PollClosedForReceiver(); };
+ }
+
+ auto AwaitEmpty() {
+ return [center = center_]() { return center->PollEmpty(); };
+ }
+
+ // Interject PromiseFactory f into the pipeline.
+ // f will be called with the current value traversing the pipe, and should
+ // return a value to replace it with.
+ // Interjects at the Next end of the pipe.
template <typename Fn>
void InterceptAndMap(Fn f, DebugLocation from = {}) {
center_->AppendMap(std::move(f), from);
}
+ // Per above, but calls cleanup_fn when the pipe is closed.
template <typename Fn, typename OnHalfClose>
void InterceptAndMapWithHalfClose(Fn f, OnHalfClose cleanup_fn,
DebugLocation from = {}) {
@@ -460,12 +638,19 @@ template <typename T>
class Push {
public:
Push(const Push&) = delete;
+
Push& operator=(const Push&) = delete;
Push(Push&& other) noexcept = default;
Push& operator=(Push&& other) noexcept = default;
Poll<bool> operator()() {
- if (center_ == nullptr) return false;
+ if (center_ == nullptr) {
+ if (grpc_trace_promise_primitives.enabled()) {
+ gpr_log(GPR_DEBUG, "%s Pipe push has a null center",
+ Activity::current()->DebugTag().c_str());
+ }
+ return false;
+ }
if (auto* p = y_absl::get_if<T>(&state_)) {
auto r = center_->Push(p);
if (auto* ok = r.value_if_ready()) {
@@ -490,24 +675,6 @@ class Push {
y_absl::variant<T, AwaitingAck> state_;
};
-// Implementation of PipeReceiver::Next promise.
-template <typename T>
-class Next {
- public:
- Next(const Next&) = delete;
- Next& operator=(const Next&) = delete;
- Next(Next&& other) noexcept = default;
- Next& operator=(Next&& other) noexcept = default;
-
- Poll<y_absl::optional<T>> operator()() { return center_->Next(); }
-
- private:
- friend class PipeReceiver<T>;
- explicit Next(RefCountedPtr<Center<T>> center) : center_(std::move(center)) {}
-
- RefCountedPtr<Center<T>> center_;
-};
-
} // namespace pipe_detail
template <typename T>
@@ -517,33 +684,6 @@ pipe_detail::Push<T> PipeSender<T>::Push(T value) {
}
template <typename T>
-auto PipeReceiver<T>::Next() {
- return Seq(
- pipe_detail::Next<T>(center_->Ref()),
- [center = center_->Ref()](y_absl::optional<T> value) {
- bool open = value.has_value();
- bool cancelled = center->cancelled();
- return If(
- open,
- [center = std::move(center), value = std::move(value)]() mutable {
- auto run_interceptors = center->Run(std::move(value));
- return Map(std::move(run_interceptors),
- [center = std::move(center)](
- y_absl::optional<T> value) mutable {
- if (value.has_value()) {
- center->value() = std::move(*value);
- return NextResult<T>(std::move(center));
- } else {
- center->MarkCancelled();
- return NextResult<T>(true);
- }
- });
- },
- [cancelled]() { return NextResult<T>(cancelled); });
- });
-}
-
-template <typename T>
using PipeReceiverNextType = decltype(std::declval<PipeReceiver<T>>().Next());
template <typename T>
diff --git a/contrib/libs/grpc/src/core/lib/promise/poll.h b/contrib/libs/grpc/src/core/lib/promise/poll.h
index 3e33123eb3..f877060806 100644
--- a/contrib/libs/grpc/src/core/lib/promise/poll.h
+++ b/contrib/libs/grpc/src/core/lib/promise/poll.h
@@ -89,6 +89,8 @@ class Poll {
Poll(U value) : ready_(true) {
Construct(&value_, std::move(value));
}
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ Poll(T&& value) : ready_(true) { Construct(&value_, std::forward<T>(value)); }
~Poll() {
if (ready_) Destruct(&value_);
}
@@ -139,8 +141,54 @@ class Poll {
};
template <>
+class Poll<Empty> {
+ public:
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ Poll(Pending) : ready_(false) {}
+ Poll() : ready_(false) {}
+ Poll(const Poll& other) = default;
+ Poll(Poll&& other) noexcept = default;
+ Poll& operator=(const Poll& other) = default;
+ Poll& operator=(Poll&& other) = default;
+ // NOLINTNEXTLINE(google-explicit-constructor)
+ Poll(Empty) : ready_(true) {}
+ ~Poll() = default;
+
+ bool pending() const { return !ready_; }
+ bool ready() const { return ready_; }
+
+ Empty value() const {
+ GPR_DEBUG_ASSERT(ready());
+ return Empty{};
+ }
+
+ Empty* value_if_ready() {
+ static Empty value;
+ if (ready()) return &value;
+ return nullptr;
+ }
+
+ const Empty* value_if_ready() const {
+ static Empty value;
+ if (ready()) return &value;
+ return nullptr;
+ }
+
+ private:
+ // Flag indicating readiness.
+ bool ready_;
+};
+
+// Ensure degenerate cases are not defined:
+
+// Can't poll for a Pending
+template <>
class Poll<Pending>;
+// Can't poll for a poll
+template <class T>
+class Poll<Poll<T>>;
+
template <typename T>
bool operator==(const Poll<T>& a, const Poll<T>& b) {
if (a.pending() && b.pending()) return true;
diff --git a/contrib/libs/grpc/src/core/lib/promise/promise.h b/contrib/libs/grpc/src/core/lib/promise/promise.h
index 681b8e1cb8..8413af6040 100644
--- a/contrib/libs/grpc/src/core/lib/promise/promise.h
+++ b/contrib/libs/grpc/src/core/lib/promise/promise.h
@@ -17,10 +17,10 @@
#include <grpc/support/port_platform.h>
-#include <functional>
#include <type_traits>
#include <utility>
+#include "y_absl/functional/any_invocable.h"
#include "y_absl/status/status.h"
#include "y_absl/types/optional.h"
@@ -33,7 +33,7 @@ namespace grpc_core {
// Most of the time we just pass around the functor, but occasionally
// it pays to have a type erased variant, which we define here.
template <typename T>
-using Promise = std::function<Poll<T>()>;
+using Promise = y_absl::AnyInvocable<Poll<T>()>;
// Helper to execute a promise immediately and return either the result or
// nothing.
diff --git a/contrib/libs/grpc/src/core/lib/resource_quota/arena.cc b/contrib/libs/grpc/src/core/lib/resource_quota/arena.cc
index 8811f8848e..d37ef42649 100644
--- a/contrib/libs/grpc/src/core/lib/resource_quota/arena.cc
+++ b/contrib/libs/grpc/src/core/lib/resource_quota/arena.cc
@@ -54,6 +54,9 @@ Arena::~Arena() {
gpr_free_aligned(z);
z = prev_z;
}
+#ifdef GRPC_ARENA_TRACE_POOLED_ALLOCATIONS
+ gpr_log(GPR_ERROR, "DESTRUCT_ARENA %p", this);
+#endif
}
Arena* Arena::Create(size_t initial_size, MemoryAllocator* memory_allocator) {
@@ -71,7 +74,7 @@ std::pair<Arena*, void*> Arena::CreateWithAlloc(
return std::make_pair(new_arena, first_alloc);
}
-void Arena::Destroy() {
+void Arena::DestroyManagedNewObjects() {
ManagedNewObject* p;
// Outer loop: clear the managed new object list.
// We do this repeatedly in case a destructor ends up allocating something.
@@ -82,6 +85,10 @@ void Arena::Destroy() {
Destruct(std::exchange(p, p->next));
}
}
+}
+
+void Arena::Destroy() {
+ DestroyManagedNewObjects();
memory_allocator_->Release(total_allocated_.load(std::memory_order_relaxed));
this->~Arena();
gpr_free_aligned(this);
@@ -114,7 +121,8 @@ void Arena::ManagedNewObject::Link(std::atomic<ManagedNewObject*>* head) {
}
}
-void* Arena::AllocPooled(size_t alloc_size, std::atomic<FreePoolNode*>* head) {
+void* Arena::AllocPooled(size_t obj_size, size_t alloc_size,
+ std::atomic<FreePoolNode*>* head) {
// ABA mitigation:
// AllocPooled may be called by multiple threads, and to remove a node from
// the free list we need to manipulate the next pointer, which may be done
@@ -132,7 +140,11 @@ void* Arena::AllocPooled(size_t alloc_size, std::atomic<FreePoolNode*>* head) {
FreePoolNode* p = head->exchange(nullptr, std::memory_order_acquire);
// If there are no nodes in the free list, then go ahead and allocate from the
// arena.
- if (p == nullptr) return Alloc(alloc_size);
+ if (p == nullptr) {
+ void* r = Alloc(alloc_size);
+ TracePoolAlloc(obj_size, r);
+ return r;
+ }
// We had a non-empty free list... but we own the *entire* free list.
// We only want one node, so if there are extras we'd better give them back.
if (p->next != nullptr) {
@@ -151,10 +163,14 @@ void* Arena::AllocPooled(size_t alloc_size, std::atomic<FreePoolNode*>* head) {
extra = next;
}
}
+ TracePoolAlloc(obj_size, p);
return p;
}
void Arena::FreePooled(void* p, std::atomic<FreePoolNode*>* head) {
+ // May spuriously trace a free of an already freed object - see AllocPooled
+ // ABA mitigation.
+ TracePoolFree(p);
FreePoolNode* node = static_cast<FreePoolNode*>(p);
node->next = head->load(std::memory_order_acquire);
while (!head->compare_exchange_weak(
diff --git a/contrib/libs/grpc/src/core/lib/resource_quota/arena.h b/contrib/libs/grpc/src/core/lib/resource_quota/arena.h
index 09d2eeddde..87c0602f6c 100644
--- a/contrib/libs/grpc/src/core/lib/resource_quota/arena.h
+++ b/contrib/libs/grpc/src/core/lib/resource_quota/arena.h
@@ -45,6 +45,9 @@
#include "src/core/lib/promise/context.h"
#include "src/core/lib/resource_quota/memory_quota.h"
+// #define GRPC_ARENA_POOLED_ALLOCATIONS_USE_MALLOC
+// #define GRPC_ARENA_TRACE_POOLED_ALLOCATIONS
+
namespace grpc_core {
namespace arena_detail {
@@ -114,7 +117,9 @@ PoolAndSize ChoosePoolForAllocationSize(
} // namespace arena_detail
class Arena {
- using PoolSizes = y_absl::integer_sequence<size_t, 256, 512, 768>;
+ // Selected pool sizes.
+ // How to tune: see tools/codegen/core/optimize_arena_pool_sizes.py
+ using PoolSizes = y_absl::integer_sequence<size_t, 80, 304, 528, 1024>;
struct FreePoolNode {
FreePoolNode* next;
};
@@ -130,6 +135,13 @@ class Arena {
size_t initial_size, size_t alloc_size,
MemoryAllocator* memory_allocator);
+ // Destroy all `ManagedNew` allocated objects.
+ // Allows safe destruction of these objects even if they need context held by
+ // the arena.
+ // Idempotent.
+ // TODO(ctiller): eliminate ManagedNew.
+ void DestroyManagedNewObjects();
+
// Destroy an arena.
void Destroy();
@@ -170,6 +182,7 @@ class Arena {
return &p->t;
}
+#ifndef GRPC_ARENA_POOLED_ALLOCATIONS_USE_MALLOC
class PooledDeleter {
public:
explicit PooledDeleter(std::atomic<FreePoolNode*>* free_list)
@@ -209,6 +222,7 @@ class Arena {
&pools_[arena_detail::PoolFromObjectSize<sizeof(T)>(PoolSizes())];
return PoolPtr<T>(
new (AllocPooled(
+ sizeof(T),
arena_detail::AllocationSizeFromObjectSize<sizeof(T)>(PoolSizes()),
free_list)) T(std::forward<Args>(args)...),
PooledDeleter(free_list));
@@ -229,12 +243,95 @@ class Arena {
return PoolPtr<T[]>(new (Alloc(where.alloc_size)) T[n],
PooledDeleter(nullptr));
} else {
- return PoolPtr<T[]>(
- new (AllocPooled(where.alloc_size, &pools_[where.pool_index])) T[n],
- PooledDeleter(&pools_[where.pool_index]));
+ return PoolPtr<T[]>(new (AllocPooled(where.alloc_size, where.alloc_size,
+ &pools_[where.pool_index])) T[n],
+ PooledDeleter(&pools_[where.pool_index]));
+ }
+ }
+
+ // Like MakePooled, but with manual memory management.
+ // The caller is responsible for calling DeletePooled() on the returned
+ // pointer, and expected to call it with the same type T as was passed to this
+ // function (else the free list returned to the arena will be corrupted).
+ template <typename T, typename... Args>
+ T* NewPooled(Args&&... args) {
+ auto* free_list =
+ &pools_[arena_detail::PoolFromObjectSize<sizeof(T)>(PoolSizes())];
+ return new (AllocPooled(
+ sizeof(T),
+ arena_detail::AllocationSizeFromObjectSize<sizeof(T)>(PoolSizes()),
+ free_list)) T(std::forward<Args>(args)...);
+ }
+
+ template <typename T>
+ void DeletePooled(T* p) {
+ auto* free_list =
+ &pools_[arena_detail::PoolFromObjectSize<sizeof(T)>(PoolSizes())];
+ p->~T();
+ FreePooled(p, free_list);
+ }
+#else
+ class PooledDeleter {
+ public:
+ PooledDeleter() = default;
+ explicit PooledDeleter(std::nullptr_t) : delete_(false) {}
+ template <typename T>
+ void operator()(T* p) {
+ // TODO(ctiller): promise based filter hijacks ownership of some pointers
+ // to make them appear as PoolPtr without really transferring ownership,
+ // by setting the arena to nullptr.
+ // This is a transitional hack and should be removed once promise based
+ // filter is removed.
+ if (delete_) delete p;
}
+
+ bool has_freelist() const { return delete_; }
+
+ private:
+ bool delete_ = true;
+ };
+
+ template <typename T>
+ using PoolPtr = std::unique_ptr<T, PooledDeleter>;
+
+ // Make a unique_ptr to T that is allocated from the arena.
+ // When the pointer is released, the memory may be reused for other
+ // MakePooled(.*) calls.
+ // CAUTION: The amount of memory allocated is rounded up to the nearest
+ // value in Arena::PoolSizes, and so this may pessimize total
+ // arena size.
+ template <typename T, typename... Args>
+ PoolPtr<T> MakePooled(Args&&... args) {
+ return PoolPtr<T>(new T(std::forward<Args>(args)...), PooledDeleter());
+ }
+
+ // Make a unique_ptr to an array of T that is allocated from the arena.
+ // When the pointer is released, the memory may be reused for other
+ // MakePooled(.*) calls.
+ // One can use MakePooledArray<char> to allocate a buffer of bytes.
+ // CAUTION: The amount of memory allocated is rounded up to the nearest
+ // value in Arena::PoolSizes, and so this may pessimize total
+ // arena size.
+ template <typename T>
+ PoolPtr<T[]> MakePooledArray(size_t n) {
+ return PoolPtr<T[]>(new T[n], PooledDeleter());
}
+ // Like MakePooled, but with manual memory management.
+ // The caller is responsible for calling DeletePooled() on the returned
+ // pointer, and expected to call it with the same type T as was passed to this
+ // function (else the free list returned to the arena will be corrupted).
+ template <typename T, typename... Args>
+ T* NewPooled(Args&&... args) {
+ return new T(std::forward<Args>(args)...);
+ }
+
+ template <typename T>
+ void DeletePooled(T* p) {
+ delete p;
+ }
+#endif
+
private:
struct Zone {
Zone* prev;
@@ -275,9 +372,24 @@ class Arena {
void* AllocZone(size_t size);
- void* AllocPooled(size_t alloc_size, std::atomic<FreePoolNode*>* head);
+ void* AllocPooled(size_t obj_size, size_t alloc_size,
+ std::atomic<FreePoolNode*>* head);
static void FreePooled(void* p, std::atomic<FreePoolNode*>* head);
+ void TracePoolAlloc(size_t size, void* ptr) {
+ (void)size;
+ (void)ptr;
+#ifdef GRPC_ARENA_TRACE_POOLED_ALLOCATIONS
+ gpr_log(GPR_ERROR, "ARENA %p ALLOC %" PRIdPTR " @ %p", this, size, ptr);
+#endif
+ }
+ static void TracePoolFree(void* ptr) {
+ (void)ptr;
+#ifdef GRPC_ARENA_TRACE_POOLED_ALLOCATIONS
+ gpr_log(GPR_ERROR, "FREE %p", ptr);
+#endif
+ }
+
// Keep track of the total used size. We use this in our call sizing
// hysteresis.
std::atomic<size_t> total_used_{0};
@@ -290,7 +402,9 @@ class Arena {
// last zone; the zone list is reverse-walked during arena destruction only.
std::atomic<Zone*> last_zone_{nullptr};
std::atomic<ManagedNewObject*> managed_new_head_{nullptr};
+#ifndef GRPC_ARENA_POOLED_ALLOCATIONS_USE_MALLOC
std::atomic<FreePoolNode*> pools_[PoolSizes::size()]{};
+#endif
// The backing memory quota
MemoryAllocator* const memory_allocator_;
};
diff --git a/contrib/libs/grpc/src/core/lib/resource_quota/memory_quota.cc b/contrib/libs/grpc/src/core/lib/resource_quota/memory_quota.cc
index accd54042e..7a28b4d236 100644
--- a/contrib/libs/grpc/src/core/lib/resource_quota/memory_quota.cc
+++ b/contrib/libs/grpc/src/core/lib/resource_quota/memory_quota.cc
@@ -645,7 +645,7 @@ TString PressureController::DebugString() const {
}
double PressureTracker::AddSampleAndGetControlValue(double sample) {
- static const double kSetPoint = 95.0;
+ static const double kSetPoint = 0.95;
double max_so_far = max_this_round_.load(std::memory_order_relaxed);
if (sample > max_so_far) {
diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.cc
index 5eb520b368..fdd8b27b35 100644
--- a/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.cc
+++ b/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.cc
@@ -38,7 +38,6 @@
#include <grpc/support/string_util.h>
#include "src/core/lib/gprpp/env.h"
-#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/http/httpcli_ssl_credentials.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/json/json.h"
@@ -49,9 +48,6 @@ namespace grpc_core {
namespace {
-const char* awsEc2MetadataIpv4Address = "169.254.169.254";
-const char* awsEc2MetadataIpv6Address = "fd00:ec2::254";
-
const char* kExpectedEnvironmentId = "aws1";
const char* kRegionEnvVar = "AWS_REGION";
@@ -78,15 +74,6 @@ TString UrlEncode(const y_absl::string_view& s) {
return result;
}
-bool ValidateAwsUrl(const TString& urlString) {
- y_absl::StatusOr<URI> url = URI::Parse(urlString);
- if (!url.ok()) return false;
- y_absl::string_view host;
- y_absl::string_view port;
- SplitHostPort(url->authority(), &host, &port);
- return host == awsEc2MetadataIpv4Address || host == awsEc2MetadataIpv6Address;
-}
-
} // namespace
RefCountedPtr<AwsExternalAccountCredentials>
@@ -129,22 +116,10 @@ AwsExternalAccountCredentials::AwsExternalAccountCredentials(
return;
}
region_url_ = it->second.string_value();
- if (!ValidateAwsUrl(region_url_)) {
- *error = GRPC_ERROR_CREATE(y_absl::StrFormat(
- "Invalid host for region_url field, expecting %s or %s.",
- awsEc2MetadataIpv4Address, awsEc2MetadataIpv6Address));
- return;
- }
it = options.credential_source.object_value().find("url");
if (it != options.credential_source.object_value().end() &&
it->second.type() == Json::Type::STRING) {
url_ = it->second.string_value();
- if (!ValidateAwsUrl(url_)) {
- *error = GRPC_ERROR_CREATE(y_absl::StrFormat(
- "Invalid host for url field, expecting %s or %s.",
- awsEc2MetadataIpv4Address, awsEc2MetadataIpv6Address));
- return;
- }
}
it = options.credential_source.object_value().find(
"regional_cred_verification_url");
@@ -164,16 +139,16 @@ AwsExternalAccountCredentials::AwsExternalAccountCredentials(
if (it != options.credential_source.object_value().end() &&
it->second.type() == Json::Type::STRING) {
imdsv2_session_token_url_ = it->second.string_value();
- if (!ValidateAwsUrl(imdsv2_session_token_url_)) {
- *error = GRPC_ERROR_CREATE(y_absl::StrFormat(
- "Invalid host for imdsv2_session_token_url field, expecting %s or "
- "%s.",
- awsEc2MetadataIpv4Address, awsEc2MetadataIpv6Address));
- return;
- }
}
}
+bool AwsExternalAccountCredentials::ShouldUseMetadataServer() {
+ return !((GetEnv(kRegionEnvVar).has_value() ||
+ GetEnv(kDefaultRegionEnvVar).has_value()) &&
+ (GetEnv(kAccessKeyIdEnvVar).has_value() &&
+ GetEnv(kSecretAccessKeyEnvVar).has_value()));
+}
+
void AwsExternalAccountCredentials::RetrieveSubjectToken(
HTTPRequestContext* ctx, const Options& /*options*/,
std::function<void(TString, grpc_error_handle)> cb) {
@@ -186,7 +161,7 @@ void AwsExternalAccountCredentials::RetrieveSubjectToken(
}
ctx_ = ctx;
cb_ = cb;
- if (!imdsv2_session_token_url_.empty()) {
+ if (!imdsv2_session_token_url_.empty() && ShouldUseMetadataServer()) {
RetrieveImdsV2SessionToken();
} else if (signer_ != nullptr) {
BuildSubjectToken();
@@ -381,10 +356,12 @@ void AwsExternalAccountCredentials::RetrieveSigningKeys() {
auto secret_access_key_from_env = GetEnv(kSecretAccessKeyEnvVar);
auto token_from_env = GetEnv(kSessionTokenEnvVar);
if (access_key_id_from_env.has_value() &&
- secret_access_key_from_env.has_value() && token_from_env.has_value()) {
+ secret_access_key_from_env.has_value()) {
access_key_id_ = std::move(*access_key_id_from_env);
secret_access_key_ = std::move(*secret_access_key_from_env);
- token_ = std::move(*token_from_env);
+ if (token_from_env.has_value()) {
+ token_ = std::move(*token_from_env);
+ }
BuildSubjectToken();
return;
}
diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.h b/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.h
index e837effa1e..7190bb3842 100644
--- a/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.h
+++ b/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.h
@@ -46,6 +46,7 @@ class AwsExternalAccountCredentials final : public ExternalAccountCredentials {
grpc_error_handle* error);
private:
+ bool ShouldUseMetadataServer();
void RetrieveSubjectToken(
HTTPRequestContext* ctx, const Options& options,
std::function<void(TString, grpc_error_handle)> cb) override;
diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc
index d23f435beb..58d4b9f578 100644
--- a/contrib/libs/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc
+++ b/contrib/libs/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc
@@ -22,7 +22,6 @@
#include <string.h>
-#include <map>
#include <memory>
#include <util/generic/string.h>
#include <util/string/cast.h>
@@ -30,7 +29,6 @@
#include "y_absl/status/statusor.h"
#include "y_absl/strings/match.h"
#include "y_absl/strings/string_view.h"
-#include "y_absl/strings/strip.h"
#include "y_absl/types/optional.h"
#include <grpc/grpc_security.h> // IWYU pragma: keep
@@ -45,7 +43,6 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/env.h"
-#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/status_helper.h"
@@ -255,57 +252,6 @@ static int is_metadata_server_reachable() {
return detector.success;
}
-namespace {
-
-bool ValidateUrlField(const Json& json, const TString& field) {
- auto it = json.object_value().find(field);
- if (it == json.object_value().end()) {
- return true;
- }
- if (it->second.type() != Json::Type::STRING ||
- it->second.string_value().empty()) {
- return false;
- }
- y_absl::StatusOr<grpc_core::URI> url =
- grpc_core::URI::Parse(it->second.string_value());
- if (!url.ok()) return false;
- if (!y_absl::EqualsIgnoreCase(url->scheme(), "https")) {
- return false;
- }
- y_absl::string_view host;
- y_absl::string_view port;
- grpc_core::SplitHostPort(url->authority(), &host, &port);
- if (y_absl::ConsumeSuffix(&host, ".p.googleapis.com")) {
- if (y_absl::StartsWith(host, "sts-") ||
- y_absl::StartsWith(host, "iamcredentials-")) {
- return true;
- }
- } else if (y_absl::ConsumeSuffix(&host, ".googleapis.com")) {
- if (host == "sts" || host == "iamcredentials") {
- return true;
- } else if (y_absl::StartsWith(host, "sts.") ||
- y_absl::StartsWith(host, "iamcredentials.")) {
- return true;
- } else if (y_absl::EndsWith(host, ".sts") ||
- y_absl::EndsWith(host, ".iamcredentials")) {
- return true;
- } else if (y_absl::EndsWith(host, "-sts") ||
- y_absl::EndsWith(host, "-iamcredentials")) {
- return true;
- }
- }
- return false;
-}
-
-bool ValidateExteralAccountCredentials(const Json& json) {
- return json.type() == Json::Type::OBJECT &&
- ValidateUrlField(json, "token_url") &&
- ValidateUrlField(json, "service_account_impersonation_url") &&
- ValidateUrlField(json, "token_info_url");
-}
-
-} // namespace
-
// Takes ownership of creds_path if not NULL.
static grpc_error_handle create_default_creds_from_path(
const TString& creds_path,
@@ -364,11 +310,6 @@ static grpc_error_handle create_default_creds_from_path(
goto end;
}
- // Finally try an external account credentials.
- if (!ValidateExteralAccountCredentials(json)) {
- error = GRPC_ERROR_CREATE("Invalid external account credentials format.");
- goto end;
- }
result = grpc_core::ExternalAccountCredentials::Create(json, {}, &error);
end:
diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
index 6e9832af67..7ac4b620cd 100644
--- a/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
+++ b/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
@@ -267,10 +267,7 @@ void grpc_oauth2_token_fetcher_credentials::on_http_response(
// Invoke callbacks for all pending requests.
while (pending_request != nullptr) {
if (status == GRPC_CREDENTIALS_OK) {
- pending_request->md->Append(
- GRPC_AUTHORIZATION_METADATA_KEY, access_token_value->Ref(),
- [](y_absl::string_view, const grpc_core::Slice&) { abort(); });
- pending_request->result = std::move(pending_request->md);
+ pending_request->result = access_token_value->Ref();
} else {
auto err = GRPC_ERROR_CREATE_REFERENCING(
"Error occurred when fetching oauth2 token.", &error, 1);
@@ -338,7 +335,15 @@ grpc_oauth2_token_fetcher_credentials::GetRequestMetadata(
if (!pending_request->done.load(std::memory_order_acquire)) {
return grpc_core::Pending{};
}
- return std::move(pending_request->result);
+ if (pending_request->result.ok()) {
+ pending_request->md->Append(
+ GRPC_AUTHORIZATION_METADATA_KEY,
+ std::move(*pending_request->result),
+ [](y_absl::string_view, const grpc_core::Slice&) { abort(); });
+ return std::move(pending_request->md);
+ } else {
+ return pending_request->result.status();
+ }
};
}
diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
index 7962e34ea6..ecbf9c58fa 100644
--- a/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
+++ b/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h
@@ -103,7 +103,7 @@ struct grpc_oauth2_pending_get_request_metadata
grpc_polling_entity* pollent;
grpc_core::ClientMetadataHandle md;
struct grpc_oauth2_pending_get_request_metadata* next;
- y_absl::StatusOr<grpc_core::ClientMetadataHandle> result;
+ y_absl::StatusOr<grpc_core::Slice> result;
};
// -- Oauth2 Token Fetcher credentials --
diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc b/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc
index efeea9059c..b13b5ff123 100644
--- a/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc
+++ b/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc
@@ -117,6 +117,8 @@ gpr_timespec TimeoutSecondsToDeadline(int64_t seconds) {
} // namespace
+static constexpr int64_t kMinimumFileWatcherRefreshIntervalSeconds = 1;
+
FileWatcherCertificateProvider::FileWatcherCertificateProvider(
TString private_key_path, TString identity_certificate_path,
TString root_cert_path, int64_t refresh_interval_sec)
@@ -125,6 +127,12 @@ FileWatcherCertificateProvider::FileWatcherCertificateProvider(
root_cert_path_(std::move(root_cert_path)),
refresh_interval_sec_(refresh_interval_sec),
distributor_(MakeRefCounted<grpc_tls_certificate_distributor>()) {
+ if (refresh_interval_sec_ < kMinimumFileWatcherRefreshIntervalSeconds) {
+ gpr_log(GPR_INFO,
+ "FileWatcherCertificateProvider refresh_interval_sec_ set to value "
+ "less than minimum. Overriding configured value to minimum.");
+ refresh_interval_sec_ = kMinimumFileWatcherRefreshIntervalSeconds;
+ }
// Private key and identity cert files must be both set or both unset.
GPR_ASSERT(private_key_path_.empty() == identity_certificate_path_.empty());
// Must be watching either root or identity certs.
@@ -381,6 +389,11 @@ FileWatcherCertificateProvider::ReadIdentityKeyCertPairFromFiles(
return y_absl::nullopt;
}
+int64_t FileWatcherCertificateProvider::TestOnlyGetRefreshIntervalSecond()
+ const {
+ return refresh_interval_sec_;
+}
+
y_absl::StatusOr<bool> PrivateKeyAndCertificateMatch(
y_absl::string_view private_key, y_absl::string_view cert_chain) {
if (private_key.empty()) {
diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h b/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h
index fedc950e7e..b638fe2b3f 100644
--- a/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h
+++ b/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h
@@ -152,6 +152,8 @@ class FileWatcherCertificateProvider final
UniqueTypeName type() const override;
+ int64_t TestOnlyGetRefreshIntervalSecond() const;
+
private:
struct WatcherInfo {
bool root_being_watched = false;
diff --git a/contrib/libs/grpc/src/core/lib/security/security_connector/load_system_roots_supported.cc b/contrib/libs/grpc/src/core/lib/security/security_connector/load_system_roots_supported.cc
index bb6dc3169b..cc40f9f70a 100644
--- a/contrib/libs/grpc/src/core/lib/security/security_connector/load_system_roots_supported.cc
+++ b/contrib/libs/grpc/src/core/lib/security/security_connector/load_system_roots_supported.cc
@@ -19,6 +19,8 @@
#include <grpc/support/port_platform.h>
#include <algorithm>
+#include <util/generic/string.h>
+#include <util/string/cast.h>
#include <vector>
#if defined(GPR_LINUX) || defined(GPR_ANDROID) || defined(GPR_FREEBSD) || \
@@ -27,7 +29,6 @@
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
-#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -35,17 +36,13 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
+#include "src/core/lib/config/config_vars.h"
#include "src/core/lib/gpr/useful.h"
-#include "src/core/lib/gprpp/global_config.h"
-#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/security_connector/load_system_roots.h"
#include "src/core/lib/security/security_connector/load_system_roots_supported.h"
-GPR_GLOBAL_CONFIG_DEFINE_STRING(grpc_system_ssl_roots_dir, "",
- "Custom directory to SSL Roots");
-
namespace grpc_core {
namespace {
@@ -150,9 +147,9 @@ grpc_slice CreateRootCertsBundle(const char* certs_directory) {
grpc_slice LoadSystemRootCerts() {
grpc_slice result = grpc_empty_slice();
// Prioritize user-specified custom directory if flag is set.
- UniquePtr<char> custom_dir = GPR_GLOBAL_CONFIG_GET(grpc_system_ssl_roots_dir);
- if (strlen(custom_dir.get()) > 0) {
- result = CreateRootCertsBundle(custom_dir.get());
+ auto custom_dir = ConfigVars::Get().SystemSslRootsDir();
+ if (!custom_dir.empty()) {
+ result = CreateRootCertsBundle(TString(custom_dir).c_str());
}
// If the custom directory is empty/invalid/not specified, fallback to
// distribution-specific directory.
diff --git a/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc b/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc
index 78b6b61c62..89be1cb65e 100644
--- a/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc
+++ b/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc
@@ -32,19 +32,18 @@
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include "src/core/ext/transport/chttp2/alpn/alpn.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/config/config_vars.h"
#include "src/core/lib/gpr/useful.h"
-#include "src/core/lib/gprpp/global_config.h"
#include "src/core/lib/gprpp/host_port.h"
-#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/security_connector/load_system_roots.h"
-#include "src/core/lib/security/security_connector/ssl_utils_config.h"
#include "src/core/tsi/ssl_transport_security.h"
#include "src/core/tsi/transport_security.h"
@@ -78,22 +77,9 @@ void grpc_set_ssl_roots_override_callback(grpc_ssl_roots_override_callback cb) {
static gpr_once cipher_suites_once = GPR_ONCE_INIT;
static const char* cipher_suites = nullptr;
-// All cipher suites for default are compliant with HTTP2.
-GPR_GLOBAL_CONFIG_DEFINE_STRING(
- grpc_ssl_cipher_suites,
- "TLS_AES_128_GCM_SHA256:"
- "TLS_AES_256_GCM_SHA384:"
- "TLS_CHACHA20_POLY1305_SHA256:"
- "ECDHE-ECDSA-AES128-GCM-SHA256:"
- "ECDHE-ECDSA-AES256-GCM-SHA384:"
- "ECDHE-RSA-AES128-GCM-SHA256:"
- "ECDHE-RSA-AES256-GCM-SHA384",
- "A colon separated list of cipher suites to use with OpenSSL")
-
static void init_cipher_suites(void) {
- grpc_core::UniquePtr<char> value =
- GPR_GLOBAL_CONFIG_GET(grpc_ssl_cipher_suites);
- cipher_suites = value.release();
+ cipher_suites = gpr_strdup(
+ TString(grpc_core::ConfigVars::Get().SslCipherSuites()).c_str());
}
// --- Util ---
@@ -575,14 +561,13 @@ const char* DefaultSslRootStore::GetPemRootCerts() {
grpc_slice DefaultSslRootStore::ComputePemRootCerts() {
grpc_slice result = grpc_empty_slice();
- const bool not_use_system_roots =
- GPR_GLOBAL_CONFIG_GET(grpc_not_use_system_ssl_roots);
// First try to load the roots from the configuration.
- UniquePtr<char> default_root_certs_path =
- GPR_GLOBAL_CONFIG_GET(grpc_default_ssl_roots_file_path);
- if (strlen(default_root_certs_path.get()) > 0) {
+ auto default_root_certs_path = ConfigVars::Get().DefaultSslRootsFilePath();
+ if (!default_root_certs_path.empty()) {
GRPC_LOG_IF_ERROR(
- "load_file", grpc_load_file(default_root_certs_path.get(), 1, &result));
+ "load_file",
+ grpc_load_file(TString(default_root_certs_path).c_str(), 1,
+ &result));
}
// Try overridden roots if needed.
grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL;
@@ -598,7 +583,8 @@ grpc_slice DefaultSslRootStore::ComputePemRootCerts() {
gpr_free(pem_root_certs);
}
// Try loading roots from OS trust store if flag is enabled.
- if (GRPC_SLICE_IS_EMPTY(result) && !not_use_system_roots) {
+ if (GRPC_SLICE_IS_EMPTY(result) &&
+ !ConfigVars::Get().NotUseSystemSslRoots()) {
result = LoadSystemRootCerts();
// Merge with Arcadia certs.
result = AddArcadiaRootCerts(result);
diff --git a/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils_config.cc b/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils_config.cc
deleted file mode 100644
index cf0d3811c4..0000000000
--- a/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils_config.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-//
-// Copyright 2019 gRPC authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/lib/security/security_connector/ssl_utils_config.h"
-
-/// Config variable that points to the default SSL roots file. This file
-/// must be a PEM encoded file with all the roots such as the one that can be
-/// downloaded from https://pki.google.com/roots.pem.
-GPR_GLOBAL_CONFIG_DEFINE_STRING(grpc_default_ssl_roots_file_path, "",
- "Path to the default SSL roots file.");
-
-/// Config variable used as a flag to enable/disable loading system root
-/// certificates from the OS trust store.
-GPR_GLOBAL_CONFIG_DEFINE_BOOL(grpc_not_use_system_ssl_roots, false,
- "Disable loading system root certificates.");
diff --git a/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils_config.h b/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils_config.h
deleted file mode 100644
index 243a197173..0000000000
--- a/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils_config.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-//
-// Copyright 2019 gRPC authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//
-
-#ifndef GRPC_SRC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SSL_UTILS_CONFIG_H
-#define GRPC_SRC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SSL_UTILS_CONFIG_H
-#include <grpc/support/port_platform.h>
-
-#include "src/core/lib/gprpp/global_config.h"
-#include "src/core/lib/gprpp/memory.h"
-
-GPR_GLOBAL_CONFIG_DECLARE_STRING(grpc_default_ssl_roots_file_path);
-GPR_GLOBAL_CONFIG_DECLARE_BOOL(grpc_not_use_system_ssl_roots);
-
-#endif // GRPC_SRC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SSL_UTILS_CONFIG_H
diff --git a/contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc b/contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc
index 9ed395da76..aeb0ea1fd1 100644
--- a/contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc
+++ b/contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc
@@ -74,6 +74,7 @@ void PendingVerifierRequestInit(
bool has_common_name = false;
bool has_peer_cert = false;
bool has_peer_cert_full_chain = false;
+ bool has_verified_root_cert_subject = false;
std::vector<char*> uri_names;
std::vector<char*> dns_names;
std::vector<char*> email_names;
@@ -105,6 +106,11 @@ void PendingVerifierRequestInit(
} else if (strcmp(prop->name, TSI_X509_IP_PEER_PROPERTY) == 0) {
char* ip = CopyCoreString(prop->value.data, prop->value.length);
ip_names.emplace_back(ip);
+ } else if (strcmp(prop->name,
+ TSI_X509_VERIFIED_ROOT_CERT_SUBECT_PEER_PROPERTY) == 0) {
+ request->peer_info.verified_root_cert_subject =
+ CopyCoreString(prop->value.data, prop->value.length);
+ has_verified_root_cert_subject = true;
}
}
if (!has_common_name) {
@@ -116,6 +122,9 @@ void PendingVerifierRequestInit(
if (!has_peer_cert_full_chain) {
request->peer_info.peer_cert_full_chain = nullptr;
}
+ if (!has_verified_root_cert_subject) {
+ request->peer_info.verified_root_cert_subject = nullptr;
+ }
request->peer_info.san_names.uri_names_size = uri_names.size();
if (!uri_names.empty()) {
request->peer_info.san_names.uri_names =
@@ -202,6 +211,9 @@ void PendingVerifierRequestDestroy(
if (request->peer_info.peer_cert_full_chain != nullptr) {
gpr_free(const_cast<char*>(request->peer_info.peer_cert_full_chain));
}
+ if (request->peer_info.verified_root_cert_subject != nullptr) {
+ gpr_free(const_cast<char*>(request->peer_info.verified_root_cert_subject));
+ }
}
tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair(
diff --git a/contrib/libs/grpc/src/core/lib/security/transport/secure_endpoint.cc b/contrib/libs/grpc/src/core/lib/security/transport/secure_endpoint.cc
index 877f15b977..db75aad627 100644
--- a/contrib/libs/grpc/src/core/lib/security/transport/secure_endpoint.cc
+++ b/contrib/libs/grpc/src/core/lib/security/transport/secure_endpoint.cc
@@ -236,7 +236,8 @@ static void flush_read_staging_buffer(secure_endpoint* ep, uint8_t** cur,
}
static void call_read_cb(secure_endpoint* ep, grpc_error_handle error) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_secure_endpoint)) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_secure_endpoint) &&
+ gpr_should_log(GPR_LOG_SEVERITY_INFO)) {
size_t i;
for (i = 0; i < ep->read_buffer->count; i++) {
char* data = grpc_dump_slice(ep->read_buffer->slices[i],
@@ -394,7 +395,8 @@ static void endpoint_write(grpc_endpoint* secure_ep, grpc_slice_buffer* slices,
grpc_slice_buffer_reset_and_unref(&ep->output_buffer);
- if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_secure_endpoint)) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_secure_endpoint) &&
+ gpr_should_log(GPR_LOG_SEVERITY_INFO)) {
for (i = 0; i < slices->count; i++) {
char* data =
grpc_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
diff --git a/contrib/libs/grpc/src/core/lib/security/transport/server_auth_filter.cc b/contrib/libs/grpc/src/core/lib/security/transport/server_auth_filter.cc
index 141bd407ba..627da1f00a 100644
--- a/contrib/libs/grpc/src/core/lib/security/transport/server_auth_filter.cc
+++ b/contrib/libs/grpc/src/core/lib/security/transport/server_auth_filter.cc
@@ -18,12 +18,13 @@
#include <grpc/support/port_platform.h>
-#include <string.h>
-
#include <algorithm>
#include <atomic>
+#include <cstddef>
#include <functional>
#include <memory>
+#include <util/generic/string.h>
+#include <util/string/cast.h>
#include <utility>
#include "y_absl/status/status.h"
@@ -41,6 +42,7 @@
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/channel/promise_based_filter.h"
+#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/status_helper.h"
@@ -57,6 +59,7 @@
#include "src/core/lib/security/transport/auth_filters.h" // IWYU pragma: keep
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/surface/call_trace.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
@@ -120,12 +123,28 @@ class ServerAuthFilter::RunApplicationCode {
// memory later
RunApplicationCode(ServerAuthFilter* filter, CallArgs call_args)
: state_(GetContext<Arena>()->ManagedNew<State>(std::move(call_args))) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_ERROR,
+ "%s[server-auth]: Delegate to application: filter=%p this=%p "
+ "auth_ctx=%p",
+ Activity::current()->DebugTag().c_str(), filter, this,
+ filter->auth_context_.get());
+ }
filter->server_credentials_->auth_metadata_processor().process(
filter->server_credentials_->auth_metadata_processor().state,
filter->auth_context_.get(), state_->md.metadata, state_->md.count,
OnMdProcessingDone, state_);
}
+ RunApplicationCode(const RunApplicationCode&) = delete;
+ RunApplicationCode& operator=(const RunApplicationCode&) = delete;
+ RunApplicationCode(RunApplicationCode&& other) noexcept
+ : state_(std::exchange(other.state_, nullptr)) {}
+ RunApplicationCode& operator=(RunApplicationCode&& other) noexcept {
+ state_ = std::exchange(other.state_, nullptr);
+ return *this;
+ }
+
Poll<y_absl::StatusOr<CallArgs>> operator()() {
if (state_->done.load(std::memory_order_acquire)) {
return Poll<y_absl::StatusOr<CallArgs>>(std::move(state_->call_args));
diff --git a/contrib/libs/grpc/src/core/lib/slice/slice.cc b/contrib/libs/grpc/src/core/lib/slice/slice.cc
index 28615df342..67641ffbe9 100644
--- a/contrib/libs/grpc/src/core/lib/slice/slice.cc
+++ b/contrib/libs/grpc/src/core/lib/slice/slice.cc
@@ -480,7 +480,7 @@ int grpc_slice_slice(grpc_slice haystack, grpc_slice needle) {
}
const uint8_t* last = haystack_bytes + haystack_len - needle_len;
- for (const uint8_t* cur = haystack_bytes; cur != last; ++cur) {
+ for (const uint8_t* cur = haystack_bytes; cur <= last; ++cur) {
if (0 == memcmp(cur, needle_bytes, needle_len)) {
return static_cast<int>(cur - haystack_bytes);
}
diff --git a/contrib/libs/grpc/src/core/lib/surface/builtins.cc b/contrib/libs/grpc/src/core/lib/surface/builtins.cc
index 2b50d2c353..bb20388b40 100644
--- a/contrib/libs/grpc/src/core/lib/surface/builtins.cc
+++ b/contrib/libs/grpc/src/core/lib/surface/builtins.cc
@@ -18,6 +18,7 @@
#include <limits.h>
+#include "src/core/lib/channel/call_tracer.h"
#include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/channel/connected_channel.h"
#include "src/core/lib/config/core_configuration.h"
@@ -29,6 +30,7 @@
namespace grpc_core {
void RegisterBuiltins(CoreConfiguration::Builder* builder) {
+ RegisterServerCallTracerFilter(builder);
builder->channel_init()->RegisterStage(GRPC_CLIENT_SUBCHANNEL,
GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
grpc_add_connected_filter);
diff --git a/contrib/libs/grpc/src/core/lib/surface/call.cc b/contrib/libs/grpc/src/core/lib/surface/call.cc
index 6e8b72fe87..589672dc9b 100644
--- a/contrib/libs/grpc/src/core/lib/surface/call.cc
+++ b/contrib/libs/grpc/src/core/lib/surface/call.cc
@@ -23,6 +23,7 @@
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
+#include <string.h>
#include <algorithm>
#include <atomic>
@@ -36,14 +37,12 @@
#include <vector>
#include "y_absl/base/thread_annotations.h"
-#include "y_absl/cleanup/cleanup.h"
#include "y_absl/meta/type_traits.h"
#include "y_absl/status/status.h"
#include "y_absl/strings/str_cat.h"
#include "y_absl/strings/str_format.h"
#include "y_absl/strings/str_join.h"
#include "y_absl/strings/string_view.h"
-#include "y_absl/types/variant.h"
#include <grpc/byte_buffer.h>
#include <grpc/compression.h>
@@ -60,6 +59,8 @@
#include <grpc/support/time.h>
#include "src/core/lib/channel/call_finalization.h"
+#include "src/core/lib/channel/call_tracer.h"
+#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/channelz.h"
#include "src/core/lib/channel/context.h"
@@ -86,8 +87,13 @@
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/detail/basic_seq.h"
+#include "src/core/lib/promise/latch.h"
+#include "src/core/lib/promise/map.h"
+#include "src/core/lib/promise/party.h"
#include "src/core/lib/promise/pipe.h"
#include "src/core/lib/promise/poll.h"
+#include "src/core/lib/promise/race.h"
+#include "src/core/lib/promise/seq.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/slice/slice_internal.h"
@@ -97,6 +103,7 @@
#include "src/core/lib/surface/completion_queue.h"
#include "src/core/lib/surface/server.h"
#include "src/core/lib/surface/validate_metadata.h"
+#include "src/core/lib/transport/batch_builder.h"
#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
@@ -137,18 +144,18 @@ class Call : public CppImplOf<Call, grpc_call> {
virtual void InternalRef(const char* reason) = 0;
virtual void InternalUnref(const char* reason) = 0;
- virtual grpc_compression_algorithm test_only_compression_algorithm() = 0;
- virtual uint32_t test_only_message_flags() = 0;
- virtual uint32_t test_only_encodings_accepted_by_peer() = 0;
- virtual grpc_compression_algorithm compression_for_level(
- grpc_compression_level level) = 0;
+ grpc_compression_algorithm test_only_compression_algorithm() {
+ return incoming_compression_algorithm_;
+ }
+ uint32_t test_only_message_flags() { return test_only_last_message_flags_; }
+ CompressionAlgorithmSet encodings_accepted_by_peer() {
+ return encodings_accepted_by_peer_;
+ }
// This should return nullptr for the promise stack (and alternative means
// for that functionality be invented)
virtual grpc_call_stack* call_stack() = 0;
- gpr_atm* peer_string_atm_ptr() { return &peer_string_; }
-
protected:
// The maximum number of concurrent batches possible.
// Based upon the maximum number of individually queueable ops in the batch
@@ -206,7 +213,37 @@ class Call : public CppImplOf<Call, grpc_call> {
send_deadline_ = send_deadline;
}
- void ClearPeerString() { gpr_atm_rel_store(&peer_string_, 0); }
+ Slice GetPeerString() const {
+ MutexLock lock(&peer_mu_);
+ return peer_string_.Ref();
+ }
+
+ void SetPeerString(Slice peer_string) {
+ MutexLock lock(&peer_mu_);
+ peer_string_ = std::move(peer_string);
+ }
+
+ void ClearPeerString() { SetPeerString(Slice(grpc_empty_slice())); }
+
+ // TODO(ctiller): cancel_func is for cancellation of the call - filter stack
+ // holds no mutexes here, promise stack does, and so locking is different.
+ // Remove this and cancel directly once promise conversion is done.
+ void ProcessIncomingInitialMetadata(grpc_metadata_batch& md);
+ // Fixup outgoing metadata before sending - adds compression, protects
+ // internal headers against external modification.
+ void PrepareOutgoingInitialMetadata(const grpc_op& op,
+ grpc_metadata_batch& md);
+ void NoteLastMessageFlags(uint32_t flags) {
+ test_only_last_message_flags_ = flags;
+ }
+ grpc_compression_algorithm incoming_compression_algorithm() const {
+ return incoming_compression_algorithm_;
+ }
+
+ void HandleCompressionAlgorithmDisabled(
+ grpc_compression_algorithm compression_algorithm) GPR_ATTRIBUTE_NOINLINE;
+ void HandleCompressionAlgorithmNotAccepted(
+ grpc_compression_algorithm compression_algorithm) GPR_ATTRIBUTE_NOINLINE;
private:
RefCountedPtr<Channel> channel_;
@@ -217,8 +254,18 @@ class Call : public CppImplOf<Call, grpc_call> {
const bool is_client_;
// flag indicating that cancellation is inherited
bool cancellation_is_inherited_ = false;
- // A char* indicating the peer name.
- gpr_atm peer_string_ = 0;
+ // Compression algorithm for *incoming* data
+ grpc_compression_algorithm incoming_compression_algorithm_ =
+ GRPC_COMPRESS_NONE;
+ // Supported encodings (compression algorithms), a bitset.
+ // Always support no compression.
+ CompressionAlgorithmSet encodings_accepted_by_peer_{GRPC_COMPRESS_NONE};
+ uint32_t test_only_last_message_flags_ = 0;
+ // Peer name is protected by a mutex because it can be accessed by the
+ // application at the same moment as it is being set by the completion
+ // of the recv_initial_metadata op. The mutex should be mostly uncontended.
+ mutable Mutex peer_mu_;
+ Slice peer_string_;
};
Call::ParentCall* Call::GetOrCreateParentCall() {
@@ -313,9 +360,13 @@ void Call::MaybeUnpublishFromParent() {
void Call::CancelWithStatus(grpc_status_code status, const char* description) {
// copying 'description' is needed to ensure the grpc_call_cancel_with_status
// guarantee that can be short-lived.
+ // TODO(ctiller): change to
+ // y_absl::Status(static_cast<y_absl::StatusCode>(status), description)
+ // (ie remove the set_int, set_str).
CancelWithError(grpc_error_set_int(
- grpc_error_set_str(GRPC_ERROR_CREATE(description),
- StatusStrProperty::kGrpcMessage, description),
+ grpc_error_set_str(
+ y_absl::Status(static_cast<y_absl::StatusCode>(status), description),
+ StatusStrProperty::kGrpcMessage, description),
StatusIntProperty::kRpcStatus, status));
}
@@ -340,9 +391,16 @@ void Call::PropagateCancellationToChildren() {
}
char* Call::GetPeer() {
- char* peer_string = reinterpret_cast<char*>(gpr_atm_acq_load(&peer_string_));
- if (peer_string != nullptr) return gpr_strdup(peer_string);
- peer_string = grpc_channel_get_target(channel_->c_ptr());
+ Slice peer_slice = GetPeerString();
+ if (!peer_slice.empty()) {
+ y_absl::string_view peer_string_view = peer_slice.as_string_view();
+ char* peer_string =
+ static_cast<char*>(gpr_malloc(peer_string_view.size() + 1));
+ memcpy(peer_string, peer_string_view.data(), peer_string_view.size());
+ peer_string[peer_string_view.size()] = '\0';
+ return peer_string;
+ }
+ char* peer_string = grpc_channel_get_target(channel_->c_ptr());
if (peer_string != nullptr) return peer_string;
return gpr_strdup("unknown");
}
@@ -355,6 +413,92 @@ void Call::DeleteThis() {
arena->Destroy();
}
+void Call::PrepareOutgoingInitialMetadata(const grpc_op& op,
+ grpc_metadata_batch& md) {
+ // TODO(juanlishen): If the user has already specified a compression
+ // algorithm by setting the initial metadata with key of
+ // GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, we shouldn't override that
+ // with the compression algorithm mapped from compression level.
+ // process compression level
+ grpc_compression_level effective_compression_level = GRPC_COMPRESS_LEVEL_NONE;
+ bool level_set = false;
+ if (op.data.send_initial_metadata.maybe_compression_level.is_set) {
+ effective_compression_level =
+ op.data.send_initial_metadata.maybe_compression_level.level;
+ level_set = true;
+ } else {
+ const grpc_compression_options copts = channel()->compression_options();
+ if (copts.default_level.is_set) {
+ level_set = true;
+ effective_compression_level = copts.default_level.level;
+ }
+ }
+ // Currently, only server side supports compression level setting.
+ if (level_set && !is_client()) {
+ const grpc_compression_algorithm calgo =
+ encodings_accepted_by_peer().CompressionAlgorithmForLevel(
+ effective_compression_level);
+ // The following metadata will be checked and removed by the message
+ // compression filter. It will be used as the call's compression
+ // algorithm.
+ md.Set(GrpcInternalEncodingRequest(), calgo);
+ }
+ // Ignore any te metadata key value pairs specified.
+ md.Remove(TeMetadata());
+}
+
+void Call::ProcessIncomingInitialMetadata(grpc_metadata_batch& md) {
+ Slice* peer_string = md.get_pointer(PeerString());
+ if (peer_string != nullptr) SetPeerString(peer_string->Ref());
+
+ incoming_compression_algorithm_ =
+ md.Take(GrpcEncodingMetadata()).value_or(GRPC_COMPRESS_NONE);
+ encodings_accepted_by_peer_ =
+ md.Take(GrpcAcceptEncodingMetadata())
+ .value_or(CompressionAlgorithmSet{GRPC_COMPRESS_NONE});
+
+ const grpc_compression_options compression_options =
+ channel_->compression_options();
+ const grpc_compression_algorithm compression_algorithm =
+ incoming_compression_algorithm_;
+ if (GPR_UNLIKELY(!CompressionAlgorithmSet::FromUint32(
+ compression_options.enabled_algorithms_bitset)
+ .IsSet(compression_algorithm))) {
+ // check if algorithm is supported by current channel config
+ HandleCompressionAlgorithmDisabled(compression_algorithm);
+ }
+ // GRPC_COMPRESS_NONE is always set.
+ GPR_DEBUG_ASSERT(encodings_accepted_by_peer_.IsSet(GRPC_COMPRESS_NONE));
+ if (GPR_UNLIKELY(!encodings_accepted_by_peer_.IsSet(compression_algorithm))) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_compression_trace)) {
+ HandleCompressionAlgorithmNotAccepted(compression_algorithm);
+ }
+ }
+}
+
+void Call::HandleCompressionAlgorithmNotAccepted(
+ grpc_compression_algorithm compression_algorithm) {
+ const char* algo_name = nullptr;
+ grpc_compression_algorithm_name(compression_algorithm, &algo_name);
+ gpr_log(GPR_ERROR,
+ "Compression algorithm ('%s') not present in the "
+ "accepted encodings (%s)",
+ algo_name,
+ TString(encodings_accepted_by_peer_.ToString()).c_str());
+}
+
+void Call::HandleCompressionAlgorithmDisabled(
+ grpc_compression_algorithm compression_algorithm) {
+ const char* algo_name = nullptr;
+ grpc_compression_algorithm_name(compression_algorithm, &algo_name);
+ TString error_msg =
+ y_absl::StrFormat("Compression algorithm '%s' is disabled.", algo_name);
+ gpr_log(GPR_ERROR, "%s", error_msg.c_str());
+ CancelWithError(grpc_error_set_int(y_absl::UnimplementedError(error_msg),
+ StatusIntProperty::kRpcStatus,
+ GRPC_STATUS_UNIMPLEMENTED));
+}
+
///////////////////////////////////////////////////////////////////////////////
// FilterStackCall
// To be removed once promise conversion is complete
@@ -413,11 +557,6 @@ class FilterStackCall final : public Call {
return context_[elem].value;
}
- grpc_compression_algorithm compression_for_level(
- grpc_compression_level level) override {
- return encodings_accepted_by_peer_.CompressionAlgorithmForLevel(level);
- }
-
bool is_trailers_only() const override {
bool result = is_trailers_only_;
GPR_DEBUG_ASSERT(!result || recv_initial_metadata_.TransportSize() == 0);
@@ -435,18 +574,6 @@ class FilterStackCall final : public Call {
return authority_metadata->as_string_view();
}
- grpc_compression_algorithm test_only_compression_algorithm() override {
- return incoming_compression_algorithm_;
- }
-
- uint32_t test_only_message_flags() override {
- return test_only_last_message_flags_;
- }
-
- uint32_t test_only_encodings_accepted_by_peer() override {
- return encodings_accepted_by_peer_.ToLegacyBitmask();
- }
-
static size_t InitialSizeEstimate() {
return sizeof(FilterStackCall) +
sizeof(BatchControl) * kMaxConcurrentBatches;
@@ -483,6 +610,7 @@ class FilterStackCall final : public Call {
}
struct BatchControl {
FilterStackCall* call_ = nullptr;
+ CallTracerAnnotationInterface* call_tracer_ = nullptr;
grpc_transport_stream_op_batch op_;
// Share memory for cq_completion and notify_tag as they are never needed
// simultaneously. Each byte used in this data structure count as six bytes
@@ -512,12 +640,31 @@ class FilterStackCall final : public Call {
}
bool completed_batch_step(PendingOp op) {
auto mask = PendingOpMask(op);
+ // Acquire call tracer before ops_pending_.fetch_sub to avoid races with
+ // call_ being set to nullptr in PostCompletion method. Store the
+ // call_tracer_ and call_ variables locally as well because they could be
+ // modified by another thread after the fetch_sub operation.
+ CallTracerAnnotationInterface* call_tracer = call_tracer_;
+ FilterStackCall* call = call_;
+ bool is_call_trace_enabled = grpc_call_trace.enabled();
+ bool is_call_ops_annotate_enabled =
+ (IsTraceRecordCallopsEnabled() && call_tracer != nullptr);
+ if (is_call_ops_annotate_enabled) {
+ call->InternalRef("Call ops annotate");
+ }
auto r = ops_pending_.fetch_sub(mask, std::memory_order_acq_rel);
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_DEBUG, "BATCH:%p COMPLETE:%s REMAINING:%s (tag:%p)", this,
- PendingOpString(mask).c_str(),
- PendingOpString(r & ~mask).c_str(),
- completion_data_.notify_tag.tag);
+ if (is_call_trace_enabled || is_call_ops_annotate_enabled) {
+ TString trace_string = y_absl::StrFormat(
+ "BATCH:%p COMPLETE:%s REMAINING:%s (tag:%p)", this,
+ PendingOpString(mask).c_str(), PendingOpString(r & ~mask).c_str(),
+ completion_data_.notify_tag.tag);
+ if (is_call_trace_enabled) {
+ gpr_log(GPR_DEBUG, "%s", trace_string.c_str());
+ }
+ if (is_call_ops_annotate_enabled) {
+ call_tracer->RecordAnnotation(trace_string);
+ call->InternalUnref("Call ops annotate");
+ }
}
GPR_ASSERT((r & mask) != 0);
return r == mask;
@@ -527,7 +674,6 @@ class FilterStackCall final : public Call {
void FinishStep(PendingOp op);
void ProcessDataAfterMetadata();
void ReceivingStreamReady(grpc_error_handle error);
- void ValidateFilteredMetadata();
void ReceivingInitialMetadataReady(grpc_error_handle error);
void ReceivingTrailingMetadataReady(grpc_error_handle error);
void FinishBatch(grpc_error_handle error);
@@ -552,10 +698,6 @@ class FilterStackCall final : public Call {
grpc_closure* start_batch_closure);
void SetFinalStatus(grpc_error_handle error);
BatchControl* ReuseOrAllocateBatchControl(const grpc_op* ops);
- void HandleCompressionAlgorithmDisabled(
- grpc_compression_algorithm compression_algorithm) GPR_ATTRIBUTE_NOINLINE;
- void HandleCompressionAlgorithmNotAccepted(
- grpc_compression_algorithm compression_algorithm) GPR_ATTRIBUTE_NOINLINE;
bool PrepareApplicationMetadata(size_t count, grpc_metadata* metadata,
bool is_trailing);
void PublishAppMetadata(grpc_metadata_batch* b, bool is_trailing);
@@ -599,13 +741,6 @@ class FilterStackCall final : public Call {
// completed
grpc_call_final_info final_info_;
- // Compression algorithm for *incoming* data
- grpc_compression_algorithm incoming_compression_algorithm_ =
- GRPC_COMPRESS_NONE;
- // Supported encodings (compression algorithms), a bitset.
- // Always support no compression.
- CompressionAlgorithmSet encodings_accepted_by_peer_{GRPC_COMPRESS_NONE};
-
// Contexts for various subsystems (security, tracing, ...).
grpc_call_context_element context_[GRPC_CONTEXT_COUNT] = {};
@@ -619,7 +754,6 @@ class FilterStackCall final : public Call {
grpc_closure receiving_stream_ready_;
grpc_closure receiving_initial_metadata_ready_;
grpc_closure receiving_trailing_metadata_ready_;
- uint32_t test_only_last_message_flags_ = 0;
// Status about operation of call
bool sent_server_trailing_metadata_ = false;
gpr_atm cancelled_with_error_ = 0;
@@ -706,6 +840,26 @@ grpc_error_handle FilterStackCall::Create(grpc_call_create_args* args,
global_stats().IncrementServerCallsCreated();
call->final_op_.server.cancelled = nullptr;
call->final_op_.server.core_server = args->server;
+ // TODO(yashykt): In the future, we want to also enable stats and trace
+ // collecting from when the call is created at the transport. The idea is
+ // that the transport would create the call tracer and pass it in as part of
+ // the metadata.
+ auto* server_call_tracer_factory = ServerCallTracerFactory::Get(
+ args->server != nullptr ? args->server->channel_args() : ChannelArgs());
+ if (server_call_tracer_factory != nullptr) {
+ auto* server_call_tracer =
+ server_call_tracer_factory->CreateNewServerCallTracer(arena);
+ if (server_call_tracer != nullptr) {
+ // Note that we are setting both
+ // GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE and
+ // GRPC_CONTEXT_CALL_TRACER as a matter of convenience. In the future
+ // promise-based world, we would just a single tracer object for each
+ // stack (call, subchannel_call, server_call.)
+ call->ContextSet(GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE,
+ server_call_tracer, nullptr);
+ call->ContextSet(GRPC_CONTEXT_CALL_TRACER, server_call_tracer, nullptr);
+ }
+ }
}
Call* parent = Call::FromC(args->parent);
@@ -1036,11 +1190,7 @@ void FilterStackCall::PublishAppMetadata(grpc_metadata_batch* b,
}
void FilterStackCall::RecvInitialFilter(grpc_metadata_batch* b) {
- incoming_compression_algorithm_ =
- b->Take(GrpcEncodingMetadata()).value_or(GRPC_COMPRESS_NONE);
- encodings_accepted_by_peer_ =
- b->Take(GrpcAcceptEncodingMetadata())
- .value_or(CompressionAlgorithmSet{GRPC_COMPRESS_NONE});
+ ProcessIncomingInitialMetadata(*b);
PublishAppMetadata(b, false);
}
@@ -1055,11 +1205,11 @@ void FilterStackCall::RecvTrailingFilter(grpc_metadata_batch* b,
grpc_status_code status_code = *grpc_status;
grpc_error_handle error;
if (status_code != GRPC_STATUS_OK) {
- char* peer = GetPeer();
+ Slice peer = GetPeerString();
error = grpc_error_set_int(
- GRPC_ERROR_CREATE(y_absl::StrCat("Error received from peer ", peer)),
+ GRPC_ERROR_CREATE(y_absl::StrCat("Error received from peer ",
+ peer.as_string_view())),
StatusIntProperty::kRpcStatus, static_cast<intptr_t>(status_code));
- gpr_free(peer);
}
auto grpc_message = b->Take(GrpcMessageMetadata());
if (grpc_message.has_value()) {
@@ -1136,6 +1286,8 @@ FilterStackCall::BatchControl* FilterStackCall::ReuseOrAllocateBatchControl(
*pslot = bctl;
}
bctl->call_ = this;
+ bctl->call_tracer_ = static_cast<CallTracerAnnotationInterface*>(
+ ContextGet(GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE));
bctl->op_.payload = &stream_op_payload_;
return bctl;
}
@@ -1207,11 +1359,11 @@ void FilterStackCall::BatchControl::ProcessDataAfterMetadata() {
call->receiving_message_ = false;
FinishStep(PendingOp::kRecvMessage);
} else {
- call->test_only_last_message_flags_ = call->receiving_stream_flags_;
+ call->NoteLastMessageFlags(call->receiving_stream_flags_);
if ((call->receiving_stream_flags_ & GRPC_WRITE_INTERNAL_COMPRESS) &&
- (call->incoming_compression_algorithm_ != GRPC_COMPRESS_NONE)) {
+ (call->incoming_compression_algorithm() != GRPC_COMPRESS_NONE)) {
*call->receiving_buffer_ = grpc_raw_compressed_byte_buffer_create(
- nullptr, 0, call->incoming_compression_algorithm_);
+ nullptr, 0, call->incoming_compression_algorithm());
} else {
*call->receiving_buffer_ = grpc_raw_byte_buffer_create(nullptr, 0);
}
@@ -1252,50 +1404,6 @@ void FilterStackCall::BatchControl::ReceivingStreamReady(
}
}
-void FilterStackCall::HandleCompressionAlgorithmDisabled(
- grpc_compression_algorithm compression_algorithm) {
- const char* algo_name = nullptr;
- grpc_compression_algorithm_name(compression_algorithm, &algo_name);
- TString error_msg =
- y_absl::StrFormat("Compression algorithm '%s' is disabled.", algo_name);
- gpr_log(GPR_ERROR, "%s", error_msg.c_str());
- CancelWithStatus(GRPC_STATUS_UNIMPLEMENTED, error_msg.c_str());
-}
-
-void FilterStackCall::HandleCompressionAlgorithmNotAccepted(
- grpc_compression_algorithm compression_algorithm) {
- const char* algo_name = nullptr;
- grpc_compression_algorithm_name(compression_algorithm, &algo_name);
- gpr_log(GPR_ERROR,
- "Compression algorithm ('%s') not present in the "
- "accepted encodings (%s)",
- algo_name,
- TString(encodings_accepted_by_peer_.ToString()).c_str());
-}
-
-void FilterStackCall::BatchControl::ValidateFilteredMetadata() {
- FilterStackCall* call = call_;
-
- const grpc_compression_options compression_options =
- call->channel()->compression_options();
- const grpc_compression_algorithm compression_algorithm =
- call->incoming_compression_algorithm_;
- if (GPR_UNLIKELY(!CompressionAlgorithmSet::FromUint32(
- compression_options.enabled_algorithms_bitset)
- .IsSet(compression_algorithm))) {
- // check if algorithm is supported by current channel config
- call->HandleCompressionAlgorithmDisabled(compression_algorithm);
- }
- // GRPC_COMPRESS_NONE is always set.
- GPR_DEBUG_ASSERT(call->encodings_accepted_by_peer_.IsSet(GRPC_COMPRESS_NONE));
- if (GPR_UNLIKELY(
- !call->encodings_accepted_by_peer_.IsSet(compression_algorithm))) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_compression_trace)) {
- call->HandleCompressionAlgorithmNotAccepted(compression_algorithm);
- }
- }
-}
-
void FilterStackCall::BatchControl::ReceivingInitialMetadataReady(
grpc_error_handle error) {
FilterStackCall* call = call_;
@@ -1306,9 +1414,6 @@ void FilterStackCall::BatchControl::ReceivingInitialMetadataReady(
grpc_metadata_batch* md = &call->recv_initial_metadata_;
call->RecvInitialFilter(md);
- // TODO(ctiller): this could be moved into recv_initial_filter now
- ValidateFilteredMetadata();
-
y_absl::optional<Timestamp> deadline = md->get(GrpcTimeoutMetadata());
if (deadline.has_value() && !call->is_client()) {
call_->set_send_deadline(*deadline);
@@ -1403,6 +1508,7 @@ grpc_call_error FilterStackCall::StartBatch(const grpc_op* ops, size_t nops,
grpc_transport_stream_op_batch_payload* stream_op_payload;
uint32_t seen_ops = 0;
intptr_t pending_ops = 0;
+ CallTracerAnnotationInterface* call_tracer = nullptr;
for (i = 0; i < nops; i++) {
if (seen_ops & (1u << ops[i].op)) {
@@ -1457,36 +1563,6 @@ grpc_call_error FilterStackCall::StartBatch(const grpc_op* ops, size_t nops,
error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
goto done_with_error;
}
- // TODO(juanlishen): If the user has already specified a compression
- // algorithm by setting the initial metadata with key of
- // GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, we shouldn't override that
- // with the compression algorithm mapped from compression level.
- // process compression level
- grpc_compression_level effective_compression_level =
- GRPC_COMPRESS_LEVEL_NONE;
- bool level_set = false;
- if (op->data.send_initial_metadata.maybe_compression_level.is_set) {
- effective_compression_level =
- op->data.send_initial_metadata.maybe_compression_level.level;
- level_set = true;
- } else {
- const grpc_compression_options copts =
- channel()->compression_options();
- if (copts.default_level.is_set) {
- level_set = true;
- effective_compression_level = copts.default_level.level;
- }
- }
- // Currently, only server side supports compression level setting.
- if (level_set && !is_client()) {
- const grpc_compression_algorithm calgo =
- encodings_accepted_by_peer_.CompressionAlgorithmForLevel(
- effective_compression_level);
- // The following metadata will be checked and removed by the message
- // compression filter. It will be used as the call's compression
- // algorithm.
- send_initial_metadata_.Set(GrpcInternalEncodingRequest(), calgo);
- }
if (op->data.send_initial_metadata.count > INT_MAX) {
error = GRPC_CALL_ERROR_INVALID_METADATA;
goto done_with_error;
@@ -1499,8 +1575,7 @@ grpc_call_error FilterStackCall::StartBatch(const grpc_op* ops, size_t nops,
error = GRPC_CALL_ERROR_INVALID_METADATA;
goto done_with_error;
}
- // Ignore any te metadata key value pairs specified.
- send_initial_metadata_.Remove(TeMetadata());
+ PrepareOutgoingInitialMetadata(*op, send_initial_metadata_);
// TODO(ctiller): just make these the same variable?
if (is_client() && send_deadline() != Timestamp::InfFuture()) {
send_initial_metadata_.Set(GrpcTimeoutMetadata(), send_deadline());
@@ -1515,10 +1590,6 @@ grpc_call_error FilterStackCall::StartBatch(const grpc_op* ops, size_t nops,
}
stream_op_payload->send_initial_metadata.send_initial_metadata =
&send_initial_metadata_;
- if (is_client()) {
- stream_op_payload->send_initial_metadata.peer_string =
- peer_string_atm_ptr();
- }
pending_ops |= PendingOpMask(PendingOp::kSends);
break;
}
@@ -1667,9 +1738,6 @@ grpc_call_error FilterStackCall::StartBatch(const grpc_op* ops, size_t nops,
if (is_client()) {
stream_op_payload->recv_initial_metadata.trailing_metadata_available =
&is_trailers_only_;
- } else {
- stream_op_payload->recv_initial_metadata.peer_string =
- peer_string_atm_ptr();
}
pending_ops |= PendingOpMask(PendingOp::kRecvInitialMetadata);
break;
@@ -1801,13 +1869,21 @@ grpc_call_error FilterStackCall::StartBatch(const grpc_op* ops, size_t nops,
stream_op->on_complete = &bctl->finish_batch_;
}
+ call_tracer = static_cast<CallTracerAnnotationInterface*>(
+ ContextGet(GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE));
+ if ((IsTraceRecordCallopsEnabled() && call_tracer != nullptr)) {
+ call_tracer->RecordAnnotation(y_absl::StrFormat(
+ "BATCH:%p START:%s BATCH:%s (tag:%p)", bctl,
+ PendingOpString(pending_ops).c_str(),
+ grpc_transport_stream_op_batch_string(stream_op, true).c_str(),
+ bctl->completion_data_.notify_tag.tag));
+ }
if (grpc_call_trace.enabled()) {
gpr_log(GPR_DEBUG, "BATCH:%p START:%s BATCH:%s (tag:%p)", bctl,
PendingOpString(pending_ops).c_str(),
- grpc_transport_stream_op_batch_string(stream_op).c_str(),
+ grpc_transport_stream_op_batch_string(stream_op, false).c_str(),
bctl->completion_data_.notify_tag.tag);
}
-
ExecuteBatch(stream_op, &bctl->start_batch_);
done:
@@ -1876,8 +1952,7 @@ bool ValidateMetadata(size_t count, grpc_metadata* metadata) {
// Will be folded into Call once the promise conversion is done
class PromiseBasedCall : public Call,
- public Activity,
- public Wakeable,
+ public Party,
public grpc_event_engine::experimental::EventEngine::
Closure /* for deadlines */ {
public:
@@ -1888,176 +1963,54 @@ class PromiseBasedCall : public Call,
void (*destroy)(void* value)) override;
void* ContextGet(grpc_context_index elem) const override;
void SetCompletionQueue(grpc_completion_queue* cq) override;
- void SetCompletionQueueLocked(grpc_completion_queue* cq)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
- void CancelWithError(y_absl::Status error) final Y_ABSL_LOCKS_EXCLUDED(mu_) {
- MutexLock lock(&mu_);
- CancelWithErrorLocked(std::move(error));
- }
- virtual void CancelWithErrorLocked(y_absl::Status error)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) = 0;
- bool Completed() final Y_ABSL_LOCKS_EXCLUDED(mu_) {
- MutexLock lock(&mu_);
- return completed_;
- }
-
- void Orphan() final {
- MutexLock lock(&mu_);
- if (!completed_) {
- CancelWithErrorLocked(y_absl::CancelledError("Call orphaned"));
- }
- }
+ bool Completed() final { return finished_.IsSet(); }
// Implementation of call refcounting: move this to DualRefCounted once we
// don't need to maintain FilterStackCall compatibility
- void ExternalRef() final {
- const uint64_t prev_ref_pair =
- refs_.fetch_add(MakeRefPair(1, 0), std::memory_order_relaxed);
- if (grpc_call_refcount_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%s EXTERNAL_REF: %d:%d->%d:%d", DebugTag().c_str(),
- GetStrongRefs(prev_ref_pair), GetWeakRefs(prev_ref_pair),
- GetStrongRefs(prev_ref_pair) + 1, GetWeakRefs(prev_ref_pair));
- }
- }
- void ExternalUnref() final {
- const uint64_t prev_ref_pair =
- refs_.fetch_add(MakeRefPair(-1, 1), std::memory_order_acq_rel);
- if (grpc_call_refcount_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%s EXTERNAL_UNREF: %d:%d->%d:%d", DebugTag().c_str(),
- GetStrongRefs(prev_ref_pair), GetWeakRefs(prev_ref_pair),
- GetStrongRefs(prev_ref_pair) - 1, GetWeakRefs(prev_ref_pair) + 1);
- }
- const uint32_t strong_refs = GetStrongRefs(prev_ref_pair);
- if (GPR_UNLIKELY(strong_refs == 1)) {
- Orphan();
- }
- // Now drop the weak ref.
- InternalUnref("external_ref");
- }
+ void ExternalRef() final { InternalRef("external"); }
+ void ExternalUnref() final { InternalUnref("external"); }
void InternalRef(const char* reason) final {
- uint64_t n = refs_.fetch_add(MakeRefPair(0, 1), std::memory_order_relaxed);
if (grpc_call_refcount_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%s REF: %s %d:%d->%d:%d", DebugTag().c_str(), reason,
- GetStrongRefs(n), GetWeakRefs(n), GetStrongRefs(n),
- GetWeakRefs(n) + 1);
+ gpr_log(GPR_DEBUG, "INTERNAL_REF:%p:%s", this, reason);
}
+ Party::IncrementRefCount();
}
void InternalUnref(const char* reason) final {
- const uint64_t prev_ref_pair =
- refs_.fetch_sub(MakeRefPair(0, 1), std::memory_order_acq_rel);
if (grpc_call_refcount_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%s UNREF: %s %d:%d->%d:%d", DebugTag().c_str(),
- reason, GetStrongRefs(prev_ref_pair), GetWeakRefs(prev_ref_pair),
- GetStrongRefs(prev_ref_pair), GetWeakRefs(prev_ref_pair) - 1);
- }
- if (GPR_UNLIKELY(prev_ref_pair == MakeRefPair(0, 1))) {
- DeleteThis();
+ gpr_log(GPR_DEBUG, "INTERNAL_UNREF:%p:%s", this, reason);
}
+ Party::Unref();
}
- // Activity methods
- void ForceImmediateRepoll() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) override;
- Waker MakeOwningWaker() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) override {
- InternalRef("wakeup");
-// If ASAN is defined, we leverage it to detect dropped Waker objects.
-// Usually Waker must be destroyed or woken up, but (especially with arenas)
-// it's not uncommon to create a Waker and then do neither. In that case it's
-// incredibly fraught to diagnose where the dropped reference to this object was
-// created. Instead, leverage ASAN and create a new object per expected wakeup.
-// Now when we drop such an object ASAN will fail and we'll get a callstack to
-// the creation of the waker in question.
-#if defined(__has_feature)
-#if __has_feature(address_sanitizer)
-#define GRPC_CALL_USES_ASAN_WAKER
- class AsanWaker final : public Wakeable {
- public:
- explicit AsanWaker(PromiseBasedCall* call) : call_(call) {}
-
- void Wakeup(void*) override {
- call_->Wakeup(nullptr);
- delete this;
- }
-
- void Drop(void*) override {
- call_->Drop(nullptr);
- delete this;
- }
-
- TString ActivityDebugTag(void*) const override {
- return call_->DebugTag();
- }
-
- private:
- PromiseBasedCall* call_;
- };
- return Waker(new AsanWaker(this), nullptr);
-#endif
-#endif
-#ifndef GRPC_CALL_USES_ASAN_WAKER
- return Waker(this, nullptr);
-#endif
- }
- Waker MakeNonOwningWaker() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) override;
-
- // Wakeable methods
- void Wakeup(void*) override {
- channel()->event_engine()->Run([this] {
- ApplicationCallbackExecCtx app_exec_ctx;
- ExecCtx exec_ctx;
- {
- ScopedContext activity_context(this);
- MutexLock lock(&mu_);
- Update();
- }
- InternalUnref("wakeup");
- });
- }
- void Drop(void*) override { InternalUnref("wakeup"); }
-
void RunInContext(y_absl::AnyInvocable<void()> fn) {
- if (Activity::current() == this) {
- fn();
- } else {
- InternalRef("in_context");
- channel()->event_engine()->Run([this, fn = std::move(fn)]() mutable {
- ApplicationCallbackExecCtx app_exec_ctx;
- ExecCtx exec_ctx;
- {
- ScopedContext activity_context(this);
- MutexLock lock(&mu_);
+ Spawn(
+ "run_in_context",
+ [fn = std::move(fn)]() mutable {
fn();
- Update();
- }
- InternalUnref("in_context");
- });
- }
- }
-
- grpc_compression_algorithm test_only_compression_algorithm() override {
- abort();
- }
- uint32_t test_only_message_flags() override { abort(); }
- uint32_t test_only_encodings_accepted_by_peer() override { abort(); }
- grpc_compression_algorithm compression_for_level(
- grpc_compression_level) override {
- abort();
+ return Empty{};
+ },
+ [](Empty) {});
}
// This should return nullptr for the promise stack (and alternative means
// for that functionality be invented)
grpc_call_stack* call_stack() override { return nullptr; }
- void UpdateDeadline(Timestamp deadline);
- void ResetDeadline();
+ void UpdateDeadline(Timestamp deadline) Y_ABSL_LOCKS_EXCLUDED(deadline_mu_);
+ void ResetDeadline() Y_ABSL_LOCKS_EXCLUDED(deadline_mu_);
// Implementation of EventEngine::Closure, called when deadline expires
void Run() override;
virtual ServerCallContext* server_call_context() { return nullptr; }
+ using Call::arena;
+
protected:
class ScopedContext
: public ScopedActivity,
+ public BatchBuilder,
+ public promise_detail::Context<BatchBuilder>,
public promise_detail::Context<Arena>,
public promise_detail::Context<grpc_call_context_element>,
public promise_detail::Context<CallContext>,
@@ -2065,6 +2018,8 @@ class PromiseBasedCall : public Call,
public:
explicit ScopedContext(PromiseBasedCall* call)
: ScopedActivity(call),
+ BatchBuilder(&call->batch_payload_),
+ promise_detail::Context<BatchBuilder>(this),
promise_detail::Context<Arena>(call->arena()),
promise_detail::Context<grpc_call_context_element>(call->context_),
promise_detail::Context<CallContext>(&call->call_context_),
@@ -2098,8 +2053,12 @@ class PromiseBasedCall : public Call,
};
~PromiseBasedCall() override {
- if (non_owning_wakeable_) non_owning_wakeable_->DropActivity();
if (cq_) GRPC_CQ_INTERNAL_UNREF(cq_, "bind");
+ for (int i = 0; i < GRPC_CONTEXT_COUNT; i++) {
+ if (context_[i].destroy) {
+ context_[i].destroy(context_[i].value);
+ }
+ }
}
// Enumerates why a Completion is still pending
@@ -2107,6 +2066,7 @@ class PromiseBasedCall : public Call,
// We're in the midst of starting a batch of operations
kStartingBatch = 0,
// The following correspond with the batch operations from above
+ kSendInitialMetadata,
kReceiveInitialMetadata,
kReceiveStatusOnClient,
kReceiveCloseOnServer = kReceiveStatusOnClient,
@@ -2116,10 +2076,17 @@ class PromiseBasedCall : public Call,
kSendCloseFromClient = kSendStatusFromServer,
};
+ bool RunParty() override {
+ ScopedContext ctx(this);
+ return Party::RunParty();
+ }
+
const char* PendingOpString(PendingOp reason) const {
switch (reason) {
case PendingOp::kStartingBatch:
return "StartingBatch";
+ case PendingOp::kSendInitialMetadata:
+ return "SendInitialMetadata";
case PendingOp::kReceiveInitialMetadata:
return "ReceiveInitialMetadata";
case PendingOp::kReceiveStatusOnClient:
@@ -2134,56 +2101,47 @@ class PromiseBasedCall : public Call,
return "Unknown";
}
- static constexpr uint8_t PendingOpBit(PendingOp reason) {
+ static constexpr uint32_t PendingOpBit(PendingOp reason) {
return 1 << static_cast<int>(reason);
}
- Mutex* mu() const Y_ABSL_LOCK_RETURNED(mu_) { return &mu_; }
// Begin work on a completion, recording the tag/closure to notify.
// Use the op selected in \a ops to determine the index to allocate into.
// Starts the "StartingBatch" PendingOp immediately.
// Assumes at least one operation in \a ops.
- Completion StartCompletion(void* tag, bool is_closure, const grpc_op* ops)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
+ Completion StartCompletion(void* tag, bool is_closure, const grpc_op* ops);
// Add one pending op to the completion, and return it.
- Completion AddOpToCompletion(const Completion& completion, PendingOp reason)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
+ Completion AddOpToCompletion(const Completion& completion, PendingOp reason);
// Stringify a completion
TString CompletionString(const Completion& completion) const {
return completion.has_value()
- ? y_absl::StrFormat(
- "%d:tag=%p", static_cast<int>(completion.index()),
- completion_info_[completion.index()].pending.tag)
+ ? completion_info_[completion.index()].pending.ToString(this)
: "no-completion";
}
// Finish one op on the completion. Must have been previously been added.
// The completion as a whole finishes when all pending ops finish.
- void FinishOpOnCompletion(Completion* completion, PendingOp reason)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
+ void FinishOpOnCompletion(Completion* completion, PendingOp reason);
// Mark the completion as failed. Does not finish it.
void FailCompletion(const Completion& completion,
SourceLocation source_location = {});
- // Run the promise polling loop until it stalls.
- void Update() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
- // Update the promise state once.
- virtual void UpdateOnce() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) = 0;
+ // Mark the completion as infallible. Overrides FailCompletion to report
+ // success always.
+ void ForceCompletionSuccess(const Completion& completion);
// Accept the stats from the context (call once we have proof the transport is
// done with them).
// Right now this means that promise based calls do not record correct stats
// with census if they are cancelled.
// TODO(ctiller): this should be remedied before promise based calls are
// dexperimentalized.
- void AcceptTransportStatsFromContext() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ void AcceptTransportStatsFromContext() {
final_stats_ = *call_context_.call_stats();
}
- grpc_completion_queue* cq() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) { return cq_; }
+ grpc_completion_queue* cq() { return cq_; }
void CToMetadata(grpc_metadata* metadata, size_t count,
grpc_metadata_batch* batch);
- TString ActivityDebugTag(void*) const override { return DebugTag(); }
-
// At the end of the call run any finalization actions.
void RunFinalization(grpc_status_code status, const char* status_details) {
grpc_call_final_info final_info;
@@ -2212,158 +2170,163 @@ class PromiseBasedCall : public Call,
}
}
- TString PollStateDebugString() const Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
- return y_absl::StrCat(PresentAndCompletionText("outstanding_send",
- outstanding_send_.has_value(),
- send_message_completion_)
- .c_str(),
- PresentAndCompletionText("outstanding_recv",
- outstanding_recv_.has_value(),
- recv_message_completion_)
- .c_str());
- }
-
+ // Spawn a job that will first do FirstPromise then receive a message
+ template <typename FirstPromise>
void StartRecvMessage(const grpc_op& op, const Completion& completion,
- PipeReceiver<MessageHandle>* receiver)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
- void PollRecvMessage(grpc_compression_algorithm compression_algorithm)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
- void CancelRecvMessage() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
+ FirstPromise first,
+ PipeReceiver<MessageHandle>* receiver,
+ Party::BulkSpawner& spawner);
void StartSendMessage(const grpc_op& op, const Completion& completion,
- PipeSender<MessageHandle>* sender)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
- bool PollSendMessage() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
- void CancelSendMessage() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
+ PipeSender<MessageHandle>* sender,
+ Party::BulkSpawner& spawner);
+
+ void set_completed() { finished_.Set(); }
- bool completed() const Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
- return completed_;
+ // Returns a promise that resolves to Empty whenever the call is completed.
+ auto finished() { return finished_.Wait(); }
+
+ // Returns a promise that resolves to Empty whenever there is no outstanding
+ // send operation
+ auto WaitForSendingStarted() {
+ return [this]() -> Poll<Empty> {
+ int n = sends_queued_.load(std::memory_order_relaxed);
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[call] WaitForSendingStarted n=%d",
+ DebugTag().c_str(), n);
+ }
+ if (n != 0) return waiting_for_queued_sends_.pending();
+ return Empty{};
+ };
}
- void set_completed() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) { completed_ = true; }
- bool is_sending() const Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
- return outstanding_send_.has_value();
+
+ // Mark that a send has been queued - blocks sending trailing metadata.
+ void QueueSend() {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[call] QueueSend", DebugTag().c_str());
+ }
+ sends_queued_.fetch_add(1, std::memory_order_relaxed);
+ }
+ // Mark that a send has been dequeued - allows sending trailing metadata once
+ // zero sends are queued.
+ void EnactSend() {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[call] EnactSend", DebugTag().c_str());
+ }
+ if (1 == sends_queued_.fetch_sub(1, std::memory_order_relaxed)) {
+ waiting_for_queued_sends_.Wake();
+ }
}
private:
union CompletionInfo {
+ static constexpr uint32_t kOpFailed = 0x8000'0000u;
+ static constexpr uint32_t kOpForceSuccess = 0x4000'0000u;
+ CompletionInfo() {}
+ enum CompletionState {
+ kPending,
+ kSuccess,
+ kFailure,
+ };
struct Pending {
- // Bitmask of PendingOps
- uint8_t pending_op_bits;
+ // Bitmask of PendingOps at the bottom, and kOpFailed, kOpForceSuccess at
+ // the top.
+ std::atomic<uint32_t> state;
bool is_closure;
- bool success;
+ // True if this completion was for a recv_message op.
+ // In that case if the completion as a whole fails we need to cleanup the
+ // returned message.
+ bool is_recv_message;
void* tag;
- } pending;
- grpc_cq_completion completion;
- };
- class NonOwningWakable final : public Wakeable {
- public:
- explicit NonOwningWakable(PromiseBasedCall* call) : call_(call) {}
-
- // Ref the Handle (not the activity).
- void Ref() { refs_.fetch_add(1, std::memory_order_relaxed); }
-
- // Activity is going away... drop its reference and sever the connection
- // back.
- void DropActivity() Y_ABSL_LOCKS_EXCLUDED(mu_) {
- auto unref = y_absl::MakeCleanup([this]() { Unref(); });
- MutexLock lock(&mu_);
- GPR_ASSERT(call_ != nullptr);
- call_ = nullptr;
- }
+ void Start(bool is_closure, void* tag) {
+ this->is_closure = is_closure;
+ this->is_recv_message = false;
+ this->tag = tag;
+ state.store(PendingOpBit(PendingOp::kStartingBatch),
+ std::memory_order_release);
+ }
- // Activity needs to wake up (if it still exists!) - wake it up, and drop
- // the ref that was kept for this handle.
- void Wakeup(void*) override Y_ABSL_LOCKS_EXCLUDED(mu_) {
- // Drop the ref to the handle at end of scope (we have one ref = one
- // wakeup semantics).
- auto unref = y_absl::MakeCleanup([this]() { Unref(); });
- ReleasableMutexLock lock(&mu_);
- // Note that activity refcount can drop to zero, but we could win the lock
- // against DropActivity, so we need to only increase activities refcount
- // if it is non-zero.
- PromiseBasedCall* call = call_;
- if (call != nullptr && call->RefIfNonZero()) {
- lock.Release();
- // Activity still exists and we have a reference: wake it up, which will
- // drop the ref.
- call->Wakeup(nullptr);
+ void AddPendingBit(PendingOp reason) {
+ if (reason == PendingOp::kReceiveMessage) is_recv_message = true;
+ auto prev =
+ state.fetch_or(PendingOpBit(reason), std::memory_order_relaxed);
+ GPR_ASSERT((prev & PendingOpBit(reason)) == 0);
}
- }
- TString ActivityDebugTag(void*) const override {
- MutexLock lock(&mu_);
- return call_ == nullptr ? "<unknown>" : call_->DebugTag();
- }
+ CompletionState RemovePendingBit(PendingOp reason) {
+ const uint32_t mask = ~PendingOpBit(reason);
+ auto prev = state.fetch_and(mask, std::memory_order_acq_rel);
+ GPR_ASSERT((prev & PendingOpBit(reason)) != 0);
+ switch (prev & mask) {
+ case kOpFailed:
+ return kFailure;
+ case kOpFailed | kOpForceSuccess:
+ case kOpForceSuccess:
+ case 0:
+ return kSuccess;
+ default:
+ return kPending;
+ }
+ }
- void Drop(void*) override { Unref(); }
+ void MarkFailed() {
+ state.fetch_or(kOpFailed, std::memory_order_relaxed);
+ }
- private:
- // Unref the Handle (not the activity).
- void Unref() {
- if (1 == refs_.fetch_sub(1, std::memory_order_acq_rel)) {
- delete this;
+ void MarkForceSuccess() {
+ state.fetch_or(kOpForceSuccess, std::memory_order_relaxed);
}
- }
- mutable Mutex mu_;
- // We have two initial refs: one for the wakeup that this is created for,
- // and will be dropped by Wakeup, and the other for the activity which is
- // dropped by DropActivity.
- std::atomic<size_t> refs_{2};
- PromiseBasedCall* call_ Y_ABSL_GUARDED_BY(mu_);
+ TString ToString(const PromiseBasedCall* call) const {
+ auto state = this->state.load(std::memory_order_relaxed);
+ std::vector<y_absl::string_view> pending_ops;
+ for (size_t i = 0; i < 24; i++) {
+ if (state & (1u << i)) {
+ pending_ops.push_back(
+ call->PendingOpString(static_cast<PendingOp>(i)));
+ }
+ }
+ return y_absl::StrFormat("{%s}%s:tag=%p", y_absl::StrJoin(pending_ops, ","),
+ (state & kOpForceSuccess) ? ":force-success"
+ : (state & kOpFailed) ? ":failed"
+ : ":success",
+ tag);
+ }
+ } pending;
+ grpc_cq_completion completion;
};
- static void OnDestroy(void* arg, grpc_error_handle) {
- auto* call = static_cast<PromiseBasedCall*>(arg);
- ScopedContext context(call);
- call->DeleteThis();
- }
-
- // First 32 bits are strong refs, next 32 bits are weak refs.
- static uint64_t MakeRefPair(uint32_t strong, uint32_t weak) {
- return (static_cast<uint64_t>(strong) << 32) + static_cast<int64_t>(weak);
- }
- static uint32_t GetStrongRefs(uint64_t ref_pair) {
- return static_cast<uint32_t>(ref_pair >> 32);
- }
- static uint32_t GetWeakRefs(uint64_t ref_pair) {
- return static_cast<uint32_t>(ref_pair & 0xffffffffu);
- }
-
- bool RefIfNonZero() {
- uint64_t prev_ref_pair = refs_.load(std::memory_order_acquire);
- do {
- const uint32_t strong_refs = GetStrongRefs(prev_ref_pair);
- if (strong_refs == 0) return false;
- } while (!refs_.compare_exchange_weak(
- prev_ref_pair, prev_ref_pair + MakeRefPair(1, 0),
- std::memory_order_acq_rel, std::memory_order_acquire));
- return true;
+ void PartyOver() override {
+ {
+ ScopedContext ctx(this);
+ CancelRemainingParticipants();
+ arena()->DestroyManagedNewObjects();
+ }
+ DeleteThis();
}
- mutable Mutex mu_;
- std::atomic<uint64_t> refs_;
CallContext call_context_{this};
- bool keep_polling_ Y_ABSL_GUARDED_BY(mu()) = false;
// Contexts for various subsystems (security, tracing, ...).
grpc_call_context_element context_[GRPC_CONTEXT_COUNT] = {};
- grpc_completion_queue* cq_ Y_ABSL_GUARDED_BY(mu_);
- NonOwningWakable* non_owning_wakeable_ Y_ABSL_GUARDED_BY(mu_) = nullptr;
+ grpc_completion_queue* cq_;
CompletionInfo completion_info_[6];
grpc_call_stats final_stats_{};
CallFinalization finalization_;
// Current deadline.
- Timestamp deadline_ = Timestamp::InfFuture();
- grpc_event_engine::experimental::EventEngine::TaskHandle deadline_task_;
- y_absl::optional<PipeSender<MessageHandle>::PushType> outstanding_send_
- Y_ABSL_GUARDED_BY(mu_);
- y_absl::optional<PipeReceiverNextType<MessageHandle>> outstanding_recv_
- Y_ABSL_GUARDED_BY(mu_);
- grpc_byte_buffer** recv_message_ Y_ABSL_GUARDED_BY(mu_) = nullptr;
- Completion send_message_completion_ Y_ABSL_GUARDED_BY(mu_);
- Completion recv_message_completion_ Y_ABSL_GUARDED_BY(mu_);
- bool completed_ Y_ABSL_GUARDED_BY(mu_) = false;
+ Mutex deadline_mu_;
+ Timestamp deadline_ Y_ABSL_GUARDED_BY(deadline_mu_) = Timestamp::InfFuture();
+ grpc_event_engine::experimental::EventEngine::TaskHandle Y_ABSL_GUARDED_BY(
+ deadline_mu_) deadline_task_;
+ ExternallyObservableLatch<void> finished_;
+ // Non-zero with an outstanding GRPC_OP_SEND_INITIAL_METADATA or
+ // GRPC_OP_SEND_MESSAGE (one count each), and 0 once those payloads have been
+ // pushed onto the outgoing pipe.
+ std::atomic<uint8_t> sends_queued_{0};
+ // Waiter for when sends_queued_ becomes 0.
+ IntraActivityWaiter waiting_for_queued_sends_;
+ grpc_byte_buffer** recv_message_ = nullptr;
+ grpc_transport_stream_op_batch_payload batch_payload_{context_};
};
template <typename T>
@@ -2383,7 +2346,7 @@ PromiseBasedCall::PromiseBasedCall(Arena* arena, uint32_t initial_external_refs,
const grpc_call_create_args& args)
: Call(arena, args.server_transport_data == nullptr, args.send_deadline,
args.channel->Ref()),
- refs_(MakeRefPair(initial_external_refs, 0)),
+ Party(arena, initial_external_refs),
cq_(args.cq) {
if (args.cq != nullptr) {
GPR_ASSERT(args.pollset_set_alternative == nullptr &&
@@ -2399,15 +2362,6 @@ PromiseBasedCall::PromiseBasedCall(Arena* arena, uint32_t initial_external_refs,
}
}
-Waker PromiseBasedCall::MakeNonOwningWaker() {
- if (non_owning_wakeable_ == nullptr) {
- non_owning_wakeable_ = new NonOwningWakable(this);
- } else {
- non_owning_wakeable_->Ref();
- }
- return Waker(non_owning_wakeable_, nullptr);
-}
-
void PromiseBasedCall::CToMetadata(grpc_metadata* metadata, size_t count,
grpc_metadata_batch* b) {
for (size_t i = 0; i < count; i++) {
@@ -2442,15 +2396,14 @@ void* PromiseBasedCall::ContextGet(grpc_context_index elem) const {
PromiseBasedCall::Completion PromiseBasedCall::StartCompletion(
void* tag, bool is_closure, const grpc_op* ops) {
Completion c(BatchSlotForOp(ops[0].op));
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[call] StartCompletion %s tag=%p", DebugTag().c_str(),
- CompletionString(c).c_str(), tag);
- }
if (!is_closure) {
grpc_cq_begin_op(cq(), tag);
}
- completion_info_[c.index()].pending = {
- PendingOpBit(PendingOp::kStartingBatch), is_closure, true, tag};
+ completion_info_[c.index()].pending.Start(is_closure, tag);
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_INFO, "%s[call] StartCompletion %s", DebugTag().c_str(),
+ CompletionString(c).c_str());
+ }
return c;
}
@@ -2461,10 +2414,7 @@ PromiseBasedCall::Completion PromiseBasedCall::AddOpToCompletion(
CompletionString(completion).c_str(), PendingOpString(reason));
}
GPR_ASSERT(completion.has_value());
- auto& pending_op_bits =
- completion_info_[completion.index()].pending.pending_op_bits;
- GPR_ASSERT((pending_op_bits & PendingOpBit(reason)) == 0);
- pending_op_bits |= PendingOpBit(reason);
+ completion_info_[completion.index()].pending.AddPendingBit(reason);
return Completion(completion.index());
}
@@ -2475,64 +2425,50 @@ void PromiseBasedCall::FailCompletion(const Completion& completion,
"%s[call] FailCompletion %s", DebugTag().c_str(),
CompletionString(completion).c_str());
}
- completion_info_[completion.index()].pending.success = false;
+ completion_info_[completion.index()].pending.MarkFailed();
+}
+
+void PromiseBasedCall::ForceCompletionSuccess(const Completion& completion) {
+ completion_info_[completion.index()].pending.MarkForceSuccess();
}
void PromiseBasedCall::FinishOpOnCompletion(Completion* completion,
PendingOp reason) {
if (grpc_call_trace.enabled()) {
- auto pending_op_bits =
- completion_info_[completion->index()].pending.pending_op_bits;
- bool success = completion_info_[completion->index()].pending.success;
- std::vector<const char*> pending;
- for (size_t i = 0; i < 8 * sizeof(pending_op_bits); i++) {
- if (static_cast<PendingOp>(i) == reason) continue;
- if (pending_op_bits & (1 << i)) {
- pending.push_back(PendingOpString(static_cast<PendingOp>(i)));
- }
- }
- gpr_log(
- GPR_INFO, "%s[call] FinishOpOnCompletion tag:%p %s %s %s",
- DebugTag().c_str(), completion_info_[completion->index()].pending.tag,
- CompletionString(*completion).c_str(), PendingOpString(reason),
- (pending.empty()
- ? (success ? TString("done") : TString("failed"))
- : y_absl::StrFormat("pending_ops={%s}", y_absl::StrJoin(pending, ",")))
- .c_str());
+ gpr_log(GPR_INFO, "%s[call] FinishOpOnCompletion completion:%s finish:%s",
+ DebugTag().c_str(), CompletionString(*completion).c_str(),
+ PendingOpString(reason));
}
const uint8_t i = completion->TakeIndex();
GPR_ASSERT(i < GPR_ARRAY_SIZE(completion_info_));
CompletionInfo::Pending& pending = completion_info_[i].pending;
- GPR_ASSERT(pending.pending_op_bits & PendingOpBit(reason));
- pending.pending_op_bits &= ~PendingOpBit(reason);
- auto error = pending.success ? y_absl::OkStatus() : y_absl::CancelledError();
- if (pending.pending_op_bits == 0) {
- if (pending.is_closure) {
- ExecCtx::Run(DEBUG_LOCATION, static_cast<grpc_closure*>(pending.tag),
- error);
- } else {
- grpc_cq_end_op(
- cq(), pending.tag, error, [](void*, grpc_cq_completion*) {}, nullptr,
- &completion_info_[i].completion);
- }
+ bool success;
+ switch (pending.RemovePendingBit(reason)) {
+ case CompletionInfo::kPending:
+ return; // Early out
+ case CompletionInfo::kSuccess:
+ success = true;
+ break;
+ case CompletionInfo::kFailure:
+ success = false;
+ break;
+ }
+ if (pending.is_recv_message && !success && *recv_message_ != nullptr) {
+ grpc_byte_buffer_destroy(*recv_message_);
+ *recv_message_ = nullptr;
+ }
+ auto error = success ? y_absl::OkStatus() : y_absl::CancelledError();
+ if (pending.is_closure) {
+ ExecCtx::Run(DEBUG_LOCATION, static_cast<grpc_closure*>(pending.tag),
+ error);
+ } else {
+ grpc_cq_end_op(
+ cq(), pending.tag, error, [](void*, grpc_cq_completion*) {}, nullptr,
+ &completion_info_[i].completion);
}
}
-void PromiseBasedCall::Update() {
- keep_polling_ = false;
- do {
- UpdateOnce();
- } while (std::exchange(keep_polling_, false));
-}
-
-void PromiseBasedCall::ForceImmediateRepoll() { keep_polling_ = true; }
-
void PromiseBasedCall::SetCompletionQueue(grpc_completion_queue* cq) {
- MutexLock lock(&mu_);
- SetCompletionQueueLocked(cq);
-}
-
-void PromiseBasedCall::SetCompletionQueueLocked(grpc_completion_queue* cq) {
cq_ = cq;
GRPC_CQ_INTERNAL_REF(cq, "bind");
call_context_.pollent_ =
@@ -2540,6 +2476,12 @@ void PromiseBasedCall::SetCompletionQueueLocked(grpc_completion_queue* cq) {
}
void PromiseBasedCall::UpdateDeadline(Timestamp deadline) {
+ MutexLock lock(&deadline_mu_);
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[call] UpdateDeadline from=%s to=%s",
+ DebugTag().c_str(), deadline_.ToString().c_str(),
+ deadline.ToString().c_str());
+ }
if (deadline >= deadline_) return;
auto* const event_engine = channel()->event_engine();
if (deadline_ != Timestamp::InfFuture()) {
@@ -2547,10 +2489,12 @@ void PromiseBasedCall::UpdateDeadline(Timestamp deadline) {
} else {
InternalRef("deadline");
}
- event_engine->RunAfter(deadline - Timestamp::Now(), this);
+ deadline_ = deadline;
+ deadline_task_ = event_engine->RunAfter(deadline - Timestamp::Now(), this);
}
void PromiseBasedCall::ResetDeadline() {
+ MutexLock lock(&deadline_mu_);
if (deadline_ == Timestamp::InfFuture()) return;
auto* const event_engine = channel()->event_engine();
if (!event_engine->Cancel(deadline_task_)) return;
@@ -2567,117 +2511,88 @@ void PromiseBasedCall::Run() {
void PromiseBasedCall::StartSendMessage(const grpc_op& op,
const Completion& completion,
- PipeSender<MessageHandle>* sender) {
- GPR_ASSERT(!outstanding_send_.has_value());
- if (!completed_) {
- send_message_completion_ =
- AddOpToCompletion(completion, PendingOp::kSendMessage);
- SliceBuffer send;
- grpc_slice_buffer_swap(
- &op.data.send_message.send_message->data.raw.slice_buffer,
- send.c_slice_buffer());
- outstanding_send_.emplace(sender->Push(
- GetContext<Arena>()->MakePooled<Message>(std::move(send), op.flags)));
- } else {
- FailCompletion(completion);
- }
+ PipeSender<MessageHandle>* sender,
+ Party::BulkSpawner& spawner) {
+ QueueSend();
+ SliceBuffer send;
+ grpc_slice_buffer_swap(
+ &op.data.send_message.send_message->data.raw.slice_buffer,
+ send.c_slice_buffer());
+ auto msg = arena()->MakePooled<Message>(std::move(send), op.flags);
+ spawner.Spawn(
+ "call_send_message",
+ [this, sender, msg = std::move(msg)]() mutable {
+ EnactSend();
+ return sender->Push(std::move(msg));
+ },
+ [this, completion = AddOpToCompletion(
+ completion, PendingOp::kSendMessage)](bool result) mutable {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%sSendMessage completes %s", DebugTag().c_str(),
+ result ? "successfully" : "with failure");
+ }
+ if (!result) FailCompletion(completion);
+ FinishOpOnCompletion(&completion, PendingOp::kSendMessage);
+ });
}
-bool PromiseBasedCall::PollSendMessage() {
- if (!outstanding_send_.has_value()) return true;
- Poll<bool> r = (*outstanding_send_)();
- if (const bool* result = r.value_if_ready()) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_DEBUG, "%sPollSendMessage completes %s", DebugTag().c_str(),
- *result ? "successfully" : "with failure");
- }
- if (!*result) {
- FailCompletion(send_message_completion_);
- return false;
- }
- FinishOpOnCompletion(&send_message_completion_, PendingOp::kSendMessage);
- outstanding_send_.reset();
+template <typename FirstPromiseFactory>
+void PromiseBasedCall::StartRecvMessage(
+ const grpc_op& op, const Completion& completion,
+ FirstPromiseFactory first_promise_factory,
+ PipeReceiver<MessageHandle>* receiver, Party::BulkSpawner& spawner) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_INFO, "%s[call] Start RecvMessage: %s", DebugTag().c_str(),
+ CompletionString(completion).c_str());
}
- return true;
-}
-
-void PromiseBasedCall::CancelSendMessage() {
- if (!outstanding_send_.has_value()) return;
- FinishOpOnCompletion(&send_message_completion_, PendingOp::kSendMessage);
- outstanding_send_.reset();
-}
-
-void PromiseBasedCall::StartRecvMessage(const grpc_op& op,
- const Completion& completion,
- PipeReceiver<MessageHandle>* receiver) {
- GPR_ASSERT(!outstanding_recv_.has_value());
recv_message_ = op.data.recv_message.recv_message;
- recv_message_completion_ =
- AddOpToCompletion(completion, PendingOp::kReceiveMessage);
- outstanding_recv_.emplace(receiver->Next());
-}
-
-void PromiseBasedCall::PollRecvMessage(
- grpc_compression_algorithm incoming_compression_algorithm) {
- if (!outstanding_recv_.has_value()) return;
- Poll<NextResult<MessageHandle>> r = (*outstanding_recv_)();
- if (auto* result = r.value_if_ready()) {
- outstanding_recv_.reset();
- if (result->has_value()) {
- MessageHandle& message = **result;
- if ((message->flags() & GRPC_WRITE_INTERNAL_COMPRESS) &&
- (incoming_compression_algorithm != GRPC_COMPRESS_NONE)) {
- *recv_message_ = grpc_raw_compressed_byte_buffer_create(
- nullptr, 0, incoming_compression_algorithm);
- } else {
- *recv_message_ = grpc_raw_byte_buffer_create(nullptr, 0);
- }
- grpc_slice_buffer_move_into(message->payload()->c_slice_buffer(),
- &(*recv_message_)->data.raw.slice_buffer);
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[call] PollRecvMessage: outstanding_recv finishes: received "
- "%" PRIdPTR " byte message",
- DebugTag().c_str(),
- (*recv_message_)->data.raw.slice_buffer.length);
- }
- } else if (result->cancelled()) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[call] PollRecvMessage: outstanding_recv finishes: received "
- "end-of-stream with error",
- DebugTag().c_str());
- }
- FailCompletion(recv_message_completion_);
- *recv_message_ = nullptr;
- } else {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[call] PollRecvMessage: outstanding_recv finishes: received "
- "end-of-stream",
- DebugTag().c_str());
- }
- *recv_message_ = nullptr;
- }
- FinishOpOnCompletion(&recv_message_completion_, PendingOp::kReceiveMessage);
- } else if (completed_) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO,
- "%s[call] UpdateOnce: outstanding_recv finishes: promise has "
- "completed without queuing a message, forcing end-of-stream",
- DebugTag().c_str());
- }
- outstanding_recv_.reset();
- *recv_message_ = nullptr;
- FinishOpOnCompletion(&recv_message_completion_, PendingOp::kReceiveMessage);
- }
-}
-
-void PromiseBasedCall::CancelRecvMessage() {
- if (!outstanding_recv_.has_value()) return;
- *recv_message_ = nullptr;
- outstanding_recv_.reset();
- FinishOpOnCompletion(&recv_message_completion_, PendingOp::kReceiveMessage);
+ spawner.Spawn(
+ "call_recv_message",
+ [first_promise_factory = std::move(first_promise_factory), receiver]() {
+ return Seq(first_promise_factory(), receiver->Next());
+ },
+ [this,
+ completion = AddOpToCompletion(completion, PendingOp::kReceiveMessage)](
+ NextResult<MessageHandle> result) mutable {
+ if (result.has_value()) {
+ MessageHandle& message = *result;
+ NoteLastMessageFlags(message->flags());
+ if ((message->flags() & GRPC_WRITE_INTERNAL_COMPRESS) &&
+ (incoming_compression_algorithm() != GRPC_COMPRESS_NONE)) {
+ *recv_message_ = grpc_raw_compressed_byte_buffer_create(
+ nullptr, 0, incoming_compression_algorithm());
+ } else {
+ *recv_message_ = grpc_raw_byte_buffer_create(nullptr, 0);
+ }
+ grpc_slice_buffer_move_into(message->payload()->c_slice_buffer(),
+ &(*recv_message_)->data.raw.slice_buffer);
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "%s[call] RecvMessage: outstanding_recv "
+ "finishes: received %" PRIdPTR " byte message",
+ DebugTag().c_str(),
+ (*recv_message_)->data.raw.slice_buffer.length);
+ }
+ } else if (result.cancelled()) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "%s[call] RecvMessage: outstanding_recv "
+ "finishes: received end-of-stream with error",
+ DebugTag().c_str());
+ }
+ FailCompletion(completion);
+ *recv_message_ = nullptr;
+ } else {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "%s[call] RecvMessage: outstanding_recv "
+ "finishes: received end-of-stream",
+ DebugTag().c_str());
+ }
+ *recv_message_ = nullptr;
+ }
+ FinishOpOnCompletion(&completion, PendingOp::kReceiveMessage);
+ });
}
///////////////////////////////////////////////////////////////////////////////
@@ -2693,10 +2608,6 @@ void CallContext::IncrementRefCount(const char* reason) {
void CallContext::Unref(const char* reason) { call_->InternalUnref(reason); }
-gpr_atm* CallContext::peer_string_atm_ptr() {
- return call_->peer_string_atm_ptr();
-}
-
void CallContext::UpdateDeadline(Timestamp deadline) {
call_->UpdateDeadline(deadline);
}
@@ -2750,24 +2661,40 @@ class ClientPromiseBasedCall final : public PromiseBasedCall {
~ClientPromiseBasedCall() override {
ScopedContext context(this);
send_initial_metadata_.reset();
- recv_status_on_client_ = y_absl::monostate();
- promise_ = ArenaPromise<ServerMetadataHandle>();
- // Need to destroy the pipes under the ScopedContext above, so we move them
- // out here and then allow the destructors to run at end of scope, but
- // before context.
+ // Need to destroy the pipes under the ScopedContext above, so we
+ // move them out here and then allow the destructors to run at
+ // end of scope, but before context.
auto c2s = std::move(client_to_server_messages_);
auto s2c = std::move(server_to_client_messages_);
auto sim = std::move(server_initial_metadata_);
}
- y_absl::string_view GetServerAuthority() const override { abort(); }
- void CancelWithErrorLocked(grpc_error_handle error) override
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu());
- bool is_trailers_only() const override {
- MutexLock lock(mu());
- return is_trailers_only_;
+ void CancelWithError(y_absl::Status error) override {
+ if (!started_.exchange(true, std::memory_order_relaxed)) {
+ // Initial metadata not sent yet, so we can just fail the call.
+ Spawn(
+ "cancel_before_initial_metadata",
+ [error = std::move(error), this]() {
+ server_to_client_messages_.sender.Close();
+ Finish(ServerMetadataFromStatus(error));
+ return Empty{};
+ },
+ [](Empty) {});
+ } else {
+ Spawn(
+ "cancel_with_error",
+ [error = std::move(error), this]() {
+ if (!cancel_error_.is_set()) {
+ cancel_error_.Set(ServerMetadataFromStatus(error));
+ }
+ return Empty{};
+ },
+ [](Empty) {});
+ }
}
- bool failed_before_recv_message() const override { abort(); }
+ y_absl::string_view GetServerAuthority() const override { abort(); }
+ bool is_trailers_only() const override { return is_trailers_only_; }
+ bool failed_before_recv_message() const override { return false; }
grpc_call_error StartBatch(const grpc_op* ops, size_t nops, void* notify_tag,
bool is_notify_tag_closure) override;
@@ -2777,65 +2704,79 @@ class ClientPromiseBasedCall final : public PromiseBasedCall {
}
private:
- // Poll the underlying promise (and sundry objects) once.
- void UpdateOnce() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu()) override;
// Finish the call with the given status/trailing metadata.
- void Finish(ServerMetadataHandle trailing_metadata)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu());
+ void Finish(ServerMetadataHandle trailing_metadata);
// Validate that a set of ops is valid for a client call.
- grpc_call_error ValidateBatch(const grpc_op* ops, size_t nops) const
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu());
+ grpc_call_error ValidateBatch(const grpc_op* ops, size_t nops) const;
// Commit a valid batch of operations to be executed.
void CommitBatch(const grpc_op* ops, size_t nops,
- const Completion& completion)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu());
+ const Completion& completion);
// Start the underlying promise.
- void StartPromise(ClientMetadataHandle client_initial_metadata)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu());
+ void StartPromise(ClientMetadataHandle client_initial_metadata,
+ const Completion& completion, Party::BulkSpawner& spawner);
+ // Start receiving initial metadata
+ void StartRecvInitialMetadata(grpc_metadata_array* array,
+ const Completion& completion,
+ Party::BulkSpawner& spawner);
+ void StartRecvStatusOnClient(
+ const Completion& completion,
+ grpc_op::grpc_op_data::grpc_op_recv_status_on_client op_args,
+ Party::BulkSpawner& spawner);
// Publish status out to the application.
void PublishStatus(
grpc_op::grpc_op_data::grpc_op_recv_status_on_client op_args,
- ServerMetadataHandle trailing_metadata)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu());
+ ServerMetadataHandle trailing_metadata);
// Publish server initial metadata out to the application.
- void PublishInitialMetadata(ServerMetadata* metadata)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu());
-
- ArenaPromise<ServerMetadataHandle> promise_ Y_ABSL_GUARDED_BY(mu());
- Pipe<ServerMetadataHandle> server_initial_metadata_ Y_ABSL_GUARDED_BY(mu()){
- arena()};
- Pipe<MessageHandle> client_to_server_messages_ Y_ABSL_GUARDED_BY(mu()){arena()};
- Pipe<MessageHandle> server_to_client_messages_ Y_ABSL_GUARDED_BY(mu()){arena()};
+ void PublishInitialMetadata(ServerMetadata* metadata);
ClientMetadataHandle send_initial_metadata_;
- grpc_metadata_array* recv_initial_metadata_ Y_ABSL_GUARDED_BY(mu()) = nullptr;
- y_absl::variant<y_absl::monostate,
- grpc_op::grpc_op_data::grpc_op_recv_status_on_client,
- ServerMetadataHandle>
- recv_status_on_client_ Y_ABSL_GUARDED_BY(mu());
- y_absl::optional<PipeReceiverNextType<ServerMetadataHandle>>
- server_initial_metadata_ready_;
- y_absl::optional<grpc_compression_algorithm> incoming_compression_algorithm_;
- Completion recv_initial_metadata_completion_ Y_ABSL_GUARDED_BY(mu());
- Completion recv_status_on_client_completion_ Y_ABSL_GUARDED_BY(mu());
- Completion close_send_completion_ Y_ABSL_GUARDED_BY(mu());
- bool is_trailers_only_ Y_ABSL_GUARDED_BY(mu());
+ Pipe<ServerMetadataHandle> server_initial_metadata_{arena()};
+ Latch<ServerMetadataHandle> server_trailing_metadata_;
+ Latch<ServerMetadataHandle> cancel_error_;
+ Pipe<MessageHandle> client_to_server_messages_{arena()};
+ Pipe<MessageHandle> server_to_client_messages_{arena()};
+ bool is_trailers_only_;
+ // True once the promise for the call is started.
+ // This corresponds to sending initial metadata, or cancelling before doing
+ // so.
+ // In the latter case real world code sometimes does not sent the initial
+ // metadata, and so gating based upon that does not work out.
+ std::atomic<bool> started_{false};
};
void ClientPromiseBasedCall::StartPromise(
- ClientMetadataHandle client_initial_metadata) {
- GPR_ASSERT(!promise_.has_value());
- promise_ = channel()->channel_stack()->MakeClientCallPromise(CallArgs{
- std::move(client_initial_metadata),
- &server_initial_metadata_.sender,
- &client_to_server_messages_.receiver,
- &server_to_client_messages_.sender,
- });
-}
-
-void ClientPromiseBasedCall::CancelWithErrorLocked(grpc_error_handle error) {
- ScopedContext context(this);
- Finish(ServerMetadataFromStatus(grpc_error_to_absl_status(error)));
+ ClientMetadataHandle client_initial_metadata, const Completion& completion,
+ Party::BulkSpawner& spawner) {
+ auto token = ClientInitialMetadataOutstandingToken::New(arena());
+ spawner.Spawn(
+ "call_send_initial_metadata", token.Wait(),
+ [this,
+ completion = AddOpToCompletion(
+ completion, PendingOp::kSendInitialMetadata)](bool result) mutable {
+ if (!result) FailCompletion(completion);
+ FinishOpOnCompletion(&completion, PendingOp::kSendInitialMetadata);
+ });
+ spawner.Spawn(
+ "client_promise",
+ [this, client_initial_metadata = std::move(client_initial_metadata),
+ token = std::move(token)]() mutable {
+ return Race(
+ cancel_error_.Wait(),
+ Map(channel()->channel_stack()->MakeClientCallPromise(
+ CallArgs{std::move(client_initial_metadata),
+ std::move(token), &server_initial_metadata_.sender,
+ &client_to_server_messages_.receiver,
+ &server_to_client_messages_.sender}),
+ [this](ServerMetadataHandle trailing_metadata) {
+ // If we're cancelled the transport doesn't get to return
+ // stats.
+ AcceptTransportStatsFromContext();
+ return trailing_metadata;
+ }));
+ },
+ [this](ServerMetadataHandle trailing_metadata) {
+ Finish(std::move(trailing_metadata));
+ });
}
grpc_call_error ClientPromiseBasedCall::ValidateBatch(const grpc_op* ops,
@@ -2876,49 +2817,61 @@ grpc_call_error ClientPromiseBasedCall::ValidateBatch(const grpc_op* ops,
void ClientPromiseBasedCall::CommitBatch(const grpc_op* ops, size_t nops,
const Completion& completion) {
+ Party::BulkSpawner spawner(this);
for (size_t op_idx = 0; op_idx < nops; op_idx++) {
const grpc_op& op = ops[op_idx];
switch (op.op) {
case GRPC_OP_SEND_INITIAL_METADATA: {
- // compression not implemented
- GPR_ASSERT(
- !op.data.send_initial_metadata.maybe_compression_level.is_set);
- if (!completed()) {
- CToMetadata(op.data.send_initial_metadata.metadata,
- op.data.send_initial_metadata.count,
- send_initial_metadata_.get());
- StartPromise(std::move(send_initial_metadata_));
+ if (started_.exchange(true, std::memory_order_relaxed)) break;
+ CToMetadata(op.data.send_initial_metadata.metadata,
+ op.data.send_initial_metadata.count,
+ send_initial_metadata_.get());
+ PrepareOutgoingInitialMetadata(op, *send_initial_metadata_);
+ if (send_deadline() != Timestamp::InfFuture()) {
+ send_initial_metadata_->Set(GrpcTimeoutMetadata(), send_deadline());
}
+ send_initial_metadata_->Set(
+ WaitForReady(),
+ WaitForReady::ValueType{
+ (op.flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) != 0,
+ (op.flags &
+ GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET) != 0});
+ StartPromise(std::move(send_initial_metadata_), completion, spawner);
} break;
case GRPC_OP_RECV_INITIAL_METADATA: {
- recv_initial_metadata_ =
- op.data.recv_initial_metadata.recv_initial_metadata;
- server_initial_metadata_ready_.emplace(
- server_initial_metadata_.receiver.Next());
- recv_initial_metadata_completion_ =
- AddOpToCompletion(completion, PendingOp::kReceiveInitialMetadata);
+ StartRecvInitialMetadata(
+ op.data.recv_initial_metadata.recv_initial_metadata, completion,
+ spawner);
} break;
case GRPC_OP_RECV_STATUS_ON_CLIENT: {
- recv_status_on_client_completion_ =
- AddOpToCompletion(completion, PendingOp::kReceiveStatusOnClient);
- if (auto* finished_metadata =
- y_absl::get_if<ServerMetadataHandle>(&recv_status_on_client_)) {
- PublishStatus(op.data.recv_status_on_client,
- std::move(*finished_metadata));
- } else {
- recv_status_on_client_ = op.data.recv_status_on_client;
- }
+ StartRecvStatusOnClient(completion, op.data.recv_status_on_client,
+ spawner);
} break;
case GRPC_OP_SEND_MESSAGE:
- StartSendMessage(op, completion, &client_to_server_messages_.sender);
+ StartSendMessage(op, completion, &client_to_server_messages_.sender,
+ spawner);
break;
case GRPC_OP_RECV_MESSAGE:
- StartRecvMessage(op, completion, &server_to_client_messages_.receiver);
+ StartRecvMessage(
+ op, completion,
+ [this]() {
+ return server_initial_metadata_.receiver.AwaitClosed();
+ },
+ &server_to_client_messages_.receiver, spawner);
break;
case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
- close_send_completion_ =
- AddOpToCompletion(completion, PendingOp::kSendCloseFromClient);
- GPR_ASSERT(close_send_completion_.has_value());
+ spawner.Spawn(
+ "send_close_from_client",
+ [this]() {
+ client_to_server_messages_.sender.Close();
+ return Empty{};
+ },
+ [this,
+ completion = AddOpToCompletion(
+ completion, PendingOp::kSendCloseFromClient)](Empty) mutable {
+ FinishOpOnCompletion(&completion,
+ PendingOp::kSendCloseFromClient);
+ });
break;
case GRPC_OP_SEND_STATUS_FROM_SERVER:
case GRPC_OP_RECV_CLOSE_ON_SERVER:
@@ -2931,8 +2884,6 @@ grpc_call_error ClientPromiseBasedCall::StartBatch(const grpc_op* ops,
size_t nops,
void* notify_tag,
bool is_notify_tag_closure) {
- MutexLock lock(mu());
- ScopedContext activity_context(this);
if (nops == 0) {
EndOpImmediately(cq(), notify_tag, is_notify_tag_closure);
return GRPC_CALL_OK;
@@ -2944,69 +2895,35 @@ grpc_call_error ClientPromiseBasedCall::StartBatch(const grpc_op* ops,
Completion completion =
StartCompletion(notify_tag, is_notify_tag_closure, ops);
CommitBatch(ops, nops, completion);
- Update();
FinishOpOnCompletion(&completion, PendingOp::kStartingBatch);
return GRPC_CALL_OK;
}
-void ClientPromiseBasedCall::PublishInitialMetadata(ServerMetadata* metadata) {
- incoming_compression_algorithm_ =
- metadata->Take(GrpcEncodingMetadata()).value_or(GRPC_COMPRESS_NONE);
- server_initial_metadata_ready_.reset();
- GPR_ASSERT(recv_initial_metadata_ != nullptr);
- PublishMetadataArray(metadata,
- std::exchange(recv_initial_metadata_, nullptr));
- FinishOpOnCompletion(&recv_initial_metadata_completion_,
- PendingOp::kReceiveInitialMetadata);
-}
-
-void ClientPromiseBasedCall::UpdateOnce() {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[call] UpdateOnce: %s%shas_promise=%s",
- DebugTag().c_str(),
- PresentAndCompletionText("server_initial_metadata_ready",
- server_initial_metadata_ready_.has_value(),
- recv_initial_metadata_completion_)
- .c_str(),
- PollStateDebugString().c_str(),
- promise_.has_value() ? "true" : "false");
- }
- if (server_initial_metadata_ready_.has_value()) {
- Poll<NextResult<ServerMetadataHandle>> r =
- (*server_initial_metadata_ready_)();
- if (auto* server_initial_metadata = r.value_if_ready()) {
- PublishInitialMetadata(server_initial_metadata->value().get());
- } else if (completed()) {
- ServerMetadata no_metadata{GetContext<Arena>()};
- PublishInitialMetadata(&no_metadata);
- }
- }
- if (!PollSendMessage()) {
- Finish(ServerMetadataFromStatus(y_absl::Status(
- y_absl::StatusCode::kInternal, "Failed to send message to server")));
- }
- if (!is_sending() && close_send_completion_.has_value()) {
- client_to_server_messages_.sender.Close();
- FinishOpOnCompletion(&close_send_completion_,
- PendingOp::kSendCloseFromClient);
- }
- if (promise_.has_value()) {
- Poll<ServerMetadataHandle> r = promise_();
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[call] UpdateOnce: promise returns %s",
- DebugTag().c_str(),
- PollToString(r, [](const ServerMetadataHandle& h) {
- return h->DebugString();
- }).c_str());
- }
- if (auto* result = r.value_if_ready()) {
- AcceptTransportStatsFromContext();
- Finish(std::move(*result));
- }
- }
- if (incoming_compression_algorithm_.has_value()) {
- PollRecvMessage(*incoming_compression_algorithm_);
- }
+void ClientPromiseBasedCall::StartRecvInitialMetadata(
+ grpc_metadata_array* array, const Completion& completion,
+ Party::BulkSpawner& spawner) {
+ spawner.Spawn(
+ "recv_initial_metadata",
+ Race(server_initial_metadata_.receiver.Next(),
+ Map(finished(),
+ [](Empty) { return NextResult<ServerMetadataHandle>(true); })),
+ [this, array,
+ completion =
+ AddOpToCompletion(completion, PendingOp::kReceiveInitialMetadata)](
+ NextResult<ServerMetadataHandle> next_metadata) mutable {
+ server_initial_metadata_.sender.Close();
+ ServerMetadataHandle metadata;
+ if (next_metadata.has_value()) {
+ is_trailers_only_ = false;
+ metadata = std::move(next_metadata.value());
+ } else {
+ is_trailers_only_ = true;
+ metadata = arena()->MakePooled<ServerMetadata>(arena());
+ }
+ ProcessIncomingInitialMetadata(*metadata);
+ PublishMetadataArray(metadata.get(), array);
+ FinishOpOnCompletion(&completion, PendingOp::kReceiveInitialMetadata);
+ });
}
void ClientPromiseBasedCall::Finish(ServerMetadataHandle trailing_metadata) {
@@ -3014,31 +2931,9 @@ void ClientPromiseBasedCall::Finish(ServerMetadataHandle trailing_metadata) {
gpr_log(GPR_INFO, "%s[call] Finish: %s", DebugTag().c_str(),
trailing_metadata->DebugString().c_str());
}
- promise_ = ArenaPromise<ServerMetadataHandle>();
ResetDeadline();
set_completed();
- if (recv_initial_metadata_ != nullptr) {
- ForceImmediateRepoll();
- }
- const bool pending_initial_metadata =
- server_initial_metadata_ready_.has_value();
- if (!pending_initial_metadata) {
- server_initial_metadata_ready_.emplace(
- server_initial_metadata_.receiver.Next());
- }
- Poll<NextResult<ServerMetadataHandle>> r =
- (*server_initial_metadata_ready_)();
- server_initial_metadata_ready_.reset();
- if (auto* result = r.value_if_ready()) {
- if (pending_initial_metadata) PublishInitialMetadata(result->value().get());
- is_trailers_only_ = false;
- } else {
- if (pending_initial_metadata) {
- ServerMetadata no_metadata{GetContext<Arena>()};
- PublishInitialMetadata(&no_metadata);
- }
- is_trailers_only_ = true;
- }
+ client_to_server_messages_.sender.Close();
if (auto* channelz_channel = channel()->channelz_node()) {
if (trailing_metadata->get(GrpcStatusMetadata())
.value_or(GRPC_STATUS_UNKNOWN) == GRPC_STATUS_OK) {
@@ -3047,13 +2942,7 @@ void ClientPromiseBasedCall::Finish(ServerMetadataHandle trailing_metadata) {
channelz_channel->RecordCallFailed();
}
}
- if (auto* status_request =
- y_absl::get_if<grpc_op::grpc_op_data::grpc_op_recv_status_on_client>(
- &recv_status_on_client_)) {
- PublishStatus(*status_request, std::move(trailing_metadata));
- } else {
- recv_status_on_client_ = std::move(trailing_metadata);
- }
+ server_trailing_metadata_.Set(std::move(trailing_metadata));
}
namespace {
@@ -3079,35 +2968,43 @@ TString MakeErrorString(const ServerMetadata* trailing_metadata) {
}
} // namespace
-void ClientPromiseBasedCall::PublishStatus(
+void ClientPromiseBasedCall::StartRecvStatusOnClient(
+ const Completion& completion,
grpc_op::grpc_op_data::grpc_op_recv_status_on_client op_args,
- ServerMetadataHandle trailing_metadata) {
- const grpc_status_code status = trailing_metadata->get(GrpcStatusMetadata())
- .value_or(GRPC_STATUS_UNKNOWN);
- *op_args.status = status;
- y_absl::string_view message_string;
- if (Slice* message = trailing_metadata->get_pointer(GrpcMessageMetadata())) {
- message_string = message->as_string_view();
- *op_args.status_details = message->Ref().TakeCSlice();
- } else {
- *op_args.status_details = grpc_empty_slice();
- }
- if (message_string.empty()) {
- RunFinalization(status, nullptr);
- } else {
- TString error_string(message_string);
- RunFinalization(status, error_string.c_str());
- }
- if (op_args.error_string != nullptr && status != GRPC_STATUS_OK) {
- *op_args.error_string =
- gpr_strdup(MakeErrorString(trailing_metadata.get()).c_str());
- }
- PublishMetadataArray(trailing_metadata.get(), op_args.trailing_metadata);
- // Clear state saying we have a RECV_STATUS_ON_CLIENT outstanding
- // (so we don't call through twice)
- recv_status_on_client_ = y_absl::monostate();
- FinishOpOnCompletion(&recv_status_on_client_completion_,
- PendingOp::kReceiveStatusOnClient);
+ Party::BulkSpawner& spawner) {
+ ForceCompletionSuccess(completion);
+ spawner.Spawn(
+ "recv_status_on_client", server_trailing_metadata_.Wait(),
+ [this, op_args,
+ completion =
+ AddOpToCompletion(completion, PendingOp::kReceiveStatusOnClient)](
+ ServerMetadataHandle trailing_metadata) mutable {
+ const grpc_status_code status =
+ trailing_metadata->get(GrpcStatusMetadata())
+ .value_or(GRPC_STATUS_UNKNOWN);
+ *op_args.status = status;
+ y_absl::string_view message_string;
+ if (Slice* message =
+ trailing_metadata->get_pointer(GrpcMessageMetadata())) {
+ message_string = message->as_string_view();
+ *op_args.status_details = message->Ref().TakeCSlice();
+ } else {
+ *op_args.status_details = grpc_empty_slice();
+ }
+ if (message_string.empty()) {
+ RunFinalization(status, nullptr);
+ } else {
+ TString error_string(message_string);
+ RunFinalization(status, error_string.c_str());
+ }
+ if (op_args.error_string != nullptr && status != GRPC_STATUS_OK) {
+ *op_args.error_string =
+ gpr_strdup(MakeErrorString(trailing_metadata.get()).c_str());
+ }
+ PublishMetadataArray(trailing_metadata.get(),
+ op_args.trailing_metadata);
+ FinishOpOnCompletion(&completion, PendingOp::kReceiveStatusOnClient);
+ });
}
#endif
@@ -3120,19 +3017,18 @@ class ServerPromiseBasedCall final : public PromiseBasedCall {
public:
ServerPromiseBasedCall(Arena* arena, grpc_call_create_args* args);
- void CancelWithErrorLocked(grpc_error_handle) override
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu());
+ void CancelWithError(grpc_error_handle) override;
grpc_call_error StartBatch(const grpc_op* ops, size_t nops, void* notify_tag,
bool is_notify_tag_closure) override;
- bool failed_before_recv_message() const override { abort(); }
+ bool failed_before_recv_message() const override { return false; }
bool is_trailers_only() const override { abort(); }
y_absl::string_view GetServerAuthority() const override { return ""; }
// Polling order for the server promise stack:
//
// │ ┌───────────────────────────────────────┐
- // │ │ ServerPromiseBasedCall::UpdateOnce ├──► Lifetime management,
- // │ ├───────────────────────────────────────┤ signal call end to app
+ // │ │ ServerPromiseBasedCall ├──► Lifetime management
+ // │ ├───────────────────────────────────────┤
// │ │ ConnectedChannel ├─┐
// │ ├───────────────────────────────────────┤ └► Interactions with the
// │ │ ... closest to transport filter │ transport - send/recv msgs
@@ -3143,16 +3039,12 @@ class ServerPromiseBasedCall final : public PromiseBasedCall {
// │ ├───────────────────────────────────────┤ │ setup, publishing call to
// │ │ Server::ChannelData::MakeCallPromise ├─┘ application
// │ ├───────────────────────────────────────┤
- // │ │ ServerPromiseBasedCall::PollTopOfCall ├──► Application interactions,
- // ▼ └───────────────────────────────────────┘ forwarding messages,
- // Polling & sending trailing metadata
+ // │ │ MakeTopOfServerCallPromise ├──► Send trailing metadata
+ // ▼ └───────────────────────────────────────┘
+ // Polling &
// instantiation
// order
- void UpdateOnce() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu()) override;
- Poll<ServerMetadataHandle> PollTopOfCall()
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu());
-
TString DebugTag() const override {
return y_absl::StrFormat("SERVER_CALL[%p]: ", this);
}
@@ -3162,44 +3054,64 @@ class ServerPromiseBasedCall final : public PromiseBasedCall {
private:
class RecvCloseOpCancelState {
public:
- // Request that receiver be filled in per grpc_op_recv_close_on_server.
- // Returns true if the request can be fulfilled immediately.
- // Returns false if the request will be fulfilled later.
+ // Request that receiver be filled in per
+ // grpc_op_recv_close_on_server. Returns true if the request can
+ // be fulfilled immediately. Returns false if the request will be
+ // fulfilled later.
bool ReceiveCloseOnServerOpStarted(int* receiver) {
- switch (state_) {
- case kUnset:
- state_ = reinterpret_cast<uintptr_t>(receiver);
- return false;
- case kFinishedWithFailure:
- *receiver = 1;
- return true;
- case kFinishedWithSuccess:
- *receiver = 0;
- return true;
- default:
- abort(); // unreachable
- }
+ uintptr_t state = state_.load(std::memory_order_acquire);
+ uintptr_t new_state;
+ do {
+ switch (state) {
+ case kUnset:
+ new_state = reinterpret_cast<uintptr_t>(receiver);
+ break;
+ case kFinishedWithFailure:
+ *receiver = 1;
+ return true;
+ case kFinishedWithSuccess:
+ *receiver = 0;
+ return true;
+ default:
+ Crash("Two threads offered ReceiveCloseOnServerOpStarted");
+ }
+ } while (!state_.compare_exchange_weak(state, new_state,
+ std::memory_order_acq_rel,
+ std::memory_order_acquire));
+ return false;
}
// Mark the call as having completed.
- // Returns true if this finishes a previous RequestReceiveCloseOnServer.
- bool CompleteCall(bool success) {
- switch (state_) {
- case kUnset:
- state_ = success ? kFinishedWithSuccess : kFinishedWithFailure;
- return false;
- case kFinishedWithFailure:
- case kFinishedWithSuccess:
- abort(); // unreachable
- default:
- *reinterpret_cast<int*>(state_) = success ? 0 : 1;
- state_ = success ? kFinishedWithSuccess : kFinishedWithFailure;
- return true;
- }
+ // Returns true if this finishes a previous
+ // RequestReceiveCloseOnServer.
+ bool CompleteCallWithCancelledSetTo(bool cancelled) {
+ uintptr_t state = state_.load(std::memory_order_acquire);
+ uintptr_t new_state;
+ bool r;
+ do {
+ switch (state) {
+ case kUnset:
+ new_state = cancelled ? kFinishedWithFailure : kFinishedWithSuccess;
+ r = false;
+ break;
+ case kFinishedWithFailure:
+ return false;
+ case kFinishedWithSuccess:
+ Crash("unreachable");
+ default:
+ new_state = cancelled ? kFinishedWithFailure : kFinishedWithSuccess;
+ r = true;
+ }
+ } while (!state_.compare_exchange_weak(state, new_state,
+ std::memory_order_acq_rel,
+ std::memory_order_acquire));
+ if (r) *reinterpret_cast<int*>(state) = cancelled ? 1 : 0;
+ return r;
}
TString ToString() const {
- switch (state_) {
+ auto state = state_.load(std::memory_order_relaxed);
+ switch (state) {
case kUnset:
return "Unset";
case kFinishedWithFailure:
@@ -3208,7 +3120,7 @@ class ServerPromiseBasedCall final : public PromiseBasedCall {
return "FinishedWithSuccess";
default:
return y_absl::StrFormat("WaitingForReceiver(%p)",
- reinterpret_cast<void*>(state_));
+ reinterpret_cast<void*>(state));
}
}
@@ -3216,37 +3128,28 @@ class ServerPromiseBasedCall final : public PromiseBasedCall {
static constexpr uintptr_t kUnset = 0;
static constexpr uintptr_t kFinishedWithFailure = 1;
static constexpr uintptr_t kFinishedWithSuccess = 2;
- // Holds one of kUnset, kFinishedWithFailure, or kFinishedWithSuccess
- // OR an int* that wants to receive the final status.
- uintptr_t state_ = kUnset;
+ // Holds one of kUnset, kFinishedWithFailure, or
+ // kFinishedWithSuccess OR an int* that wants to receive the
+ // final status.
+ std::atomic<uintptr_t> state_{kUnset};
};
grpc_call_error ValidateBatch(const grpc_op* ops, size_t nops) const;
void CommitBatch(const grpc_op* ops, size_t nops,
- const Completion& completion)
- Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu());
+ const Completion& completion);
+ void Finish(ServerMetadataHandle result);
friend class ServerCallContext;
ServerCallContext call_context_;
Server* const server_;
- ArenaPromise<ServerMetadataHandle> promise_ Y_ABSL_GUARDED_BY(mu());
- PipeSender<MessageHandle>* server_to_client_messages_ Y_ABSL_GUARDED_BY(mu()) =
- nullptr;
- PipeReceiver<MessageHandle>* client_to_server_messages_
- Y_ABSL_GUARDED_BY(mu()) = nullptr;
- using SendInitialMetadataState =
- y_absl::variant<y_absl::monostate, PipeSender<ServerMetadataHandle>*,
- typename PipeSender<ServerMetadataHandle>::PushType>;
- SendInitialMetadataState send_initial_metadata_state_ Y_ABSL_GUARDED_BY(mu()) =
- y_absl::monostate{};
- ServerMetadataHandle send_trailing_metadata_ Y_ABSL_GUARDED_BY(mu());
- grpc_compression_algorithm incoming_compression_algorithm_
- Y_ABSL_GUARDED_BY(mu());
- RecvCloseOpCancelState recv_close_op_cancel_state_ Y_ABSL_GUARDED_BY(mu());
- Completion recv_close_completion_ Y_ABSL_GUARDED_BY(mu());
- bool cancel_send_and_receive_ Y_ABSL_GUARDED_BY(mu()) = false;
- Completion send_status_from_server_completion_ Y_ABSL_GUARDED_BY(mu());
- ClientMetadataHandle client_initial_metadata_ Y_ABSL_GUARDED_BY(mu());
+ PipeSender<ServerMetadataHandle>* server_initial_metadata_ = nullptr;
+ PipeSender<MessageHandle>* server_to_client_messages_ = nullptr;
+ PipeReceiver<MessageHandle>* client_to_server_messages_ = nullptr;
+ Latch<ServerMetadataHandle> send_trailing_metadata_;
+ RecvCloseOpCancelState recv_close_op_cancel_state_;
+ ClientMetadataHandle client_initial_metadata_;
+ Completion recv_close_completion_;
+ std::atomic<bool> cancelled_{false};
};
ServerPromiseBasedCall::ServerPromiseBasedCall(Arena* arena,
@@ -3259,106 +3162,60 @@ ServerPromiseBasedCall::ServerPromiseBasedCall(Arena* arena,
if (channelz_node != nullptr) {
channelz_node->RecordCallStarted();
}
- MutexLock lock(mu());
+ // TODO(yashykt): In the future, we want to also enable stats and trace
+ // collecting from when the call is created at the transport. The idea is that
+ // the transport would create the call tracer and pass it in as part of the
+ // metadata.
+ auto* server_call_tracer_factory =
+ ServerCallTracerFactory::Get(args->server->channel_args());
+ if (server_call_tracer_factory != nullptr) {
+ auto* server_call_tracer =
+ server_call_tracer_factory->CreateNewServerCallTracer(arena);
+ if (server_call_tracer != nullptr) {
+ // Note that we are setting both
+ // GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE and
+ // GRPC_CONTEXT_CALL_TRACER as a matter of convenience. In the future
+ // promise-based world, we would just a single tracer object for each
+ // stack (call, subchannel_call, server_call.)
+ ContextSet(GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE,
+ server_call_tracer, nullptr);
+ ContextSet(GRPC_CONTEXT_CALL_TRACER, server_call_tracer, nullptr);
+ }
+ }
ScopedContext activity_context(this);
- promise_ = channel()->channel_stack()->MakeServerCallPromise(
- CallArgs{nullptr, nullptr, nullptr, nullptr});
+ Spawn("server_promise",
+ channel()->channel_stack()->MakeServerCallPromise(
+ CallArgs{nullptr, ClientInitialMetadataOutstandingToken::Empty(),
+ nullptr, nullptr, nullptr}),
+ [this](ServerMetadataHandle result) { Finish(std::move(result)); });
}
-Poll<ServerMetadataHandle> ServerPromiseBasedCall::PollTopOfCall() {
+void ServerPromiseBasedCall::Finish(ServerMetadataHandle result) {
if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[call] PollTopOfCall: %s%s%s", DebugTag().c_str(),
- cancel_send_and_receive_ ? "force-" : "",
- send_trailing_metadata_ != nullptr
- ? y_absl::StrCat("send-metadata:",
- send_trailing_metadata_->DebugString(), " ")
- .c_str()
- : " ",
- PollStateDebugString().c_str());
+ gpr_log(GPR_INFO, "%s[call] Finish: recv_close_state:%s result:%s",
+ DebugTag().c_str(), recv_close_op_cancel_state_.ToString().c_str(),
+ result->DebugString().c_str());
}
-
- if (cancel_send_and_receive_) {
- CancelSendMessage();
- CancelRecvMessage();
- }
-
- PollSendMessage();
- PollRecvMessage(incoming_compression_algorithm_);
-
- if (!is_sending() && send_trailing_metadata_ != nullptr) {
- server_to_client_messages_->Close();
- return std::move(send_trailing_metadata_);
+ if (recv_close_op_cancel_state_.CompleteCallWithCancelledSetTo(
+ result->get(GrpcCallWasCancelled()).value_or(true))) {
+ FinishOpOnCompletion(&recv_close_completion_,
+ PendingOp::kReceiveCloseOnServer);
}
-
- return Pending{};
-}
-
-void ServerPromiseBasedCall::UpdateOnce() {
- if (grpc_call_trace.enabled()) {
- gpr_log(
- GPR_INFO, "%s[call] UpdateOnce: recv_close:%s%s %s%shas_promise=%s",
- DebugTag().c_str(), recv_close_op_cancel_state_.ToString().c_str(),
- recv_close_completion_.has_value()
- ? y_absl::StrCat(":", CompletionString(recv_close_completion_))
- .c_str()
- : "",
- send_status_from_server_completion_.has_value()
- ? y_absl::StrCat(
- "send_status:",
- CompletionString(send_status_from_server_completion_), " ")
- .c_str()
- : "",
- PollStateDebugString().c_str(),
- promise_.has_value() ? "true" : "false");
- }
- if (auto* p =
- y_absl::get_if<typename PipeSender<ServerMetadataHandle>::PushType>(
- &send_initial_metadata_state_)) {
- if ((*p)().ready()) {
- send_initial_metadata_state_ = y_absl::monostate{};
- }
+ if (server_initial_metadata_ != nullptr) {
+ server_initial_metadata_->Close();
}
- if (promise_.has_value()) {
- auto r = promise_();
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[call] UpdateOnce: promise returns %s",
- DebugTag().c_str(),
- PollToString(r, [](const ServerMetadataHandle& h) {
- return h->DebugString();
- }).c_str());
- }
- if (auto* result = r.value_if_ready()) {
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[call] UpdateOnce: GotResult %s result:%s",
- DebugTag().c_str(),
- recv_close_op_cancel_state_.ToString().c_str(),
- (*result)->DebugString().c_str());
- }
- if (recv_close_op_cancel_state_.CompleteCall(
- (*result)->get(GrpcStatusFromWire()).value_or(false))) {
- FinishOpOnCompletion(&recv_close_completion_,
- PendingOp::kReceiveCloseOnServer);
- }
- channelz::ServerNode* channelz_node = server_->channelz_node();
- if (channelz_node != nullptr) {
- if ((*result)
- ->get(GrpcStatusMetadata())
- .value_or(GRPC_STATUS_UNKNOWN) == GRPC_STATUS_OK) {
- channelz_node->RecordCallSucceeded();
- } else {
- channelz_node->RecordCallFailed();
- }
- }
- if (send_status_from_server_completion_.has_value()) {
- FinishOpOnCompletion(&send_status_from_server_completion_,
- PendingOp::kSendStatusFromServer);
- }
- CancelSendMessage();
- CancelRecvMessage();
- set_completed();
- promise_ = ArenaPromise<ServerMetadataHandle>();
+ channelz::ServerNode* channelz_node = server_->channelz_node();
+ if (channelz_node != nullptr) {
+ if (result->get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN) ==
+ GRPC_STATUS_OK) {
+ channelz_node->RecordCallSucceeded();
+ } else {
+ channelz_node->RecordCallFailed();
}
}
+ set_completed();
+ ResetDeadline();
+ PropagateCancellationToChildren();
}
grpc_call_error ServerPromiseBasedCall::ValidateBatch(const grpc_op* ops,
@@ -3399,56 +3256,92 @@ grpc_call_error ServerPromiseBasedCall::ValidateBatch(const grpc_op* ops,
void ServerPromiseBasedCall::CommitBatch(const grpc_op* ops, size_t nops,
const Completion& completion) {
+ Party::BulkSpawner spawner(this);
for (size_t op_idx = 0; op_idx < nops; op_idx++) {
const grpc_op& op = ops[op_idx];
switch (op.op) {
case GRPC_OP_SEND_INITIAL_METADATA: {
- // compression not implemented
- GPR_ASSERT(
- !op.data.send_initial_metadata.maybe_compression_level.is_set);
- if (!completed()) {
- auto metadata = arena()->MakePooled<ServerMetadata>(arena());
- CToMetadata(op.data.send_initial_metadata.metadata,
- op.data.send_initial_metadata.count, metadata.get());
- if (grpc_call_trace.enabled()) {
- gpr_log(GPR_INFO, "%s[call] Send initial metadata",
- DebugTag().c_str());
- }
- auto* pipe = y_absl::get<PipeSender<ServerMetadataHandle>*>(
- send_initial_metadata_state_);
- send_initial_metadata_state_ = pipe->Push(std::move(metadata));
+ auto metadata = arena()->MakePooled<ServerMetadata>(arena());
+ PrepareOutgoingInitialMetadata(op, *metadata);
+ CToMetadata(op.data.send_initial_metadata.metadata,
+ op.data.send_initial_metadata.count, metadata.get());
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_INFO, "%s[call] Send initial metadata",
+ DebugTag().c_str());
}
+ QueueSend();
+ spawner.Spawn(
+ "call_send_initial_metadata",
+ [this, metadata = std::move(metadata)]() mutable {
+ EnactSend();
+ return server_initial_metadata_->Push(std::move(metadata));
+ },
+ [this,
+ completion = AddOpToCompletion(
+ completion, PendingOp::kSendInitialMetadata)](bool r) mutable {
+ if (!r) FailCompletion(completion);
+ FinishOpOnCompletion(&completion,
+ PendingOp::kSendInitialMetadata);
+ });
} break;
case GRPC_OP_SEND_MESSAGE:
- StartSendMessage(op, completion, server_to_client_messages_);
+ StartSendMessage(op, completion, server_to_client_messages_, spawner);
break;
case GRPC_OP_RECV_MESSAGE:
- StartRecvMessage(op, completion, client_to_server_messages_);
+ if (cancelled_.load(std::memory_order_relaxed)) {
+ FailCompletion(completion);
+ break;
+ }
+ StartRecvMessage(
+ op, completion, []() { return []() { return Empty{}; }; },
+ client_to_server_messages_, spawner);
break;
- case GRPC_OP_SEND_STATUS_FROM_SERVER:
- send_trailing_metadata_ = arena()->MakePooled<ServerMetadata>(arena());
+ case GRPC_OP_SEND_STATUS_FROM_SERVER: {
+ auto metadata = arena()->MakePooled<ServerMetadata>(arena());
CToMetadata(op.data.send_status_from_server.trailing_metadata,
op.data.send_status_from_server.trailing_metadata_count,
- send_trailing_metadata_.get());
- send_trailing_metadata_->Set(GrpcStatusMetadata(),
- op.data.send_status_from_server.status);
+ metadata.get());
+ metadata->Set(GrpcStatusMetadata(),
+ op.data.send_status_from_server.status);
if (auto* details = op.data.send_status_from_server.status_details) {
- send_trailing_metadata_->Set(GrpcMessageMetadata(),
- Slice(CSliceRef(*details)));
+ metadata->Set(GrpcMessageMetadata(), Slice(CSliceRef(*details)));
}
- send_status_from_server_completion_ =
- AddOpToCompletion(completion, PendingOp::kSendStatusFromServer);
- break;
+ spawner.Spawn(
+ "call_send_status_from_server",
+ [this, metadata = std::move(metadata)]() mutable {
+ bool r = true;
+ if (send_trailing_metadata_.is_set()) {
+ r = false;
+ } else {
+ send_trailing_metadata_.Set(std::move(metadata));
+ }
+ return Map(WaitForSendingStarted(), [this, r](Empty) {
+ server_initial_metadata_->Close();
+ server_to_client_messages_->Close();
+ return r;
+ });
+ },
+ [this, completion = AddOpToCompletion(
+ completion, PendingOp::kSendStatusFromServer)](
+ bool ok) mutable {
+ if (!ok) FailCompletion(completion);
+ FinishOpOnCompletion(&completion,
+ PendingOp::kSendStatusFromServer);
+ });
+ } break;
case GRPC_OP_RECV_CLOSE_ON_SERVER:
if (grpc_call_trace.enabled()) {
gpr_log(GPR_INFO, "%s[call] StartBatch: RecvClose %s",
DebugTag().c_str(),
recv_close_op_cancel_state_.ToString().c_str());
}
- if (!recv_close_op_cancel_state_.ReceiveCloseOnServerOpStarted(
+ ForceCompletionSuccess(completion);
+ recv_close_completion_ =
+ AddOpToCompletion(completion, PendingOp::kReceiveCloseOnServer);
+ if (recv_close_op_cancel_state_.ReceiveCloseOnServerOpStarted(
op.data.recv_close_on_server.cancelled)) {
- recv_close_completion_ =
- AddOpToCompletion(completion, PendingOp::kReceiveCloseOnServer);
+ FinishOpOnCompletion(&recv_close_completion_,
+ PendingOp::kReceiveCloseOnServer);
}
break;
case GRPC_OP_RECV_STATUS_ON_CLIENT:
@@ -3463,8 +3356,6 @@ grpc_call_error ServerPromiseBasedCall::StartBatch(const grpc_op* ops,
size_t nops,
void* notify_tag,
bool is_notify_tag_closure) {
- MutexLock lock(mu());
- ScopedContext activity_context(this);
if (nops == 0) {
EndOpImmediately(cq(), notify_tag, is_notify_tag_closure);
return GRPC_CALL_OK;
@@ -3476,18 +3367,30 @@ grpc_call_error ServerPromiseBasedCall::StartBatch(const grpc_op* ops,
Completion completion =
StartCompletion(notify_tag, is_notify_tag_closure, ops);
CommitBatch(ops, nops, completion);
- Update();
FinishOpOnCompletion(&completion, PendingOp::kStartingBatch);
return GRPC_CALL_OK;
}
-void ServerPromiseBasedCall::CancelWithErrorLocked(y_absl::Status error) {
- if (!promise_.has_value()) return;
- cancel_send_and_receive_ = true;
- send_trailing_metadata_ = ServerMetadataFromStatus(error, arena());
- ForceWakeup();
+void ServerPromiseBasedCall::CancelWithError(y_absl::Status error) {
+ cancelled_.store(true, std::memory_order_relaxed);
+ Spawn(
+ "cancel_with_error",
+ [this, error = std::move(error)]() {
+ if (!send_trailing_metadata_.is_set()) {
+ auto md = ServerMetadataFromStatus(error);
+ md->Set(GrpcCallWasCancelled(), true);
+ send_trailing_metadata_.Set(std::move(md));
+ }
+ if (server_to_client_messages_ != nullptr) {
+ server_to_client_messages_->Close();
+ }
+ if (server_initial_metadata_ != nullptr) {
+ server_initial_metadata_->Close();
+ }
+ return Empty{};
+ },
+ [](Empty) {});
}
-
#endif
#ifdef GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_SERVER_CALL
@@ -3496,24 +3399,19 @@ ServerCallContext::MakeTopOfServerCallPromise(
CallArgs call_args, grpc_completion_queue* cq,
grpc_metadata_array* publish_initial_metadata,
y_absl::FunctionRef<void(grpc_call* call)> publish) {
- call_->mu()->AssertHeld();
- call_->SetCompletionQueueLocked(cq);
+ call_->SetCompletionQueue(cq);
call_->server_to_client_messages_ = call_args.server_to_client_messages;
call_->client_to_server_messages_ = call_args.client_to_server_messages;
- call_->send_initial_metadata_state_ = call_args.server_initial_metadata;
- call_->incoming_compression_algorithm_ =
- call_args.client_initial_metadata->get(GrpcEncodingMetadata())
- .value_or(GRPC_COMPRESS_NONE);
+ call_->server_initial_metadata_ = call_args.server_initial_metadata;
call_->client_initial_metadata_ =
std::move(call_args.client_initial_metadata);
+ call_->ProcessIncomingInitialMetadata(*call_->client_initial_metadata_);
PublishMetadataArray(call_->client_initial_metadata_.get(),
publish_initial_metadata);
call_->ExternalRef();
publish(call_->c_ptr());
- return [this]() {
- call_->mu()->AssertHeld();
- return call_->PollTopOfCall();
- };
+ return Seq(call_->server_to_client_messages_->AwaitClosed(),
+ call_->send_trailing_metadata_.Wait());
}
#else
ArenaPromise<ServerMetadataHandle>
@@ -3616,7 +3514,9 @@ uint32_t grpc_call_test_only_get_message_flags(grpc_call* call) {
}
uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call* call) {
- return grpc_core::Call::FromC(call)->test_only_encodings_accepted_by_peer();
+ return grpc_core::Call::FromC(call)
+ ->encodings_accepted_by_peer()
+ .ToLegacyBitmask();
}
grpc_core::Arena* grpc_call_get_arena(grpc_call* call) {
@@ -3665,7 +3565,9 @@ uint8_t grpc_call_is_client(grpc_call* call) {
grpc_compression_algorithm grpc_call_compression_for_level(
grpc_call* call, grpc_compression_level level) {
- return grpc_core::Call::FromC(call)->compression_for_level(level);
+ return grpc_core::Call::FromC(call)
+ ->encodings_accepted_by_peer()
+ .CompressionAlgorithmForLevel(level);
}
bool grpc_call_is_trailers_only(const grpc_call* call) {
diff --git a/contrib/libs/grpc/src/core/lib/surface/call.h b/contrib/libs/grpc/src/core/lib/surface/call.h
index c8b8f5c275..eb161de6cb 100644
--- a/contrib/libs/grpc/src/core/lib/surface/call.h
+++ b/contrib/libs/grpc/src/core/lib/surface/call.h
@@ -119,12 +119,20 @@ class CallContext {
// TODO(ctiller): remove this once transport APIs are promise based
void Unref(const char* reason = "call_context");
+ RefCountedPtr<CallContext> Ref() {
+ IncrementRefCount();
+ return RefCountedPtr<CallContext>(this);
+ }
+
grpc_call_stats* call_stats() { return &call_stats_; }
gpr_atm* peer_string_atm_ptr();
grpc_polling_entity* polling_entity() { return &pollent_; }
ServerCallContext* server_call_context();
+ void set_traced(bool traced) { traced_ = traced; }
+ bool traced() const { return traced_; }
+
private:
friend class PromiseBasedCall;
// Call final info.
@@ -135,6 +143,8 @@ class CallContext {
// TODO(ctiller): remove this once transport APIs are promise based and we
// don't need refcounting here.
PromiseBasedCall* const call_;
+ // Is this call traced?
+ bool traced_ = false;
};
template <>
diff --git a/contrib/libs/grpc/src/core/lib/surface/lame_client.cc b/contrib/libs/grpc/src/core/lib/surface/lame_client.cc
index c4afc17d75..6df15c70d1 100644
--- a/contrib/libs/grpc/src/core/lib/surface/lame_client.cc
+++ b/contrib/libs/grpc/src/core/lib/surface/lame_client.cc
@@ -79,6 +79,7 @@ ArenaPromise<ServerMetadataHandle> LameClientFilter::MakeCallPromise(
if (args.server_to_client_messages != nullptr) {
args.server_to_client_messages->Close();
}
+ args.client_initial_metadata_outstanding.Complete(true);
return Immediate(ServerMetadataFromStatus(error_));
}
diff --git a/contrib/libs/grpc/src/core/lib/surface/version.cc b/contrib/libs/grpc/src/core/lib/surface/version.cc
index 57224a52e4..f7f4587988 100644
--- a/contrib/libs/grpc/src/core/lib/surface/version.cc
+++ b/contrib/libs/grpc/src/core/lib/surface/version.cc
@@ -23,6 +23,6 @@
#include <grpc/grpc.h>
-const char* grpc_version_string(void) { return "30.1.0"; }
+const char* grpc_version_string(void) { return "31.0.0"; }
-const char* grpc_g_stands_for(void) { return "glockenspiel"; }
+const char* grpc_g_stands_for(void) { return "gracious"; }
diff --git a/contrib/libs/grpc/src/core/lib/transport/batch_builder.cc b/contrib/libs/grpc/src/core/lib/transport/batch_builder.cc
new file mode 100644
index 0000000000..08a1d90991
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/transport/batch_builder.cc
@@ -0,0 +1,179 @@
+// Copyright 2023 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/lib/transport/batch_builder.h"
+
+#include <type_traits>
+
+#include "src/core/lib/promise/poll.h"
+#include "src/core/lib/slice/slice.h"
+#include "src/core/lib/surface/call_trace.h"
+#include "src/core/lib/transport/metadata_batch.h"
+#include "src/core/lib/transport/transport.h"
+#include "src/core/lib/transport/transport_impl.h"
+
+namespace grpc_core {
+
+BatchBuilder::BatchBuilder(grpc_transport_stream_op_batch_payload* payload)
+ : payload_(payload) {}
+
+void BatchBuilder::PendingCompletion::CompletionCallback(
+ void* self, grpc_error_handle error) {
+ auto* pc = static_cast<PendingCompletion*>(self);
+ auto* party = pc->batch->party.get();
+ if (grpc_call_trace.enabled()) {
+ gpr_log(
+ GPR_DEBUG, "%s[connected] Finish batch-component %s for %s: status=%s",
+ party->DebugTag().c_str(), TString(pc->name()).c_str(),
+ grpc_transport_stream_op_batch_string(&pc->batch->batch, false).c_str(),
+ error.ToString().c_str());
+ }
+ party->Spawn(
+ "batch-completion",
+ [pc, error = std::move(error)]() mutable {
+ RefCountedPtr<Batch> batch = std::exchange(pc->batch, nullptr);
+ pc->done_latch.Set(std::move(error));
+ return Empty{};
+ },
+ [](Empty) {});
+}
+
+BatchBuilder::PendingCompletion::PendingCompletion(RefCountedPtr<Batch> batch)
+ : batch(std::move(batch)) {
+ GRPC_CLOSURE_INIT(&on_done_closure, CompletionCallback, this, nullptr);
+}
+
+BatchBuilder::Batch::Batch(grpc_transport_stream_op_batch_payload* payload,
+ grpc_stream_refcount* stream_refcount)
+ : party(static_cast<Party*>(Activity::current())->Ref()),
+ stream_refcount(stream_refcount) {
+ batch.payload = payload;
+ batch.is_traced = GetContext<CallContext>()->traced();
+#ifndef NDEBUG
+ grpc_stream_ref(stream_refcount, "pending-batch");
+#else
+ grpc_stream_ref(stream_refcount);
+#endif
+}
+
+BatchBuilder::Batch::~Batch() {
+ auto* arena = party->arena();
+ if (pending_receive_message != nullptr) {
+ arena->DeletePooled(pending_receive_message);
+ }
+ if (pending_receive_initial_metadata != nullptr) {
+ arena->DeletePooled(pending_receive_initial_metadata);
+ }
+ if (pending_receive_trailing_metadata != nullptr) {
+ arena->DeletePooled(pending_receive_trailing_metadata);
+ }
+ if (pending_sends != nullptr) {
+ arena->DeletePooled(pending_sends);
+ }
+ if (batch.cancel_stream) {
+ arena->DeletePooled(batch.payload);
+ }
+#ifndef NDEBUG
+ grpc_stream_unref(stream_refcount, "pending-batch");
+#else
+ grpc_stream_unref(stream_refcount);
+#endif
+}
+
+BatchBuilder::Batch* BatchBuilder::GetBatch(Target target) {
+ if (target_.has_value() &&
+ (target_->stream != target.stream ||
+ target.transport->vtable
+ ->hacky_disable_stream_op_batch_coalescing_in_connected_channel)) {
+ FlushBatch();
+ }
+ if (!target_.has_value()) {
+ target_ = target;
+ batch_ = GetContext<Arena>()->NewPooled<Batch>(payload_,
+ target_->stream_refcount);
+ }
+ GPR_ASSERT(batch_ != nullptr);
+ return batch_;
+}
+
+void BatchBuilder::FlushBatch() {
+ GPR_ASSERT(batch_ != nullptr);
+ GPR_ASSERT(target_.has_value());
+ if (grpc_call_trace.enabled()) {
+ gpr_log(
+ GPR_DEBUG, "%s[connected] Perform transport stream op batch: %p %s",
+ batch_->party->DebugTag().c_str(), &batch_->batch,
+ grpc_transport_stream_op_batch_string(&batch_->batch, false).c_str());
+ }
+ std::exchange(batch_, nullptr)->PerformWith(*target_);
+ target_.reset();
+}
+
+void BatchBuilder::Batch::PerformWith(Target target) {
+ grpc_transport_perform_stream_op(target.transport, target.stream, &batch);
+}
+
+ServerMetadataHandle BatchBuilder::CompleteSendServerTrailingMetadata(
+ ServerMetadataHandle sent_metadata, y_absl::Status send_result,
+ bool actually_sent) {
+ if (!send_result.ok()) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG,
+ "%s[connected] Send metadata failed with error: %s, "
+ "fabricating trailing metadata",
+ Activity::current()->DebugTag().c_str(),
+ send_result.ToString().c_str());
+ }
+ sent_metadata->Clear();
+ sent_metadata->Set(GrpcStatusMetadata(),
+ static_cast<grpc_status_code>(send_result.code()));
+ sent_metadata->Set(GrpcMessageMetadata(),
+ Slice::FromCopiedString(send_result.message()));
+ sent_metadata->Set(GrpcCallWasCancelled(), true);
+ }
+ if (!sent_metadata->get(GrpcCallWasCancelled()).has_value()) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(
+ GPR_DEBUG,
+ "%s[connected] Tagging trailing metadata with "
+ "cancellation status from transport: %s",
+ Activity::current()->DebugTag().c_str(),
+ actually_sent ? "sent => not-cancelled" : "not-sent => cancelled");
+ }
+ sent_metadata->Set(GrpcCallWasCancelled(), !actually_sent);
+ }
+ return sent_metadata;
+}
+
+BatchBuilder::Batch* BatchBuilder::MakeCancel(
+ grpc_stream_refcount* stream_refcount, y_absl::Status status) {
+ auto* arena = GetContext<Arena>();
+ auto* payload =
+ arena->NewPooled<grpc_transport_stream_op_batch_payload>(nullptr);
+ auto* batch = arena->NewPooled<Batch>(payload, stream_refcount);
+ batch->batch.cancel_stream = true;
+ payload->cancel_stream.cancel_error = std::move(status);
+ return batch;
+}
+
+void BatchBuilder::Cancel(Target target, y_absl::Status status) {
+ auto* batch = MakeCancel(target.stream_refcount, std::move(status));
+ batch->batch.on_complete = NewClosure(
+ [batch](y_absl::Status) { batch->party->arena()->DeletePooled(batch); });
+ batch->PerformWith(target);
+}
+
+} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/transport/batch_builder.h b/contrib/libs/grpc/src/core/lib/transport/batch_builder.h
new file mode 100644
index 0000000000..d7d358bb38
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/transport/batch_builder.h
@@ -0,0 +1,469 @@
+// Copyright 2023 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef GRPC_SRC_CORE_LIB_TRANSPORT_BATCH_BUILDER_H
+#define GRPC_SRC_CORE_LIB_TRANSPORT_BATCH_BUILDER_H
+
+#include <grpc/support/port_platform.h>
+
+#include <stdint.h>
+
+#include <memory>
+#include <util/generic/string.h>
+#include <util/string/cast.h>
+#include <utility>
+
+#include "y_absl/status/status.h"
+#include "y_absl/status/statusor.h"
+#include "y_absl/strings/string_view.h"
+#include "y_absl/types/optional.h"
+
+#include <grpc/status.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/gprpp/status_helper.h"
+#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/error.h"
+#include "src/core/lib/promise/activity.h"
+#include "src/core/lib/promise/context.h"
+#include "src/core/lib/promise/latch.h"
+#include "src/core/lib/promise/map.h"
+#include "src/core/lib/promise/party.h"
+#include "src/core/lib/resource_quota/arena.h"
+#include "src/core/lib/slice/slice_buffer.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/surface/call_trace.h"
+#include "src/core/lib/transport/metadata_batch.h"
+#include "src/core/lib/transport/transport.h"
+#include "src/core/lib/transport/transport_fwd.h"
+
+namespace grpc_core {
+
+// Build up a transport stream op batch for a stream for a promise based
+// connected channel.
+// Offered as a context from Call, so that it can collect ALL the updates during
+// a single party round, and then push them down to the transport as a single
+// transaction.
+class BatchBuilder {
+ public:
+ explicit BatchBuilder(grpc_transport_stream_op_batch_payload* payload);
+ ~BatchBuilder() {
+ if (batch_ != nullptr) FlushBatch();
+ }
+
+ struct Target {
+ grpc_transport* transport;
+ grpc_stream* stream;
+ grpc_stream_refcount* stream_refcount;
+ };
+
+ BatchBuilder(const BatchBuilder&) = delete;
+ BatchBuilder& operator=(const BatchBuilder&) = delete;
+
+ // Returns a promise that will resolve to a Status when the send is completed.
+ auto SendMessage(Target target, MessageHandle message);
+
+ // Returns a promise that will resolve to a Status when the send is completed.
+ auto SendClientInitialMetadata(Target target, ClientMetadataHandle metadata);
+
+ // Returns a promise that will resolve to a Status when the send is completed.
+ auto SendClientTrailingMetadata(Target target);
+
+ // Returns a promise that will resolve to a Status when the send is completed.
+ auto SendServerInitialMetadata(Target target, ServerMetadataHandle metadata);
+
+ // Returns a promise that will resolve to a ServerMetadataHandle when the send
+ // is completed.
+ //
+ // If convert_to_cancellation is true, then the status will be converted to a
+ // cancellation batch instead of a trailing metadata op in a coalesced batch.
+ //
+ // This quirk exists as in the filter based stack upon which our transports
+ // were written if a trailing metadata op were sent it always needed to be
+ // paired with an initial op batch, and the transports would wait for the
+ // initial metadata batch to arrive (in case of reordering up the stack).
+ auto SendServerTrailingMetadata(Target target, ServerMetadataHandle metadata,
+ bool convert_to_cancellation);
+
+ // Returns a promise that will resolve to a StatusOr<optional<MessageHandle>>
+ // when a message is received.
+ // Error => non-ok status
+ // End of stream => Ok, nullopt (no message)
+ // Message => Ok, message
+ auto ReceiveMessage(Target target);
+
+ // Returns a promise that will resolve to a StatusOr<ClientMetadataHandle>
+ // when the receive is complete.
+ auto ReceiveClientInitialMetadata(Target target);
+
+ // Returns a promise that will resolve to a StatusOr<ClientMetadataHandle>
+ // when the receive is complete.
+ auto ReceiveClientTrailingMetadata(Target target);
+
+ // Returns a promise that will resolve to a StatusOr<ServerMetadataHandle>
+ // when the receive is complete.
+ auto ReceiveServerInitialMetadata(Target target);
+
+ // Returns a promise that will resolve to a StatusOr<ServerMetadataHandle>
+ // when the receive is complete.
+ auto ReceiveServerTrailingMetadata(Target target);
+
+ // Send a cancellation: does not occupy the same payload, nor does it
+ // coalesce with other ops.
+ void Cancel(Target target, y_absl::Status status);
+
+ private:
+ struct Batch;
+
+ // Base pending operation
+ struct PendingCompletion {
+ explicit PendingCompletion(RefCountedPtr<Batch> batch);
+ virtual y_absl::string_view name() const = 0;
+ static void CompletionCallback(void* self, grpc_error_handle error);
+ grpc_closure on_done_closure;
+ Latch<y_absl::Status> done_latch;
+ RefCountedPtr<Batch> batch;
+
+ protected:
+ ~PendingCompletion() = default;
+ };
+
+ // A pending receive message.
+ struct PendingReceiveMessage final : public PendingCompletion {
+ using PendingCompletion::PendingCompletion;
+
+ y_absl::string_view name() const override { return "receive_message"; }
+
+ MessageHandle IntoMessageHandle() {
+ return GetContext<Arena>()->MakePooled<Message>(std::move(*payload),
+ flags);
+ }
+
+ y_absl::optional<SliceBuffer> payload;
+ uint32_t flags;
+ };
+
+ // A pending receive metadata.
+ struct PendingReceiveMetadata : public PendingCompletion {
+ using PendingCompletion::PendingCompletion;
+
+ Arena::PoolPtr<grpc_metadata_batch> metadata =
+ GetContext<Arena>()->MakePooled<grpc_metadata_batch>(
+ GetContext<Arena>());
+
+ protected:
+ ~PendingReceiveMetadata() = default;
+ };
+
+ struct PendingReceiveInitialMetadata final : public PendingReceiveMetadata {
+ using PendingReceiveMetadata::PendingReceiveMetadata;
+ y_absl::string_view name() const override {
+ return "receive_initial_metadata";
+ }
+ };
+
+ struct PendingReceiveTrailingMetadata final : public PendingReceiveMetadata {
+ using PendingReceiveMetadata::PendingReceiveMetadata;
+ y_absl::string_view name() const override {
+ return "receive_trailing_metadata";
+ }
+ };
+
+ // Pending sends in a batch
+ struct PendingSends final : public PendingCompletion {
+ using PendingCompletion::PendingCompletion;
+
+ y_absl::string_view name() const override { return "sends"; }
+
+ MessageHandle send_message;
+ Arena::PoolPtr<grpc_metadata_batch> send_initial_metadata;
+ Arena::PoolPtr<grpc_metadata_batch> send_trailing_metadata;
+ bool trailing_metadata_sent = false;
+ };
+
+ // One outstanding batch.
+ struct Batch final {
+ Batch(grpc_transport_stream_op_batch_payload* payload,
+ grpc_stream_refcount* stream_refcount);
+ ~Batch();
+ Batch(const Batch&) = delete;
+ Batch& operator=(const Batch&) = delete;
+ void IncrementRefCount() { ++refs; }
+ void Unref() {
+ if (--refs == 0) party->arena()->DeletePooled(this);
+ }
+ RefCountedPtr<Batch> Ref() {
+ IncrementRefCount();
+ return RefCountedPtr<Batch>(this);
+ }
+ // Get an initialized pending completion.
+ // There are four pending completions potentially contained within a batch.
+ // They can be rather large so we don't create all of them always. Instead,
+ // we dynamically create them on the arena as needed.
+ // This method either returns the existing completion in a batch if that
+ // completion has already been initialized, or it creates a new completion
+ // and returns that.
+ template <typename T>
+ T* GetInitializedCompletion(T*(Batch::*field)) {
+ if (this->*field != nullptr) return this->*field;
+ this->*field = party->arena()->NewPooled<T>(Ref());
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[connected] Add batch closure for %s @ %s",
+ Activity::current()->DebugTag().c_str(),
+ TString((this->*field)->name()).c_str(),
+ (this->*field)->on_done_closure.DebugString().c_str());
+ }
+ return this->*field;
+ }
+ // grpc_transport_perform_stream_op on target.stream
+ void PerformWith(Target target);
+ // Take a promise, and return a promise that holds a ref on this batch until
+ // the promise completes or is cancelled.
+ template <typename P>
+ auto RefUntil(P promise) {
+ return [self = Ref(), promise = std::move(promise)]() mutable {
+ return promise();
+ };
+ }
+
+ grpc_transport_stream_op_batch batch;
+ PendingReceiveMessage* pending_receive_message = nullptr;
+ PendingReceiveInitialMetadata* pending_receive_initial_metadata = nullptr;
+ PendingReceiveTrailingMetadata* pending_receive_trailing_metadata = nullptr;
+ PendingSends* pending_sends = nullptr;
+ const RefCountedPtr<Party> party;
+ grpc_stream_refcount* const stream_refcount;
+ uint8_t refs = 0;
+ };
+
+ // Get a batch for the given target.
+ // Currently: if the current batch is for this target, return it - otherwise
+ // flush the batch and start a new one (and return that).
+ // This function may change in the future to allow multiple batches to be
+ // building at once (if that turns out to be useful for hedging).
+ Batch* GetBatch(Target target);
+ // Flush the current batch down to the transport.
+ void FlushBatch();
+ // Create a cancel batch with its own payload.
+ Batch* MakeCancel(grpc_stream_refcount* stream_refcount, y_absl::Status status);
+
+ // Note: we don't distinguish between client and server metadata here.
+ // At the time of writing they're both the same thing - and it's unclear
+ // whether we'll get to separate them prior to batches going away or not.
+ // So for now we claim YAGNI and just do the simplest possible implementation.
+ auto SendInitialMetadata(Target target,
+ Arena::PoolPtr<grpc_metadata_batch> md);
+ auto ReceiveInitialMetadata(Target target);
+ auto ReceiveTrailingMetadata(Target target);
+
+ // Combine send status and server metadata into a final status to report back
+ // to the containing call.
+ static ServerMetadataHandle CompleteSendServerTrailingMetadata(
+ ServerMetadataHandle sent_metadata, y_absl::Status send_result,
+ bool actually_sent);
+
+ grpc_transport_stream_op_batch_payload* const payload_;
+ y_absl::optional<Target> target_;
+ Batch* batch_ = nullptr;
+};
+
+inline auto BatchBuilder::SendMessage(Target target, MessageHandle message) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[connected] Queue send message: %s",
+ Activity::current()->DebugTag().c_str(),
+ message->DebugString().c_str());
+ }
+ auto* batch = GetBatch(target);
+ auto* pc = batch->GetInitializedCompletion(&Batch::pending_sends);
+ batch->batch.on_complete = &pc->on_done_closure;
+ batch->batch.send_message = true;
+ payload_->send_message.send_message = message->payload();
+ payload_->send_message.flags = message->flags();
+ pc->send_message = std::move(message);
+ return batch->RefUntil(pc->done_latch.WaitAndCopy());
+}
+
+inline auto BatchBuilder::SendInitialMetadata(
+ Target target, Arena::PoolPtr<grpc_metadata_batch> md) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[connected] Queue send initial metadata: %s",
+ Activity::current()->DebugTag().c_str(), md->DebugString().c_str());
+ }
+ auto* batch = GetBatch(target);
+ auto* pc = batch->GetInitializedCompletion(&Batch::pending_sends);
+ batch->batch.on_complete = &pc->on_done_closure;
+ batch->batch.send_initial_metadata = true;
+ payload_->send_initial_metadata.send_initial_metadata = md.get();
+ pc->send_initial_metadata = std::move(md);
+ return batch->RefUntil(pc->done_latch.WaitAndCopy());
+}
+
+inline auto BatchBuilder::SendClientInitialMetadata(
+ Target target, ClientMetadataHandle metadata) {
+ return SendInitialMetadata(target, std::move(metadata));
+}
+
+inline auto BatchBuilder::SendClientTrailingMetadata(Target target) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[connected] Queue send trailing metadata",
+ Activity::current()->DebugTag().c_str());
+ }
+ auto* batch = GetBatch(target);
+ auto* pc = batch->GetInitializedCompletion(&Batch::pending_sends);
+ batch->batch.on_complete = &pc->on_done_closure;
+ batch->batch.send_trailing_metadata = true;
+ auto metadata =
+ GetContext<Arena>()->MakePooled<grpc_metadata_batch>(GetContext<Arena>());
+ payload_->send_trailing_metadata.send_trailing_metadata = metadata.get();
+ payload_->send_trailing_metadata.sent = nullptr;
+ pc->send_trailing_metadata = std::move(metadata);
+ return batch->RefUntil(pc->done_latch.WaitAndCopy());
+}
+
+inline auto BatchBuilder::SendServerInitialMetadata(
+ Target target, ServerMetadataHandle metadata) {
+ return SendInitialMetadata(target, std::move(metadata));
+}
+
+inline auto BatchBuilder::SendServerTrailingMetadata(
+ Target target, ServerMetadataHandle metadata,
+ bool convert_to_cancellation) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[connected] %s: %s",
+ Activity::current()->DebugTag().c_str(),
+ convert_to_cancellation ? "Send trailing metadata as cancellation"
+ : "Queue send trailing metadata",
+ metadata->DebugString().c_str());
+ }
+ Batch* batch;
+ PendingSends* pc;
+ if (convert_to_cancellation) {
+ const auto status_code =
+ metadata->get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN);
+ auto status = grpc_error_set_int(
+ y_absl::Status(static_cast<y_absl::StatusCode>(status_code),
+ metadata->GetOrCreatePointer(GrpcMessageMetadata())
+ ->as_string_view()),
+ StatusIntProperty::kRpcStatus, status_code);
+ batch = MakeCancel(target.stream_refcount, std::move(status));
+ pc = batch->GetInitializedCompletion(&Batch::pending_sends);
+ } else {
+ batch = GetBatch(target);
+ pc = batch->GetInitializedCompletion(&Batch::pending_sends);
+ batch->batch.send_trailing_metadata = true;
+ payload_->send_trailing_metadata.send_trailing_metadata = metadata.get();
+ payload_->send_trailing_metadata.sent = &pc->trailing_metadata_sent;
+ }
+ batch->batch.on_complete = &pc->on_done_closure;
+ pc->send_trailing_metadata = std::move(metadata);
+ auto promise = batch->RefUntil(
+ Map(pc->done_latch.WaitAndCopy(), [pc](y_absl::Status status) {
+ return CompleteSendServerTrailingMetadata(
+ std::move(pc->send_trailing_metadata), std::move(status),
+ pc->trailing_metadata_sent);
+ }));
+ if (convert_to_cancellation) {
+ batch->PerformWith(target);
+ }
+ return promise;
+}
+
+inline auto BatchBuilder::ReceiveMessage(Target target) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[connected] Queue receive message",
+ Activity::current()->DebugTag().c_str());
+ }
+ auto* batch = GetBatch(target);
+ auto* pc = batch->GetInitializedCompletion(&Batch::pending_receive_message);
+ batch->batch.recv_message = true;
+ payload_->recv_message.recv_message_ready = &pc->on_done_closure;
+ payload_->recv_message.recv_message = &pc->payload;
+ payload_->recv_message.flags = &pc->flags;
+ return batch->RefUntil(
+ Map(pc->done_latch.Wait(),
+ [pc](y_absl::Status status)
+ -> y_absl::StatusOr<y_absl::optional<MessageHandle>> {
+ if (!status.ok()) return status;
+ if (!pc->payload.has_value()) return y_absl::nullopt;
+ return pc->IntoMessageHandle();
+ }));
+}
+
+inline auto BatchBuilder::ReceiveInitialMetadata(Target target) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[connected] Queue receive initial metadata",
+ Activity::current()->DebugTag().c_str());
+ }
+ auto* batch = GetBatch(target);
+ auto* pc =
+ batch->GetInitializedCompletion(&Batch::pending_receive_initial_metadata);
+ batch->batch.recv_initial_metadata = true;
+ payload_->recv_initial_metadata.recv_initial_metadata_ready =
+ &pc->on_done_closure;
+ payload_->recv_initial_metadata.recv_initial_metadata = pc->metadata.get();
+ return batch->RefUntil(
+ Map(pc->done_latch.Wait(),
+ [pc](y_absl::Status status) -> y_absl::StatusOr<ClientMetadataHandle> {
+ if (!status.ok()) return status;
+ return std::move(pc->metadata);
+ }));
+}
+
+inline auto BatchBuilder::ReceiveClientInitialMetadata(Target target) {
+ return ReceiveInitialMetadata(target);
+}
+
+inline auto BatchBuilder::ReceiveServerInitialMetadata(Target target) {
+ return ReceiveInitialMetadata(target);
+}
+
+inline auto BatchBuilder::ReceiveTrailingMetadata(Target target) {
+ if (grpc_call_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "%s[connected] Queue receive trailing metadata",
+ Activity::current()->DebugTag().c_str());
+ }
+ auto* batch = GetBatch(target);
+ auto* pc = batch->GetInitializedCompletion(
+ &Batch::pending_receive_trailing_metadata);
+ batch->batch.recv_trailing_metadata = true;
+ payload_->recv_trailing_metadata.recv_trailing_metadata_ready =
+ &pc->on_done_closure;
+ payload_->recv_trailing_metadata.recv_trailing_metadata = pc->metadata.get();
+ payload_->recv_trailing_metadata.collect_stats =
+ &GetContext<CallContext>()->call_stats()->transport_stream_stats;
+ return batch->RefUntil(
+ Map(pc->done_latch.Wait(),
+ [pc](y_absl::Status status) -> y_absl::StatusOr<ServerMetadataHandle> {
+ if (!status.ok()) return status;
+ return std::move(pc->metadata);
+ }));
+}
+
+inline auto BatchBuilder::ReceiveClientTrailingMetadata(Target target) {
+ return ReceiveTrailingMetadata(target);
+}
+
+inline auto BatchBuilder::ReceiveServerTrailingMetadata(Target target) {
+ return ReceiveTrailingMetadata(target);
+}
+
+template <>
+struct ContextType<BatchBuilder> {};
+
+} // namespace grpc_core
+
+#endif // GRPC_SRC_CORE_LIB_TRANSPORT_BATCH_BUILDER_H
diff --git a/contrib/libs/grpc/src/core/lib/transport/bdp_estimator.cc b/contrib/libs/grpc/src/core/lib/transport/bdp_estimator.cc
index 053a06684b..5890411057 100644
--- a/contrib/libs/grpc/src/core/lib/transport/bdp_estimator.cc
+++ b/contrib/libs/grpc/src/core/lib/transport/bdp_estimator.cc
@@ -29,7 +29,7 @@ grpc_core::TraceFlag grpc_bdp_estimator_trace(false, "bdp_estimator");
namespace grpc_core {
-BdpEstimator::BdpEstimator(const char* name)
+BdpEstimator::BdpEstimator(y_absl::string_view name)
: ping_state_(PingState::UNSCHEDULED),
accumulator_(0),
estimate_(65536),
@@ -50,16 +50,16 @@ Timestamp BdpEstimator::CompletePing() {
gpr_log(GPR_INFO,
"bdp[%s]:complete acc=%" PRId64 " est=%" PRId64
" dt=%lf bw=%lfMbs bw_est=%lfMbs",
- name_, accumulator_, estimate_, dt, bw / 125000.0,
- bw_est_ / 125000.0);
+ TString(name_).c_str(), accumulator_, estimate_, dt,
+ bw / 125000.0, bw_est_ / 125000.0);
}
GPR_ASSERT(ping_state_ == PingState::STARTED);
if (accumulator_ > 2 * estimate_ / 3 && bw > bw_est_) {
estimate_ = std::max(accumulator_, estimate_ * 2);
bw_est_ = bw;
if (GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace)) {
- gpr_log(GPR_INFO, "bdp[%s]: estimate increased to %" PRId64, name_,
- estimate_);
+ gpr_log(GPR_INFO, "bdp[%s]: estimate increased to %" PRId64,
+ TString(name_).c_str(), estimate_);
}
inter_ping_delay_ /= 2; // if the ping estimate changes,
// exponentially get faster at probing
@@ -74,8 +74,8 @@ Timestamp BdpEstimator::CompletePing() {
if (start_inter_ping_delay != inter_ping_delay_) {
stable_estimate_count_ = 0;
if (GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace)) {
- gpr_log(GPR_INFO, "bdp[%s]:update_inter_time to %" PRId64 "ms", name_,
- inter_ping_delay_.millis());
+ gpr_log(GPR_INFO, "bdp[%s]:update_inter_time to %" PRId64 "ms",
+ TString(name_).c_str(), inter_ping_delay_.millis());
}
}
ping_state_ = PingState::UNSCHEDULED;
diff --git a/contrib/libs/grpc/src/core/lib/transport/bdp_estimator.h b/contrib/libs/grpc/src/core/lib/transport/bdp_estimator.h
index e5576786f1..183e6633db 100644
--- a/contrib/libs/grpc/src/core/lib/transport/bdp_estimator.h
+++ b/contrib/libs/grpc/src/core/lib/transport/bdp_estimator.h
@@ -23,6 +23,11 @@
#include <inttypes.h>
+#include <util/generic/string.h>
+#include <util/string/cast.h>
+
+#include "y_absl/strings/string_view.h"
+
#include <grpc/support/log.h>
#include <grpc/support/time.h>
@@ -35,7 +40,7 @@ namespace grpc_core {
class BdpEstimator {
public:
- explicit BdpEstimator(const char* name);
+ explicit BdpEstimator(y_absl::string_view name);
~BdpEstimator() {}
int64_t EstimateBdp() const { return estimate_; }
@@ -48,8 +53,8 @@ class BdpEstimator {
// transport (but not necessarily started)
void SchedulePing() {
if (GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace)) {
- gpr_log(GPR_INFO, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64, name_,
- accumulator_, estimate_);
+ gpr_log(GPR_INFO, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64,
+ TString(name_).c_str(), accumulator_, estimate_);
}
GPR_ASSERT(ping_state_ == PingState::UNSCHEDULED);
ping_state_ = PingState::SCHEDULED;
@@ -61,8 +66,8 @@ class BdpEstimator {
// the ping is on the wire
void StartPing() {
if (GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace)) {
- gpr_log(GPR_INFO, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64, name_,
- accumulator_, estimate_);
+ gpr_log(GPR_INFO, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64,
+ TString(name_).c_str(), accumulator_, estimate_);
}
GPR_ASSERT(ping_state_ == PingState::SCHEDULED);
ping_state_ = PingState::STARTED;
@@ -85,7 +90,7 @@ class BdpEstimator {
Duration inter_ping_delay_;
int stable_estimate_count_;
double bw_est_;
- const char* name_;
+ y_absl::string_view name_;
};
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/transport/custom_metadata.h b/contrib/libs/grpc/src/core/lib/transport/custom_metadata.h
new file mode 100644
index 0000000000..7cf9c2fc32
--- /dev/null
+++ b/contrib/libs/grpc/src/core/lib/transport/custom_metadata.h
@@ -0,0 +1,30 @@
+// Copyright 2023 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef GRPC_SRC_CORE_LIB_TRANSPORT_CUSTOM_METADATA_H
+#define GRPC_SRC_CORE_LIB_TRANSPORT_CUSTOM_METADATA_H
+
+// This file defines two macros: GRPC_CUSTOM_CLIENT_METADATA and
+// GRPC_CUSTOM_SERVER_METADATA.
+// Each of these is a comma-prefixed and comma-separated list of metadata types
+// that will be added to ClientMetadata and ServerMetadata respectively.
+// (note: for now both are added to both).
+// Different sites with internal grpc-core extensions can substitute this file
+// and define their own versions of these macros to extend the metadata system
+// with fast metadata types of their own.
+
+#define GRPC_CUSTOM_CLIENT_METADATA
+#define GRPC_CUSTOM_SERVER_METADATA
+
+#endif // GRPC_SRC_CORE_LIB_TRANSPORT_CUSTOM_METADATA_H
diff --git a/contrib/libs/grpc/src/core/lib/transport/metadata_batch.cc b/contrib/libs/grpc/src/core/lib/transport/metadata_batch.cc
index e75f256e65..b1e23f744c 100644
--- a/contrib/libs/grpc/src/core/lib/transport/metadata_batch.cc
+++ b/contrib/libs/grpc/src/core/lib/transport/metadata_batch.cc
@@ -187,7 +187,7 @@ size_t EncodedSizeOfKey(HttpSchemeMetadata, HttpSchemeMetadata::ValueType x) {
}
}
-const char* HttpSchemeMetadata::DisplayValue(MementoType content_type) {
+const char* HttpSchemeMetadata::DisplayValue(ValueType content_type) {
switch (content_type) {
case kHttp:
return "http";
@@ -300,7 +300,10 @@ TString GrpcStreamNetworkState::DisplayValue(ValueType x) {
GPR_UNREACHABLE_CODE(return "unknown value");
}
-TString PeerString::DisplayValue(ValueType x) { return TString(x); }
+TString PeerString::DisplayValue(const ValueType& x) {
+ return TString(x.as_string_view());
+}
+
const TString& GrpcStatusContext::DisplayValue(const TString& x) {
return x;
}
diff --git a/contrib/libs/grpc/src/core/lib/transport/metadata_batch.h b/contrib/libs/grpc/src/core/lib/transport/metadata_batch.h
index 81effd7be0..0321aef451 100644
--- a/contrib/libs/grpc/src/core/lib/transport/metadata_batch.h
+++ b/contrib/libs/grpc/src/core/lib/transport/metadata_batch.h
@@ -46,6 +46,7 @@
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice.h"
+#include "src/core/lib/transport/custom_metadata.h"
#include "src/core/lib/transport/parsed_metadata.h"
namespace grpc_core {
@@ -491,8 +492,8 @@ struct GrpcStreamNetworkState {
struct PeerString {
static y_absl::string_view DebugKey() { return "PeerString"; }
static constexpr bool kRepeatable = false;
- using ValueType = y_absl::string_view;
- static TString DisplayValue(ValueType x);
+ using ValueType = Slice;
+ static TString DisplayValue(const ValueType& x);
};
// Annotation added by various systems to describe the reason for a failure.
@@ -511,6 +512,15 @@ struct GrpcStatusFromWire {
static y_absl::string_view DisplayValue(bool x) { return x ? "true" : "false"; }
};
+// Annotation to denote that this call qualifies for cancelled=1 for the
+// RECV_CLOSE_ON_SERVER op
+struct GrpcCallWasCancelled {
+ static y_absl::string_view DebugKey() { return "GrpcCallWasCancelled"; }
+ static constexpr bool kRepeatable = false;
+ using ValueType = bool;
+ static y_absl::string_view DisplayValue(bool x) { return x ? "true" : "false"; }
+};
+
// Annotation added by client surface code to denote wait-for-ready state
struct WaitForReady {
struct ValueType {
@@ -1487,7 +1497,9 @@ using grpc_metadata_batch_base = grpc_core::MetadataMap<
// Non-encodable things
grpc_core::GrpcStreamNetworkState, grpc_core::PeerString,
grpc_core::GrpcStatusContext, grpc_core::GrpcStatusFromWire,
- grpc_core::WaitForReady, grpc_core::GrpcTrailersOnly>;
+ grpc_core::GrpcCallWasCancelled, grpc_core::WaitForReady,
+ grpc_core::GrpcTrailersOnly GRPC_CUSTOM_CLIENT_METADATA
+ GRPC_CUSTOM_SERVER_METADATA>;
struct grpc_metadata_batch : public grpc_metadata_batch_base {
using grpc_metadata_batch_base::grpc_metadata_batch_base;
diff --git a/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.cc b/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.cc
index 2b43f2a307..4371609412 100644
--- a/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.cc
+++ b/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.cc
@@ -20,6 +20,8 @@
#include "src/core/lib/transport/timeout_encoding.h"
+#include <limits>
+
#include "y_absl/base/attributes.h"
#include <grpc/support/log.h>
@@ -30,7 +32,7 @@ namespace grpc_core {
namespace {
int64_t DivideRoundingUp(int64_t dividend, int64_t divisor) {
- return (dividend + divisor - 1) / divisor;
+ return (dividend - 1 + divisor) / divisor;
}
constexpr int64_t kSecondsPerMinute = 60;
@@ -173,6 +175,9 @@ Timeout Timeout::FromMillis(int64_t millis) {
} else if (millis < 100000) {
int64_t value = DivideRoundingUp(millis, 100);
if (value % 10 != 0) return Timeout(value, Unit::kHundredMilliseconds);
+ } else if (millis > std::numeric_limits<int64_t>::max() - 999) {
+ // prevent signed integer overflow.
+ return Timeout(kMaxHours, Unit::kHours);
}
return Timeout::FromSeconds(DivideRoundingUp(millis, 1000));
}
diff --git a/contrib/libs/grpc/src/core/lib/transport/transport.cc b/contrib/libs/grpc/src/core/lib/transport/transport.cc
index 9d59b261f8..1965ce8c37 100644
--- a/contrib/libs/grpc/src/core/lib/transport/transport.cc
+++ b/contrib/libs/grpc/src/core/lib/transport/transport.cc
@@ -26,13 +26,17 @@
#include <new>
#include "y_absl/status/status.h"
+#include "y_absl/strings/str_cat.h"
#include <grpc/event_engine/event_engine.h>
+#include <grpc/grpc.h>
#include "src/core/lib/event_engine/default_event_engine.h"
#include "src/core/lib/gpr/alloc.h"
+#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice.h"
+#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/transport_impl.h"
grpc_core::DebugOnlyTraceFlag grpc_trace_stream_refcount(false,
@@ -271,11 +275,35 @@ namespace grpc_core {
ServerMetadataHandle ServerMetadataFromStatus(const y_absl::Status& status,
Arena* arena) {
auto hdl = arena->MakePooled<ServerMetadata>(arena);
- hdl->Set(GrpcStatusMetadata(), static_cast<grpc_status_code>(status.code()));
+ grpc_status_code code;
+ TString message;
+ grpc_error_get_status(status, Timestamp::InfFuture(), &code, &message,
+ nullptr, nullptr);
+ hdl->Set(GrpcStatusMetadata(), code);
if (!status.ok()) {
- hdl->Set(GrpcMessageMetadata(), Slice::FromCopiedString(status.message()));
+ hdl->Set(GrpcMessageMetadata(), Slice::FromCopiedString(message));
}
return hdl;
}
+TString Message::DebugString() const {
+ TString out = y_absl::StrCat(payload_.Length(), "b");
+ auto flags = flags_;
+ auto explain = [&flags, &out](uint32_t flag, y_absl::string_view name) {
+ if (flags & flag) {
+ flags &= ~flag;
+ y_absl::StrAppend(&out, ":", name);
+ }
+ };
+ explain(GRPC_WRITE_BUFFER_HINT, "write_buffer");
+ explain(GRPC_WRITE_NO_COMPRESS, "no_compress");
+ explain(GRPC_WRITE_THROUGH, "write_through");
+ explain(GRPC_WRITE_INTERNAL_COMPRESS, "compress");
+ explain(GRPC_WRITE_INTERNAL_TEST_ONLY_WAS_COMPRESSED, "was_compressed");
+ if (flags != 0) {
+ y_absl::StrAppend(&out, ":huh=0x", y_absl::Hex(flags));
+ }
+ return out;
+}
+
} // namespace grpc_core
diff --git a/contrib/libs/grpc/src/core/lib/transport/transport.h b/contrib/libs/grpc/src/core/lib/transport/transport.h
index bc205f2e9a..8147710964 100644
--- a/contrib/libs/grpc/src/core/lib/transport/transport.h
+++ b/contrib/libs/grpc/src/core/lib/transport/transport.h
@@ -28,6 +28,7 @@
#include <functional>
#include <util/generic/string.h>
#include <util/string/cast.h>
+#include <type_traits>
#include <utility>
#include "y_absl/status/status.h"
@@ -37,7 +38,6 @@
#include <grpc/impl/connectivity_state.h>
#include <grpc/slice.h>
#include <grpc/status.h>
-#include <grpc/support/atm.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
@@ -55,6 +55,7 @@
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/detail/status.h"
+#include "src/core/lib/promise/latch.h"
#include "src/core/lib/promise/pipe.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice_buffer.h"
@@ -107,6 +108,8 @@ class Message {
SliceBuffer* payload() { return &payload_; }
const SliceBuffer* payload() const { return &payload_; }
+ TString DebugString() const;
+
private:
SliceBuffer payload_;
uint32_t flags_ = 0;
@@ -145,11 +148,70 @@ struct StatusCastImpl<ServerMetadataHandle, y_absl::Status&> {
}
};
+// Move only type that tracks call startup.
+// Allows observation of when client_initial_metadata has been processed by the
+// end of the local call stack.
+// Interested observers can call Wait() to obtain a promise that will resolve
+// when all local client_initial_metadata processing has completed.
+// The result of this token is either true on successful completion, or false
+// if the metadata was not sent.
+// To set a successful completion, call Complete(true). For failure, call
+// Complete(false).
+// If Complete is not called, the destructor of a still held token will complete
+// with failure.
+// Transports should hold this token until client_initial_metadata has passed
+// any flow control (eg MAX_CONCURRENT_STREAMS for http2).
+class ClientInitialMetadataOutstandingToken {
+ public:
+ static ClientInitialMetadataOutstandingToken Empty() {
+ return ClientInitialMetadataOutstandingToken();
+ }
+ static ClientInitialMetadataOutstandingToken New(
+ Arena* arena = GetContext<Arena>()) {
+ ClientInitialMetadataOutstandingToken token;
+ token.latch_ = arena->New<Latch<bool>>();
+ return token;
+ }
+
+ ClientInitialMetadataOutstandingToken(
+ const ClientInitialMetadataOutstandingToken&) = delete;
+ ClientInitialMetadataOutstandingToken& operator=(
+ const ClientInitialMetadataOutstandingToken&) = delete;
+ ClientInitialMetadataOutstandingToken(
+ ClientInitialMetadataOutstandingToken&& other) noexcept
+ : latch_(std::exchange(other.latch_, nullptr)) {}
+ ClientInitialMetadataOutstandingToken& operator=(
+ ClientInitialMetadataOutstandingToken&& other) noexcept {
+ latch_ = std::exchange(other.latch_, nullptr);
+ return *this;
+ }
+ ~ClientInitialMetadataOutstandingToken() {
+ if (latch_ != nullptr) latch_->Set(false);
+ }
+ void Complete(bool success) { std::exchange(latch_, nullptr)->Set(success); }
+
+ // Returns a promise that will resolve when this object (or its moved-from
+ // ancestor) is dropped.
+ auto Wait() { return latch_->Wait(); }
+
+ private:
+ ClientInitialMetadataOutstandingToken() = default;
+
+ Latch<bool>* latch_ = nullptr;
+};
+
+using ClientInitialMetadataOutstandingTokenWaitType =
+ decltype(std::declval<ClientInitialMetadataOutstandingToken>().Wait());
+
struct CallArgs {
// Initial metadata from the client to the server.
// During promise setup this can be manipulated by filters (and then
// passed on to the next filter).
ClientMetadataHandle client_initial_metadata;
+ // Token indicating that client_initial_metadata is still being processed.
+ // This should be moved around and only destroyed when the transport is
+ // satisfied that the metadata has passed any flow control measures it has.
+ ClientInitialMetadataOutstandingToken client_initial_metadata_outstanding;
// Initial metadata from the server to the client.
// Set once when it's available.
// During promise setup filters can substitute their own latch for this
@@ -332,6 +394,12 @@ struct grpc_transport_stream_op_batch {
/// Is this stream traced
bool is_traced : 1;
+ bool HasOp() const {
+ return send_initial_metadata || send_trailing_metadata || send_message ||
+ recv_initial_metadata || recv_message || recv_trailing_metadata ||
+ cancel_stream;
+ }
+
//**************************************************************************
// remaining fields are initialized and used at the discretion of the
// current handler of the op
@@ -345,12 +413,6 @@ struct grpc_transport_stream_op_batch_payload {
: context(context) {}
struct {
grpc_metadata_batch* send_initial_metadata = nullptr;
- // If non-NULL, will be set by the transport to the peer string (a char*).
- // The transport retains ownership of the string.
- // Note: This pointer may be used by the transport after the
- // send_initial_metadata op is completed. It must remain valid
- // until the call is destroyed.
- gpr_atm* peer_string = nullptr;
} send_initial_metadata;
struct {
@@ -395,12 +457,6 @@ struct grpc_transport_stream_op_batch_payload {
// uses this to set the success flag of OnReadInitialMetadataDone()
// callback.
bool* trailing_metadata_available = nullptr;
- // If non-NULL, will be set by the transport to the peer string (a char*).
- // The transport retains ownership of the string.
- // Note: This pointer may be used by the transport after the
- // recv_initial_metadata op is completed. It must remain valid
- // until the call is destroyed.
- gpr_atm* peer_string = nullptr;
} recv_initial_metadata;
struct {
@@ -547,7 +603,7 @@ void grpc_transport_stream_op_batch_finish_with_failure_from_transport(
grpc_transport_stream_op_batch* batch, grpc_error_handle error);
TString grpc_transport_stream_op_batch_string(
- grpc_transport_stream_op_batch* op);
+ grpc_transport_stream_op_batch* op, bool truncate);
TString grpc_transport_op_string(grpc_transport_op* op);
// Send a batch of operations on a transport
diff --git a/contrib/libs/grpc/src/core/lib/transport/transport_impl.h b/contrib/libs/grpc/src/core/lib/transport/transport_impl.h
index 62fc911104..7556ffcf9e 100644
--- a/contrib/libs/grpc/src/core/lib/transport/transport_impl.h
+++ b/contrib/libs/grpc/src/core/lib/transport/transport_impl.h
@@ -38,6 +38,13 @@ typedef struct grpc_transport_vtable {
// layers and initialized by the transport
size_t sizeof_stream; // = sizeof(transport stream)
+ // HACK: inproc does not handle stream op batch callbacks correctly (receive
+ // ops are required to complete prior to on_complete triggering).
+ // This flag is used to disable coalescing of batches in connected_channel for
+ // that specific transport.
+ // TODO(ctiller): This ought not be necessary once we have promises complete.
+ bool hacky_disable_stream_op_batch_coalescing_in_connected_channel;
+
// name of this transport implementation
const char* name;
diff --git a/contrib/libs/grpc/src/core/lib/transport/transport_op_string.cc b/contrib/libs/grpc/src/core/lib/transport/transport_op_string.cc
index 13d4b6b636..3c8fe8d806 100644
--- a/contrib/libs/grpc/src/core/lib/transport/transport_op_string.cc
+++ b/contrib/libs/grpc/src/core/lib/transport/transport_op_string.cc
@@ -18,16 +18,13 @@
#include <grpc/support/port_platform.h>
-#include <algorithm>
#include <initializer_list>
#include <memory>
#include <util/generic/string.h>
#include <util/string/cast.h>
-#include <vector>
#include "y_absl/strings/str_cat.h"
#include "y_absl/strings/str_format.h"
-#include "y_absl/strings/str_join.h"
#include <grpc/support/log.h>
@@ -45,105 +42,118 @@
// representations of various transport data structures
TString grpc_transport_stream_op_batch_string(
- grpc_transport_stream_op_batch* op) {
- std::vector<TString> out;
+ grpc_transport_stream_op_batch* op, bool truncate) {
+ TString out;
if (op->send_initial_metadata) {
- out.push_back(" SEND_INITIAL_METADATA{");
- out.push_back(op->payload->send_initial_metadata.send_initial_metadata
- ->DebugString());
- out.push_back("}");
+ y_absl::StrAppend(&out, " SEND_INITIAL_METADATA{");
+ if (truncate) {
+ y_absl::StrAppend(&out, "Length=",
+ op->payload->send_initial_metadata.send_initial_metadata
+ ->TransportSize());
+ } else {
+ y_absl::StrAppend(&out, op->payload->send_initial_metadata
+ .send_initial_metadata->DebugString());
+ }
+ y_absl::StrAppend(&out, "}");
}
if (op->send_message) {
if (op->payload->send_message.send_message != nullptr) {
- out.push_back(y_absl::StrFormat(
- " SEND_MESSAGE:flags=0x%08x:len=%d", op->payload->send_message.flags,
- op->payload->send_message.send_message->Length()));
+ y_absl::StrAppendFormat(&out, " SEND_MESSAGE:flags=0x%08x:len=%d",
+ op->payload->send_message.flags,
+ op->payload->send_message.send_message->Length());
} else {
// This can happen when we check a batch after the transport has
// processed and cleared the send_message op.
- out.push_back(" SEND_MESSAGE(flag and length unknown, already orphaned)");
+ y_absl::StrAppend(
+ &out, " SEND_MESSAGE(flag and length unknown, already orphaned)");
}
}
if (op->send_trailing_metadata) {
- out.push_back(" SEND_TRAILING_METADATA{");
- out.push_back(op->payload->send_trailing_metadata.send_trailing_metadata
- ->DebugString());
- out.push_back("}");
+ y_absl::StrAppend(&out, " SEND_TRAILING_METADATA{");
+ if (truncate) {
+ y_absl::StrAppend(&out, "Length=",
+ op->payload->send_trailing_metadata
+ .send_trailing_metadata->TransportSize());
+ } else {
+ y_absl::StrAppend(&out, op->payload->send_trailing_metadata
+ .send_trailing_metadata->DebugString());
+ }
+ y_absl::StrAppend(&out, "}");
}
if (op->recv_initial_metadata) {
- out.push_back(" RECV_INITIAL_METADATA");
+ y_absl::StrAppend(&out, " RECV_INITIAL_METADATA");
}
if (op->recv_message) {
- out.push_back(" RECV_MESSAGE");
+ y_absl::StrAppend(&out, " RECV_MESSAGE");
}
if (op->recv_trailing_metadata) {
- out.push_back(" RECV_TRAILING_METADATA");
+ y_absl::StrAppend(&out, " RECV_TRAILING_METADATA");
}
if (op->cancel_stream) {
- out.push_back(y_absl::StrCat(
- " CANCEL:",
- grpc_core::StatusToString(op->payload->cancel_stream.cancel_error)));
+ y_absl::StrAppend(
+ &out, " CANCEL:",
+ grpc_core::StatusToString(op->payload->cancel_stream.cancel_error));
}
- return y_absl::StrJoin(out, "");
+ return out;
}
TString grpc_transport_op_string(grpc_transport_op* op) {
- std::vector<TString> out;
+ TString out;
if (op->start_connectivity_watch != nullptr) {
- out.push_back(y_absl::StrFormat(
- " START_CONNECTIVITY_WATCH:watcher=%p:from=%s",
+ y_absl::StrAppendFormat(
+ &out, " START_CONNECTIVITY_WATCH:watcher=%p:from=%s",
op->start_connectivity_watch.get(),
- grpc_core::ConnectivityStateName(op->start_connectivity_watch_state)));
+ grpc_core::ConnectivityStateName(op->start_connectivity_watch_state));
}
if (op->stop_connectivity_watch != nullptr) {
- out.push_back(y_absl::StrFormat(" STOP_CONNECTIVITY_WATCH:watcher=%p",
- op->stop_connectivity_watch));
+ y_absl::StrAppendFormat(&out, " STOP_CONNECTIVITY_WATCH:watcher=%p",
+ op->stop_connectivity_watch);
}
if (!op->disconnect_with_error.ok()) {
- out.push_back(y_absl::StrCat(
- " DISCONNECT:", grpc_core::StatusToString(op->disconnect_with_error)));
+ y_absl::StrAppend(&out, " DISCONNECT:",
+ grpc_core::StatusToString(op->disconnect_with_error));
}
if (!op->goaway_error.ok()) {
- out.push_back(y_absl::StrCat(" SEND_GOAWAY:",
- grpc_core::StatusToString(op->goaway_error)));
+ y_absl::StrAppend(
+ &out, " SEND_GOAWAY:", grpc_core::StatusToString(op->goaway_error));
}
if (op->set_accept_stream) {
- out.push_back(y_absl::StrFormat(" SET_ACCEPT_STREAM:%p(%p,...)",
- op->set_accept_stream_fn,
- op->set_accept_stream_user_data));
+ y_absl::StrAppendFormat(&out, " SET_ACCEPT_STREAM:%p(%p,...)",
+ op->set_accept_stream_fn,
+ op->set_accept_stream_user_data);
}
if (op->bind_pollset != nullptr) {
- out.push_back(" BIND_POLLSET");
+ y_absl::StrAppend(&out, " BIND_POLLSET");
}
if (op->bind_pollset_set != nullptr) {
- out.push_back(" BIND_POLLSET_SET");
+ y_absl::StrAppend(&out, " BIND_POLLSET_SET");
}
if (op->send_ping.on_initiate != nullptr || op->send_ping.on_ack != nullptr) {
- out.push_back(" SEND_PING");
+ y_absl::StrAppend(&out, " SEND_PING");
}
- return y_absl::StrJoin(out, "");
+ return out;
}
void grpc_call_log_op(const char* file, int line, gpr_log_severity severity,
grpc_call_element* elem,
grpc_transport_stream_op_batch* op) {
gpr_log(file, line, severity, "OP[%s:%p]: %s", elem->filter->name, elem,
- grpc_transport_stream_op_batch_string(op).c_str());
+ grpc_transport_stream_op_batch_string(op, false).c_str());
}
diff --git a/contrib/libs/grpc/src/core/plugin_registry/grpc_plugin_registry.cc b/contrib/libs/grpc/src/core/plugin_registry/grpc_plugin_registry.cc
index c120471fbe..cf0d0b3c0c 100644
--- a/contrib/libs/grpc/src/core/plugin_registry/grpc_plugin_registry.cc
+++ b/contrib/libs/grpc/src/core/plugin_registry/grpc_plugin_registry.cc
@@ -76,8 +76,8 @@ void BuildCoreConfiguration(CoreConfiguration::Builder* builder) {
grpc_event_engine::experimental::RegisterEventEngineChannelArgPreconditioning(
builder);
// The order of the handshaker registration is crucial here.
- // We want TCP connect handshaker to be registered last so that it is added to
- // the start of the handshaker list.
+ // We want TCP connect handshaker to be registered last so that it is added
+ // to the start of the handshaker list.
RegisterHttpConnectHandshaker(builder);
RegisterTCPConnectHandshaker(builder);
RegisterPriorityLbPolicy(builder);
diff --git a/contrib/libs/grpc/src/core/tsi/alts/frame_protector/alts_frame_protector.cc b/contrib/libs/grpc/src/core/tsi/alts/frame_protector/alts_frame_protector.cc
index 7c9b310907..9a3ba475dd 100644
--- a/contrib/libs/grpc/src/core/tsi/alts/frame_protector/alts_frame_protector.cc
+++ b/contrib/libs/grpc/src/core/tsi/alts/frame_protector/alts_frame_protector.cc
@@ -30,6 +30,7 @@
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/crash.h"
+#include "src/core/lib/gprpp/memory.h"
#include "src/core/tsi/alts/crypt/gsec.h"
#include "src/core/tsi/alts/frame_protector/alts_crypter.h"
#include "src/core/tsi/alts/frame_protector/frame_handler.h"
diff --git a/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.cc b/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.cc
index df29ca8114..9f09f2f142 100644
--- a/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.cc
+++ b/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.cc
@@ -22,6 +22,7 @@
#include <list>
+#include "y_absl/strings/numbers.h"
#include "upb/upb.hpp"
#include <grpc/byte_buffer.h>
@@ -29,6 +30,7 @@
#include <grpc/support/log.h>
#include "src/core/lib/gprpp/crash.h"
+#include "src/core/lib/gprpp/env.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/call.h"
@@ -40,6 +42,8 @@
#define TSI_ALTS_INITIAL_BUFFER_SIZE 256
const int kHandshakerClientOpNum = 4;
+const char kMaxConcurrentStreamsEnvironmentVariable[] =
+ "GRPC_ALTS_MAX_CONCURRENT_HANDSHAKES";
struct alts_handshaker_client {
const alts_handshaker_client_vtable* vtable;
@@ -419,7 +423,8 @@ HandshakeQueue* g_client_handshake_queue;
HandshakeQueue* g_server_handshake_queue;
void DoHandshakeQueuesInit(void) {
- const size_t per_queue_max_outstanding_handshakes = 40;
+ const size_t per_queue_max_outstanding_handshakes =
+ MaxNumberOfConcurrentHandshakes();
g_client_handshake_queue =
new HandshakeQueue(per_queue_max_outstanding_handshakes);
g_server_handshake_queue =
@@ -733,16 +738,14 @@ alts_handshaker_client* alts_grpc_handshaker_client_create(
client->handshake_status_details = grpc_empty_slice();
client->max_frame_size = max_frame_size;
client->error = error;
- grpc_slice slice = grpc_slice_from_copied_string(handshaker_service_url);
client->call =
strcmp(handshaker_service_url, ALTS_HANDSHAKER_SERVICE_URL_FOR_TESTING) ==
0
? nullptr
: grpc_channel_create_pollset_set_call(
channel, nullptr, GRPC_PROPAGATE_DEFAULTS, interested_parties,
- grpc_slice_from_static_string(ALTS_SERVICE_METHOD), &slice,
+ grpc_slice_from_static_string(ALTS_SERVICE_METHOD), nullptr,
grpc_core::Timestamp::InfFuture(), nullptr);
- grpc_core::CSliceUnref(slice);
GRPC_CLOSURE_INIT(&client->on_handshaker_service_resp_recv, grpc_cb, client,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&client->on_status_received, on_status_received, client,
@@ -926,3 +929,17 @@ void alts_handshaker_client_destroy(alts_handshaker_client* c) {
alts_grpc_handshaker_client_unref(client);
}
}
+
+size_t MaxNumberOfConcurrentHandshakes() {
+ size_t max_concurrent_handshakes = 40;
+ y_absl::optional<TString> env_var_max_concurrent_handshakes =
+ grpc_core::GetEnv(kMaxConcurrentStreamsEnvironmentVariable);
+ if (env_var_max_concurrent_handshakes.has_value()) {
+ size_t effective_max_concurrent_handshakes = 40;
+ if (y_absl::SimpleAtoi(*env_var_max_concurrent_handshakes,
+ &effective_max_concurrent_handshakes)) {
+ max_concurrent_handshakes = effective_max_concurrent_handshakes;
+ }
+ }
+ return max_concurrent_handshakes;
+}
diff --git a/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.h b/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.h
index cb50cfcadf..f1870ac75e 100644
--- a/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.h
+++ b/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.h
@@ -157,4 +157,9 @@ alts_handshaker_client* alts_grpc_handshaker_client_create(
void alts_handshaker_client_handle_response(alts_handshaker_client* client,
bool is_ok);
+// Returns the max number of concurrent handshakes that are permitted.
+//
+// Exposed for testing purposes only.
+size_t MaxNumberOfConcurrentHandshakes();
+
#endif // GRPC_SRC_CORE_TSI_ALTS_HANDSHAKER_ALTS_HANDSHAKER_CLIENT_H
diff --git a/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc b/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
index 8e26ccfc80..64bd1dce51 100644
--- a/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
+++ b/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
@@ -351,7 +351,7 @@ tsi_result alts_tsi_handshaker_result_create(grpc_gcp_HandshakerResp* resp,
gpr_log(GPR_ERROR, "Null peer identity in ALTS context.");
return TSI_FAILED_PRECONDITION;
}
- if (grpc_gcp_Identity_has_attributes(identity)) {
+ if (grpc_gcp_Identity_attributes_size(identity) != 0) {
size_t iter = kUpb_Map_Begin;
grpc_gcp_Identity_AttributesEntry* peer_attributes_entry =
grpc_gcp_Identity_attributes_nextmutable(peer_identity, &iter);
diff --git a/contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc b/contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc
index 90680739ab..deb3b952d4 100644
--- a/contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc
+++ b/contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc
@@ -2071,7 +2071,8 @@ tsi_result tsi_create_ssl_client_handshaker_factory_with_options(
gpr_log(GPR_ERROR, "Failed to load CRL File from directory.");
} else {
X509_VERIFY_PARAM* param = X509_STORE_get0_param(cert_store);
- X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
+ X509_VERIFY_PARAM_set_flags(
+ param, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
gpr_log(GPR_INFO, "enabled client side CRL checking.");
}
}
@@ -2255,7 +2256,8 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
gpr_log(GPR_ERROR, "Failed to load CRL File from directory.");
} else {
X509_VERIFY_PARAM* param = X509_STORE_get0_param(cert_store);
- X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
+ X509_VERIFY_PARAM_set_flags(
+ param, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
gpr_log(GPR_INFO, "enabled server CRL checking.");
}
}
diff --git a/contrib/libs/grpc/src/cpp/client/client_interceptor.cc b/contrib/libs/grpc/src/cpp/client/client_interceptor.cc
index 93181b825c..dfa30d6fe4 100644
--- a/contrib/libs/grpc/src/cpp/client/client_interceptor.cc
+++ b/contrib/libs/grpc/src/cpp/client/client_interceptor.cc
@@ -25,7 +25,8 @@ namespace grpc {
namespace internal {
experimental::ClientInterceptorFactoryInterface*
g_global_client_interceptor_factory = nullptr;
-}
+
+} // namespace internal
namespace experimental {
void RegisterGlobalClientInterceptorFactory(
diff --git a/contrib/libs/grpc/src/cpp/client/client_stats_interceptor.cc b/contrib/libs/grpc/src/cpp/client/client_stats_interceptor.cc
new file mode 100644
index 0000000000..84c017ddbc
--- /dev/null
+++ b/contrib/libs/grpc/src/cpp/client/client_stats_interceptor.cc
@@ -0,0 +1,40 @@
+//
+//
+// Copyright 2023 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+
+#include <grpcpp/support/client_interceptor.h>
+
+#include "src/core/lib/gprpp/crash.h"
+
+namespace grpc {
+namespace internal {
+
+experimental::ClientInterceptorFactoryInterface*
+ g_global_client_stats_interceptor_factory = nullptr;
+
+void RegisterGlobalClientStatsInterceptorFactory(
+ grpc::experimental::ClientInterceptorFactoryInterface* factory) {
+ if (internal::g_global_client_stats_interceptor_factory != nullptr) {
+ grpc_core::Crash(
+ "It is illegal to call RegisterGlobalClientStatsInterceptorFactory "
+ "multiple times.");
+ }
+ internal::g_global_client_interceptor_factory = factory;
+}
+
+} // namespace internal
+} // namespace grpc
diff --git a/contrib/libs/grpc/src/cpp/common/channel_filter.h b/contrib/libs/grpc/src/cpp/common/channel_filter.h
index 9a5eb7dc94..abc3051fde 100644
--- a/contrib/libs/grpc/src/cpp/common/channel_filter.h
+++ b/contrib/libs/grpc/src/cpp/common/channel_filter.h
@@ -31,7 +31,6 @@
#include "y_absl/types/optional.h"
#include <grpc/grpc.h>
-#include <grpc/support/atm.h>
#include <grpcpp/support/config.h>
#include "src/core/lib/channel/channel_args.h"
@@ -172,18 +171,6 @@ class TransportStreamOpBatch {
op_->payload->context[GRPC_CONTEXT_TRACING].value);
}
- const gpr_atm* get_peer_string() const {
- if (op_->send_initial_metadata &&
- op_->payload->send_initial_metadata.peer_string != nullptr) {
- return op_->payload->send_initial_metadata.peer_string;
- } else if (op_->recv_initial_metadata &&
- op_->payload->recv_initial_metadata.peer_string != nullptr) {
- return op_->payload->recv_initial_metadata.peer_string;
- } else {
- return nullptr;
- }
- }
-
private:
grpc_transport_stream_op_batch* op_; // Not owned.
MetadataBatch send_initial_metadata_;
diff --git a/contrib/libs/grpc/src/cpp/common/tls_certificate_verifier.cc b/contrib/libs/grpc/src/cpp/common/tls_certificate_verifier.cc
index 313116de6d..9d0c86b1c5 100644
--- a/contrib/libs/grpc/src/cpp/common/tls_certificate_verifier.cc
+++ b/contrib/libs/grpc/src/cpp/common/tls_certificate_verifier.cc
@@ -66,6 +66,13 @@ grpc::string_ref TlsCustomVerificationCheckRequest::common_name() const {
: "";
}
+grpc::string_ref TlsCustomVerificationCheckRequest::verified_root_cert_subject()
+ const {
+ return c_request_->peer_info.verified_root_cert_subject != nullptr
+ ? c_request_->peer_info.verified_root_cert_subject
+ : "";
+}
+
std::vector<grpc::string_ref> TlsCustomVerificationCheckRequest::uri_names()
const {
std::vector<grpc::string_ref> uri_names;
diff --git a/contrib/libs/grpc/src/cpp/server/backend_metric_recorder.cc b/contrib/libs/grpc/src/cpp/server/backend_metric_recorder.cc
index f45ef4b6b8..e76ad18f28 100644
--- a/contrib/libs/grpc/src/cpp/server/backend_metric_recorder.cc
+++ b/contrib/libs/grpc/src/cpp/server/backend_metric_recorder.cc
@@ -40,8 +40,8 @@ bool IsUtilizationValid(double utilization) {
return utilization >= 0.0 && utilization <= 1.0;
}
-// QPS must be in [0, infy).
-bool IsQpsValid(double qps) { return qps >= 0.0; }
+// Rate values (qps and eps) must be in [0, infy).
+bool IsRateValid(double rate) { return rate >= 0.0; }
grpc_core::TraceFlag grpc_backend_metric_trace(false, "backend_metric");
} // namespace
@@ -94,7 +94,7 @@ void ServerMetricRecorder::SetMemoryUtilization(double value) {
}
void ServerMetricRecorder::SetQps(double value) {
- if (!IsQpsValid(value)) {
+ if (!IsRateValid(value)) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_backend_metric_trace)) {
gpr_log(GPR_INFO, "[%p] QPS rejected: %f", this, value);
}
@@ -107,6 +107,20 @@ void ServerMetricRecorder::SetQps(double value) {
}
}
+void ServerMetricRecorder::SetEps(double value) {
+ if (!IsRateValid(value)) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_backend_metric_trace)) {
+ gpr_log(GPR_INFO, "[%p] EPS rejected: %f", this, value);
+ }
+ return;
+ }
+ UpdateBackendMetricDataState(
+ [value](BackendMetricData* data) { data->eps = value; });
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_backend_metric_trace)) {
+ gpr_log(GPR_INFO, "[%p] EPS set: %f", this, value);
+ }
+}
+
void ServerMetricRecorder::SetNamedUtilization(string_ref name, double value) {
if (!IsUtilizationValid(value)) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_backend_metric_trace)) {
@@ -163,6 +177,13 @@ void ServerMetricRecorder::ClearQps() {
}
}
+void ServerMetricRecorder::ClearEps() {
+ UpdateBackendMetricDataState([](BackendMetricData* data) { data->eps = -1; });
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_backend_metric_trace)) {
+ gpr_log(GPR_INFO, "[%p] EPS utilization cleared.", this);
+ }
+}
+
void ServerMetricRecorder::ClearNamedUtilization(string_ref name) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_backend_metric_trace)) {
gpr_log(GPR_INFO, "[%p] Named utilization cleared. name: %s", this,
@@ -189,9 +210,9 @@ ServerMetricRecorder::GetMetricsIfChanged() const {
const auto& data = result->data;
gpr_log(GPR_INFO,
"[%p] GetMetrics() returned: seq:%" PRIu64
- " cpu:%f mem:%f qps:%f utilization size: %" PRIuPTR,
+ " cpu:%f mem:%f qps:%f eps:%f utilization size: %" PRIuPTR,
this, result->sequence_number, data.cpu_utilization,
- data.mem_utilization, data.qps, data.utilization.size());
+ data.mem_utilization, data.qps, data.eps, data.utilization.size());
}
return result;
}
@@ -230,7 +251,7 @@ BackendMetricState::RecordMemoryUtilizationMetric(double value) {
experimental::CallMetricRecorder& BackendMetricState::RecordQpsMetric(
double value) {
- if (!IsQpsValid(value)) {
+ if (!IsRateValid(value)) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_backend_metric_trace)) {
gpr_log(GPR_INFO, "[%p] QPS value rejected: %f", this, value);
}
@@ -243,6 +264,21 @@ experimental::CallMetricRecorder& BackendMetricState::RecordQpsMetric(
return *this;
}
+experimental::CallMetricRecorder& BackendMetricState::RecordEpsMetric(
+ double value) {
+ if (!IsRateValid(value)) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_backend_metric_trace)) {
+ gpr_log(GPR_INFO, "[%p] EPS value rejected: %f", this, value);
+ }
+ return *this;
+ }
+ eps_.store(value, std::memory_order_relaxed);
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_backend_metric_trace)) {
+ gpr_log(GPR_INFO, "[%p] EPS recorded: %f", this, value);
+ }
+ return *this;
+}
+
experimental::CallMetricRecorder& BackendMetricState::RecordUtilizationMetric(
string_ref name, double value) {
if (!IsUtilizationValid(value)) {
@@ -274,6 +310,18 @@ experimental::CallMetricRecorder& BackendMetricState::RecordRequestCostMetric(
return *this;
}
+experimental::CallMetricRecorder& BackendMetricState::RecordNamedMetric(
+ string_ref name, double value) {
+ internal::MutexLock lock(&mu_);
+ y_absl::string_view name_sv(name.data(), name.length());
+ named_metrics_[name_sv] = value;
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_backend_metric_trace)) {
+ gpr_log(GPR_INFO, "[%p] Named metric recorded: %s %f", this,
+ TString(name_sv).c_str(), value);
+ }
+ return *this;
+}
+
BackendMetricData BackendMetricState::GetBackendMetricData() {
// Merge metrics from the ServerMetricRecorder first since metrics recorded
// to CallMetricRecorder takes a higher precedence.
@@ -291,20 +339,33 @@ BackendMetricData BackendMetricState::GetBackendMetricData() {
data.mem_utilization = mem;
}
const double qps = qps_.load(std::memory_order_relaxed);
- if (IsQpsValid(qps)) {
+ if (IsRateValid(qps)) {
data.qps = qps;
}
+ const double eps = eps_.load(std::memory_order_relaxed);
+ if (IsRateValid(eps)) {
+ data.eps = eps;
+ }
{
internal::MutexLock lock(&mu_);
- data.utilization = std::move(utilization_);
- data.request_cost = std::move(request_cost_);
+ for (const auto& u : utilization_) {
+ data.utilization[u.first] = u.second;
+ }
+ for (const auto& r : request_cost_) {
+ data.request_cost[r.first] = r.second;
+ }
+ for (const auto& r : named_metrics_) {
+ data.named_metrics[r.first] = r.second;
+ }
}
if (GRPC_TRACE_FLAG_ENABLED(grpc_backend_metric_trace)) {
gpr_log(GPR_INFO,
- "[%p] Backend metric data returned: cpu:%f mem:%f qps:%f "
- "utilization size:%" PRIuPTR " request_cost size:%" PRIuPTR,
+ "[%p] Backend metric data returned: cpu:%f mem:%f qps:%f eps:%f "
+ "utilization size:%" PRIuPTR " request_cost size:%" PRIuPTR
+ "named_metrics size:%" PRIuPTR,
this, data.cpu_utilization, data.mem_utilization, data.qps,
- data.utilization.size(), data.request_cost.size());
+ data.eps, data.utilization.size(), data.request_cost.size(),
+ data.named_metrics.size());
}
return data;
}
diff --git a/contrib/libs/grpc/src/cpp/server/backend_metric_recorder.h b/contrib/libs/grpc/src/cpp/server/backend_metric_recorder.h
index 7634b61ad8..6de0a08469 100644
--- a/contrib/libs/grpc/src/cpp/server/backend_metric_recorder.h
+++ b/contrib/libs/grpc/src/cpp/server/backend_metric_recorder.h
@@ -59,10 +59,13 @@ class BackendMetricState : public grpc_core::BackendMetricProvider,
experimental::CallMetricRecorder& RecordMemoryUtilizationMetric(
double value) override;
experimental::CallMetricRecorder& RecordQpsMetric(double value) override;
+ experimental::CallMetricRecorder& RecordEpsMetric(double value) override;
experimental::CallMetricRecorder& RecordUtilizationMetric(
string_ref name, double value) override;
experimental::CallMetricRecorder& RecordRequestCostMetric(
string_ref name, double value) override;
+ experimental::CallMetricRecorder& RecordNamedMetric(string_ref name,
+ double value) override;
// This clears metrics currently recorded. Don't call twice.
grpc_core::BackendMetricData GetBackendMetricData() override;
@@ -71,9 +74,11 @@ class BackendMetricState : public grpc_core::BackendMetricProvider,
std::atomic<double> cpu_utilization_{-1.0};
std::atomic<double> mem_utilization_{-1.0};
std::atomic<double> qps_{-1.0};
+ std::atomic<double> eps_{-1.0};
internal::Mutex mu_;
std::map<y_absl::string_view, double> utilization_ Y_ABSL_GUARDED_BY(mu_);
std::map<y_absl::string_view, double> request_cost_ Y_ABSL_GUARDED_BY(mu_);
+ std::map<y_absl::string_view, double> named_metrics_ Y_ABSL_GUARDED_BY(mu_);
};
} // namespace grpc
diff --git a/contrib/libs/grpc/third_party/README.md b/contrib/libs/grpc/third_party/README.md
index 4425c05620..505efe13e4 100644
--- a/contrib/libs/grpc/third_party/README.md
+++ b/contrib/libs/grpc/third_party/README.md
@@ -58,26 +58,29 @@ Updating some dependencies requires extra care.
### Updating third_party/boringssl-with-bazel
-- Update the `third_party/boringssl-with-bazel` submodule to the latest [`main-with-bazel`](https://github.com/google/boringssl/tree/main-with-bazel) branch
+NOTE: updating the boringssl dependency is now part of the internal grpc release tooling (see [go/grpc-release](http://go/grpc-release)).
+Prefer using the release tooling when possible. The instructions below are provided as a reference and aren't guaranteed to be up-to-date.
+
+- Update the `third_party/boringssl-with-bazel` submodule to the latest [`master-with-bazel`](https://github.com/google/boringssl/tree/master-with-bazel) branch
```
git submodule update --init # just to start in a clean state
cd third_party/boringssl-with-bazel
git fetch origin # fetch what's new in the boringssl repository
-git checkout origin/main-with-bazel # checkout the current state of main-with-bazel branch in the boringssl repo
-# Note the latest commit SHA on main-with-bazel branch
+git checkout origin/master-with-bazel # checkout the current state of master-with-bazel branch in the boringssl repo
+# Note the latest commit SHA on master-with-bazel branch
cd ../.. # go back to grpc repo root
git status # will show that there are new commits in third_party/boringssl-with-bazel
git add third_party/boringssl-with-bazel # we actually want to update the changes to the submodule
-git commit -m "update submodule boringssl-with-bazel with origin/main-with-bazel" # commit
+git commit -m "update submodule boringssl-with-bazel with origin/master-with-bazel" # commit
```
-- Update boringssl dependency in `bazel/grpc_deps.bzl` to the same commit SHA as main-with-bazel branch
+- Update boringssl dependency in `bazel/grpc_deps.bzl` to the same commit SHA as master-with-bazel branch
- Update `http_archive(name = "boringssl",` section by updating the sha in `strip_prefix` and `urls` fields.
- Also, set `sha256` field to "" as the existing value is not valid. This will be added later once we know what that value is.
- Update `tools/run_tests/sanity/check_submodules.sh` with the same commit
-- Commit these changes `git commit -m "update boringssl dependency to main-with-bazel commit SHA"`
+- Commit these changes `git commit -m "update boringssl dependency to master-with-bazel commit SHA"`
- Run `tools/buildgen/generate_projects.sh` to regenerate the generated files
- Because `sha256` in `bazel/grpc_deps.bzl` was left empty, you will get a DEBUG msg like this one:
@@ -104,7 +107,7 @@ git commit -m "update submodule boringssl-with-bazel with origin/main-with-bazel
### Updating third_party/protobuf
-See http://go/grpc-third-party-protobuf-update-instructions (internal only)
+Updating the protobuf dependency is now part of the internal release process (see [go/grpc-release](http://go/grpc-release)).
### Updating third_party/envoy-api
diff --git a/contrib/libs/grpc/ya.make b/contrib/libs/grpc/ya.make
index c956bb9f51..f1d90e4584 100644
--- a/contrib/libs/grpc/ya.make
+++ b/contrib/libs/grpc/ya.make
@@ -2,9 +2,9 @@
LIBRARY()
-VERSION(1.53.1)
+VERSION(1.54.2)
-ORIGINAL_SOURCE(https://github.com/grpc/grpc/archive/v1.53.1.tar.gz)
+ORIGINAL_SOURCE(https://github.com/grpc/grpc/archive/v1.54.2.tar.gz)
LICENSE(
Apache-2.0 AND
@@ -26,6 +26,7 @@ PEERDIR(
contrib/restricted/abseil-cpp-tstring/y_absl/algorithm
contrib/restricted/abseil-cpp-tstring/y_absl/base
contrib/restricted/abseil-cpp-tstring/y_absl/container
+ contrib/restricted/abseil-cpp-tstring/y_absl/flags
contrib/restricted/abseil-cpp-tstring/y_absl/functional
contrib/restricted/abseil-cpp-tstring/y_absl/hash
contrib/restricted/abseil-cpp-tstring/y_absl/memory
@@ -108,7 +109,6 @@ SRCS(
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc
- src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc
src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc
@@ -136,6 +136,7 @@ SRCS(
src/core/ext/filters/server_config_selector/server_config_selector_filter.cc
src/core/ext/filters/stateful_session/stateful_session_filter.cc
src/core/ext/filters/stateful_session/stateful_session_service_config_parser.cc
+ src/core/ext/gcp/metadata_query.cc
src/core/ext/transport/binder/client/binder_connector.cc
src/core/ext/transport/binder/client/channel_create.cc
src/core/ext/transport/binder/client/channel_create_impl.cc
@@ -522,6 +523,7 @@ SRCS(
src/core/lib/address_utils/sockaddr_utils.cc
src/core/lib/backoff/backoff.cc
src/core/lib/backoff/random_early_detection.cc
+ src/core/lib/channel/call_tracer.cc
src/core/lib/channel/channel_args.cc
src/core/lib/channel/channel_args_preconditioning.cc
src/core/lib/channel/channel_stack.cc
@@ -532,11 +534,15 @@ SRCS(
src/core/lib/channel/channelz_registry.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/promise_based_filter.cc
+ src/core/lib/channel/server_call_tracer_filter.cc
src/core/lib/channel/status_util.cc
src/core/lib/compression/compression.cc
src/core/lib/compression/compression_internal.cc
src/core/lib/compression/message_compress.cc
+ src/core/lib/config/config_vars.cc
+ src/core/lib/config/config_vars_non_generated.cc
src/core/lib/config/core_configuration.cc
+ src/core/lib/config/load_config.cc
src/core/lib/debug/event_log.cc
src/core/lib/debug/histogram_view.cc
src/core/lib/debug/stats.cc
@@ -579,56 +585,56 @@ SRCS(
src/core/lib/event_engine/windows/win_socket.cc
src/core/lib/event_engine/windows/windows_endpoint.cc
src/core/lib/event_engine/windows/windows_engine.cc
+ src/core/lib/event_engine/windows/windows_listener.cc
src/core/lib/experiments/config.cc
src/core/lib/experiments/experiments.cc
src/core/lib/gpr/alloc.cc
+ src/core/lib/gpr/android/log.cc
src/core/lib/gpr/atm.cc
- src/core/lib/gpr/cpu_iphone.cc
- src/core/lib/gpr/cpu_linux.cc
- src/core/lib/gpr/cpu_posix.cc
- src/core/lib/gpr/cpu_windows.cc
+ src/core/lib/gpr/iphone/cpu.cc
+ src/core/lib/gpr/linux/cpu.cc
+ src/core/lib/gpr/linux/log.cc
src/core/lib/gpr/log.cc
- src/core/lib/gpr/log_android.cc
- src/core/lib/gpr/log_linux.cc
- src/core/lib/gpr/log_posix.cc
- src/core/lib/gpr/log_windows.cc
+ src/core/lib/gpr/msys/tmpfile.cc
+ src/core/lib/gpr/posix/cpu.cc
+ src/core/lib/gpr/posix/log.cc
+ src/core/lib/gpr/posix/string.cc
+ src/core/lib/gpr/posix/sync.cc
+ src/core/lib/gpr/posix/time.cc
+ src/core/lib/gpr/posix/tmpfile.cc
src/core/lib/gpr/string.cc
- src/core/lib/gpr/string_posix.cc
- src/core/lib/gpr/string_util_windows.cc
- src/core/lib/gpr/string_windows.cc
src/core/lib/gpr/sync.cc
src/core/lib/gpr/sync_abseil.cc
- src/core/lib/gpr/sync_posix.cc
- src/core/lib/gpr/sync_windows.cc
src/core/lib/gpr/time.cc
- src/core/lib/gpr/time_posix.cc
src/core/lib/gpr/time_precise.cc
- src/core/lib/gpr/time_windows.cc
- src/core/lib/gpr/tmpfile_msys.cc
- src/core/lib/gpr/tmpfile_posix.cc
- src/core/lib/gpr/tmpfile_windows.cc
+ src/core/lib/gpr/windows/cpu.cc
+ src/core/lib/gpr/windows/log.cc
+ src/core/lib/gpr/windows/string.cc
+ src/core/lib/gpr/windows/string_util.cc
+ src/core/lib/gpr/windows/sync.cc
+ src/core/lib/gpr/windows/time.cc
+ src/core/lib/gpr/windows/tmpfile.cc
src/core/lib/gpr/wrap_memcpy.cc
src/core/lib/gprpp/crash.cc
- src/core/lib/gprpp/env_linux.cc
- src/core/lib/gprpp/env_posix.cc
- src/core/lib/gprpp/env_windows.cc
src/core/lib/gprpp/examine_stack.cc
src/core/lib/gprpp/fork.cc
- src/core/lib/gprpp/global_config_env.cc
src/core/lib/gprpp/host_port.cc
+ src/core/lib/gprpp/linux/env.cc
src/core/lib/gprpp/load_file.cc
src/core/lib/gprpp/mpscq.cc
- src/core/lib/gprpp/stat_posix.cc
- src/core/lib/gprpp/stat_windows.cc
+ src/core/lib/gprpp/posix/env.cc
+ src/core/lib/gprpp/posix/stat.cc
+ src/core/lib/gprpp/posix/thd.cc
src/core/lib/gprpp/status_helper.cc
src/core/lib/gprpp/strerror.cc
src/core/lib/gprpp/tchar.cc
- src/core/lib/gprpp/thd_posix.cc
- src/core/lib/gprpp/thd_windows.cc
src/core/lib/gprpp/time.cc
src/core/lib/gprpp/time_averaged_stats.cc
src/core/lib/gprpp/time_util.cc
src/core/lib/gprpp/validation_errors.cc
+ src/core/lib/gprpp/windows/env.cc
+ src/core/lib/gprpp/windows/stat.cc
+ src/core/lib/gprpp/windows/thd.cc
src/core/lib/gprpp/work_serializer.cc
src/core/lib/handshaker/proxy_mapper_registry.cc
src/core/lib/http/format_request.cc
@@ -720,6 +726,7 @@ SRCS(
src/core/lib/load_balancing/lb_policy_registry.cc
src/core/lib/matchers/matchers.cc
src/core/lib/promise/activity.cc
+ src/core/lib/promise/party.cc
src/core/lib/promise/sleep.cc
src/core/lib/promise/trace.cc
src/core/lib/resolver/resolver.cc
@@ -786,7 +793,6 @@ SRCS(
src/core/lib/security/security_connector/security_connector.cc
src/core/lib/security/security_connector/ssl/ssl_security_connector.cc
src/core/lib/security/security_connector/ssl_utils.cc
- src/core/lib/security/security_connector/ssl_utils_config.cc
src/core/lib/security/security_connector/tls/tls_security_connector.cc
src/core/lib/security/transport/client_auth_filter.cc
src/core/lib/security/transport/secure_endpoint.cc
@@ -824,6 +830,7 @@ SRCS(
src/core/lib/surface/server.cc
src/core/lib/surface/validate_metadata.cc
src/core/lib/surface/version.cc
+ src/core/lib/transport/batch_builder.cc
src/core/lib/transport/bdp_estimator.cc
src/core/lib/transport/connectivity_state.cc
src/core/lib/transport/error_utils.cc
@@ -874,6 +881,7 @@ SRCS(
src/cpp/client/client_callback.cc
src/cpp/client/client_context.cc
src/cpp/client/client_interceptor.cc
+ src/cpp/client/client_stats_interceptor.cc
src/cpp/client/create_channel.cc
src/cpp/client/create_channel_internal.cc
src/cpp/client/create_channel_posix.cc
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/CMakeLists.txt b/contrib/restricted/abseil-cpp-tstring/y_absl/CMakeLists.txt
index e9b44bd27d..f6aaf30d40 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/CMakeLists.txt
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/CMakeLists.txt
@@ -10,6 +10,7 @@ add_subdirectory(algorithm)
add_subdirectory(base)
add_subdirectory(container)
add_subdirectory(debugging)
+add_subdirectory(flags)
add_subdirectory(functional)
add_subdirectory(hash)
add_subdirectory(memory)
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.darwin-x86_64.txt b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.darwin-x86_64.txt
new file mode 100644
index 0000000000..df26b1e9b5
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.darwin-x86_64.txt
@@ -0,0 +1,45 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(abseil-cpp-tstring-y_absl-flags)
+target_compile_options(abseil-cpp-tstring-y_absl-flags PRIVATE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(abseil-cpp-tstring-y_absl-flags PUBLIC
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring
+)
+target_link_libraries(abseil-cpp-tstring-y_absl-flags PUBLIC
+ contrib-libs-cxxsupp
+ yutil
+ abseil-cpp-tstring-y_absl-base
+ abseil-cpp-tstring-y_absl-container
+ abseil-cpp-tstring-y_absl-debugging
+ abseil-cpp-tstring-y_absl-hash
+ abseil-cpp-tstring-y_absl-memory
+ abseil-cpp-tstring-y_absl-numeric
+ abseil-cpp-tstring-y_absl-profiling
+ abseil-cpp-tstring-y_absl-strings
+ abseil-cpp-tstring-y_absl-synchronization
+ abseil-cpp-tstring-y_absl-time
+ abseil-cpp-tstring-y_absl-types
+)
+target_sources(abseil-cpp-tstring-y_absl-flags PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/commandlineflag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/flag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/commandlineflag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/private_handle_accessor.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/program_name.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/usage.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/marshalling.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/parse.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/reflection.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage_config.cc
+)
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.linux-aarch64.txt b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.linux-aarch64.txt
new file mode 100644
index 0000000000..7672e6df4f
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.linux-aarch64.txt
@@ -0,0 +1,46 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(abseil-cpp-tstring-y_absl-flags)
+target_compile_options(abseil-cpp-tstring-y_absl-flags PRIVATE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(abseil-cpp-tstring-y_absl-flags PUBLIC
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring
+)
+target_link_libraries(abseil-cpp-tstring-y_absl-flags PUBLIC
+ contrib-libs-linux-headers
+ contrib-libs-cxxsupp
+ yutil
+ abseil-cpp-tstring-y_absl-base
+ abseil-cpp-tstring-y_absl-container
+ abseil-cpp-tstring-y_absl-debugging
+ abseil-cpp-tstring-y_absl-hash
+ abseil-cpp-tstring-y_absl-memory
+ abseil-cpp-tstring-y_absl-numeric
+ abseil-cpp-tstring-y_absl-profiling
+ abseil-cpp-tstring-y_absl-strings
+ abseil-cpp-tstring-y_absl-synchronization
+ abseil-cpp-tstring-y_absl-time
+ abseil-cpp-tstring-y_absl-types
+)
+target_sources(abseil-cpp-tstring-y_absl-flags PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/commandlineflag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/flag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/commandlineflag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/private_handle_accessor.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/program_name.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/usage.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/marshalling.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/parse.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/reflection.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage_config.cc
+)
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.linux-x86_64.txt b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.linux-x86_64.txt
new file mode 100644
index 0000000000..7672e6df4f
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.linux-x86_64.txt
@@ -0,0 +1,46 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(abseil-cpp-tstring-y_absl-flags)
+target_compile_options(abseil-cpp-tstring-y_absl-flags PRIVATE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(abseil-cpp-tstring-y_absl-flags PUBLIC
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring
+)
+target_link_libraries(abseil-cpp-tstring-y_absl-flags PUBLIC
+ contrib-libs-linux-headers
+ contrib-libs-cxxsupp
+ yutil
+ abseil-cpp-tstring-y_absl-base
+ abseil-cpp-tstring-y_absl-container
+ abseil-cpp-tstring-y_absl-debugging
+ abseil-cpp-tstring-y_absl-hash
+ abseil-cpp-tstring-y_absl-memory
+ abseil-cpp-tstring-y_absl-numeric
+ abseil-cpp-tstring-y_absl-profiling
+ abseil-cpp-tstring-y_absl-strings
+ abseil-cpp-tstring-y_absl-synchronization
+ abseil-cpp-tstring-y_absl-time
+ abseil-cpp-tstring-y_absl-types
+)
+target_sources(abseil-cpp-tstring-y_absl-flags PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/commandlineflag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/flag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/commandlineflag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/private_handle_accessor.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/program_name.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/usage.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/marshalling.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/parse.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/reflection.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage_config.cc
+)
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.txt b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.txt
new file mode 100644
index 0000000000..f8b31df0c1
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.txt
@@ -0,0 +1,17 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND NOT HAVE_CUDA)
+ include(CMakeLists.linux-aarch64.txt)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
+ include(CMakeLists.darwin-x86_64.txt)
+elseif (WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" AND NOT HAVE_CUDA)
+ include(CMakeLists.windows-x86_64.txt)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND NOT HAVE_CUDA)
+ include(CMakeLists.linux-x86_64.txt)
+endif()
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.windows-x86_64.txt b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.windows-x86_64.txt
new file mode 100644
index 0000000000..df26b1e9b5
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/CMakeLists.windows-x86_64.txt
@@ -0,0 +1,45 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(abseil-cpp-tstring-y_absl-flags)
+target_compile_options(abseil-cpp-tstring-y_absl-flags PRIVATE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(abseil-cpp-tstring-y_absl-flags PUBLIC
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring
+)
+target_link_libraries(abseil-cpp-tstring-y_absl-flags PUBLIC
+ contrib-libs-cxxsupp
+ yutil
+ abseil-cpp-tstring-y_absl-base
+ abseil-cpp-tstring-y_absl-container
+ abseil-cpp-tstring-y_absl-debugging
+ abseil-cpp-tstring-y_absl-hash
+ abseil-cpp-tstring-y_absl-memory
+ abseil-cpp-tstring-y_absl-numeric
+ abseil-cpp-tstring-y_absl-profiling
+ abseil-cpp-tstring-y_absl-strings
+ abseil-cpp-tstring-y_absl-synchronization
+ abseil-cpp-tstring-y_absl-time
+ abseil-cpp-tstring-y_absl-types
+)
+target_sources(abseil-cpp-tstring-y_absl-flags PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/commandlineflag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/flag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/commandlineflag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/private_handle_accessor.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/program_name.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/usage.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/marshalling.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/parse.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/reflection.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage_config.cc
+)
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/commandlineflag.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/commandlineflag.cc
new file mode 100644
index 0000000000..b70a9815c9
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/commandlineflag.cc
@@ -0,0 +1,34 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "y_absl/flags/commandlineflag.h"
+
+#include <util/generic/string.h>
+
+#include "y_absl/base/config.h"
+#include "y_absl/flags/internal/commandlineflag.h"
+#include "y_absl/strings/string_view.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+
+bool CommandLineFlag::IsRetired() const { return false; }
+bool CommandLineFlag::ParseFrom(y_absl::string_view value, TString* error) {
+ return ParseFrom(value, flags_internal::SET_FLAGS_VALUE,
+ flags_internal::kProgrammaticChange, *error);
+}
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/commandlineflag.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/commandlineflag.h
new file mode 100644
index 0000000000..30c2bb07a5
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/commandlineflag.h
@@ -0,0 +1,200 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: commandlineflag.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `CommandLineFlag`, which acts as a type-erased
+// handle for accessing metadata about the Abseil Flag in question.
+//
+// Because an actual Abseil flag is of an unspecified type, you should not
+// manipulate or interact directly with objects of that type. Instead, use the
+// CommandLineFlag type as an intermediary.
+#ifndef Y_ABSL_FLAGS_COMMANDLINEFLAG_H_
+#define Y_ABSL_FLAGS_COMMANDLINEFLAG_H_
+
+#include <memory>
+#include <util/generic/string.h>
+
+#include "y_absl/base/config.h"
+#include "y_absl/base/internal/fast_type_id.h"
+#include "y_absl/flags/internal/commandlineflag.h"
+#include "y_absl/strings/string_view.h"
+#include "y_absl/types/optional.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+class PrivateHandleAccessor;
+} // namespace flags_internal
+
+// CommandLineFlag
+//
+// This type acts as a type-erased handle for an instance of an Abseil Flag and
+// holds reflection information pertaining to that flag. Use CommandLineFlag to
+// access a flag's name, location, help string etc.
+//
+// To obtain an y_absl::CommandLineFlag, invoke `y_absl::FindCommandLineFlag()`
+// passing it the flag name string.
+//
+// Example:
+//
+// // Obtain reflection handle for a flag named "flagname".
+// const y_absl::CommandLineFlag* my_flag_data =
+// y_absl::FindCommandLineFlag("flagname");
+//
+// // Now you can get flag info from that reflection handle.
+// TString flag_location = my_flag_data->Filename();
+// ...
+class CommandLineFlag {
+ public:
+ constexpr CommandLineFlag() = default;
+
+ // Not copyable/assignable.
+ CommandLineFlag(const CommandLineFlag&) = delete;
+ CommandLineFlag& operator=(const CommandLineFlag&) = delete;
+
+ // y_absl::CommandLineFlag::IsOfType()
+ //
+ // Return true iff flag has type T.
+ template <typename T>
+ inline bool IsOfType() const {
+ return TypeId() == base_internal::FastTypeId<T>();
+ }
+
+ // y_absl::CommandLineFlag::TryGet()
+ //
+ // Attempts to retrieve the flag value. Returns value on success,
+ // y_absl::nullopt otherwise.
+ template <typename T>
+ y_absl::optional<T> TryGet() const {
+ if (IsRetired() || !IsOfType<T>()) {
+ return y_absl::nullopt;
+ }
+
+ // Implementation notes:
+ //
+ // We are wrapping a union around the value of `T` to serve three purposes:
+ //
+ // 1. `U.value` has correct size and alignment for a value of type `T`
+ // 2. The `U.value` constructor is not invoked since U's constructor does
+ // not do it explicitly.
+ // 3. The `U.value` destructor is invoked since U's destructor does it
+ // explicitly. This makes `U` a kind of RAII wrapper around non default
+ // constructible value of T, which is destructed when we leave the
+ // scope. We do need to destroy U.value, which is constructed by
+ // CommandLineFlag::Read even though we left it in a moved-from state
+ // after std::move.
+ //
+ // All of this serves to avoid requiring `T` being default constructible.
+ union U {
+ T value;
+ U() {}
+ ~U() { value.~T(); }
+ };
+ U u;
+
+ Read(&u.value);
+ // allow retired flags to be "read", so we can report invalid access.
+ if (IsRetired()) {
+ return y_absl::nullopt;
+ }
+ return std::move(u.value);
+ }
+
+ // y_absl::CommandLineFlag::Name()
+ //
+ // Returns name of this flag.
+ virtual y_absl::string_view Name() const = 0;
+
+ // y_absl::CommandLineFlag::Filename()
+ //
+ // Returns name of the file where this flag is defined.
+ virtual TString Filename() const = 0;
+
+ // y_absl::CommandLineFlag::Help()
+ //
+ // Returns help message associated with this flag.
+ virtual TString Help() const = 0;
+
+ // y_absl::CommandLineFlag::IsRetired()
+ //
+ // Returns true iff this object corresponds to retired flag.
+ virtual bool IsRetired() const;
+
+ // y_absl::CommandLineFlag::DefaultValue()
+ //
+ // Returns the default value for this flag.
+ virtual TString DefaultValue() const = 0;
+
+ // y_absl::CommandLineFlag::CurrentValue()
+ //
+ // Returns the current value for this flag.
+ virtual TString CurrentValue() const = 0;
+
+ // y_absl::CommandLineFlag::ParseFrom()
+ //
+ // Sets the value of the flag based on specified string `value`. If the flag
+ // was successfully set to new value, it returns true. Otherwise, sets `error`
+ // to indicate the error, leaves the flag unchanged, and returns false.
+ bool ParseFrom(y_absl::string_view value, TString* error);
+
+ protected:
+ ~CommandLineFlag() = default;
+
+ private:
+ friend class flags_internal::PrivateHandleAccessor;
+
+ // Sets the value of the flag based on specified string `value`. If the flag
+ // was successfully set to new value, it returns true. Otherwise, sets `error`
+ // to indicate the error, leaves the flag unchanged, and returns false. There
+ // are three ways to set the flag's value:
+ // * Update the current flag value
+ // * Update the flag's default value
+ // * Update the current flag value if it was never set before
+ // The mode is selected based on `set_mode` parameter.
+ virtual bool ParseFrom(y_absl::string_view value,
+ flags_internal::FlagSettingMode set_mode,
+ flags_internal::ValueSource source,
+ TString& error) = 0;
+
+ // Returns id of the flag's value type.
+ virtual flags_internal::FlagFastTypeId TypeId() const = 0;
+
+ // Interface to save flag to some persistent state. Returns current flag state
+ // or nullptr if flag does not support saving and restoring a state.
+ virtual std::unique_ptr<flags_internal::FlagStateInterface> SaveState() = 0;
+
+ // Copy-construct a new value of the flag's type in a memory referenced by
+ // the dst based on the current flag's value.
+ virtual void Read(void* dst) const = 0;
+
+ // To be deleted. Used to return true if flag's current value originated from
+ // command line.
+ virtual bool IsSpecifiedOnCommandLine() const = 0;
+
+ // Validates supplied value usign validator or parseflag routine
+ virtual bool ValidateInputValue(y_absl::string_view value) const = 0;
+
+ // Checks that flags default value can be converted to string and back to the
+ // flag's value type.
+ virtual void CheckDefaultValueParsingRoundtrip() const = 0;
+};
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_COMMANDLINEFLAG_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/config.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/config.h
new file mode 100644
index 0000000000..08de490eb1
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/config.h
@@ -0,0 +1,68 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef Y_ABSL_FLAGS_CONFIG_H_
+#define Y_ABSL_FLAGS_CONFIG_H_
+
+// Determine if we should strip string literals from the Flag objects.
+// By default we strip string literals on mobile platforms.
+#if !defined(Y_ABSL_FLAGS_STRIP_NAMES)
+
+#if defined(__ANDROID__)
+#define Y_ABSL_FLAGS_STRIP_NAMES 1
+
+#elif defined(__APPLE__)
+#include <TargetConditionals.h>
+#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+#define Y_ABSL_FLAGS_STRIP_NAMES 1
+#elif defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED
+#define Y_ABSL_FLAGS_STRIP_NAMES 1
+#endif // TARGET_OS_*
+#endif
+
+#endif // !defined(Y_ABSL_FLAGS_STRIP_NAMES)
+
+#if !defined(Y_ABSL_FLAGS_STRIP_NAMES)
+// If Y_ABSL_FLAGS_STRIP_NAMES wasn't set on the command line or above,
+// the default is not to strip.
+#define Y_ABSL_FLAGS_STRIP_NAMES 0
+#endif
+
+#if !defined(Y_ABSL_FLAGS_STRIP_HELP)
+// By default, if we strip names, we also strip help.
+#define Y_ABSL_FLAGS_STRIP_HELP Y_ABSL_FLAGS_STRIP_NAMES
+#endif
+
+// These macros represent the "source of truth" for the list of supported
+// built-in types.
+#define Y_ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \
+ A(bool, bool) \
+ A(short, short) \
+ A(unsigned short, unsigned_short) \
+ A(int, int) \
+ A(unsigned int, unsigned_int) \
+ A(long, long) \
+ A(unsigned long, unsigned_long) \
+ A(long long, long_long) \
+ A(unsigned long long, unsigned_long_long) \
+ A(double, double) \
+ A(float, float)
+
+#define Y_ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(A) \
+ Y_ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \
+ A(TString, std_string) \
+ A(std::vector<TString>, std_vector_of_string)
+
+#endif // Y_ABSL_FLAGS_CONFIG_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/declare.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/declare.h
new file mode 100644
index 0000000000..0b36402496
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/declare.h
@@ -0,0 +1,73 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: declare.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the Y_ABSL_DECLARE_FLAG macro, allowing you to declare an
+// `y_absl::Flag` for use within a translation unit. You should place this
+// declaration within the header file associated with the .cc file that defines
+// and owns the `Flag`.
+
+#ifndef Y_ABSL_FLAGS_DECLARE_H_
+#define Y_ABSL_FLAGS_DECLARE_H_
+
+#include "y_absl/base/config.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// y_absl::Flag<T> represents a flag of type 'T' created by Y_ABSL_FLAG.
+template <typename T>
+class Flag;
+
+} // namespace flags_internal
+
+// Flag
+//
+// Forward declaration of the `y_absl::Flag` type for use in defining the macro.
+#if defined(_MSC_VER) && !defined(__clang__)
+template <typename T>
+class Flag;
+#else
+template <typename T>
+using Flag = flags_internal::Flag<T>;
+#endif
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+// Y_ABSL_DECLARE_FLAG()
+//
+// This macro is a convenience for declaring use of an `y_absl::Flag` within a
+// translation unit. This macro should be used within a header file to
+// declare usage of the flag within any .cc file including that header file.
+//
+// The Y_ABSL_DECLARE_FLAG(type, name) macro expands to:
+//
+// extern y_absl::Flag<type> FLAGS_name;
+#define Y_ABSL_DECLARE_FLAG(type, name) Y_ABSL_DECLARE_FLAG_INTERNAL(type, name)
+
+// Internal implementation of Y_ABSL_DECLARE_FLAG to allow macro expansion of its
+// arguments. Clients must use Y_ABSL_DECLARE_FLAG instead.
+#define Y_ABSL_DECLARE_FLAG_INTERNAL(type, name) \
+ extern y_absl::Flag<type> FLAGS_##name; \
+ namespace y_absl /* block flags in namespaces */ {} \
+ /* second redeclaration is to allow applying attributes */ \
+ extern y_absl::Flag<type> FLAGS_##name
+
+#endif // Y_ABSL_FLAGS_DECLARE_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/flag.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/flag.cc
new file mode 100644
index 0000000000..9bc5137f3e
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/flag.cc
@@ -0,0 +1,38 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "y_absl/flags/flag.h"
+
+#include "y_absl/base/config.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+
+// This global mutex protects on-demand construction of flag objects in MSVC
+// builds.
+#if defined(_MSC_VER) && !defined(__clang__)
+
+namespace flags_internal {
+
+Y_ABSL_CONST_INIT static y_absl::Mutex construction_guard(y_absl::kConstInit);
+
+y_absl::Mutex* GetGlobalConstructionGuard() { return &construction_guard; }
+
+} // namespace flags_internal
+
+#endif
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/flag.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/flag.h
new file mode 100644
index 0000000000..65448650d3
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/flag.h
@@ -0,0 +1,310 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: flag.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `y_absl::Flag<T>` type for holding command-line
+// flag data, and abstractions to create, get and set such flag data.
+//
+// It is important to note that this type is **unspecified** (an implementation
+// detail) and you do not construct or manipulate actual `y_absl::Flag<T>`
+// instances. Instead, you define and declare flags using the
+// `Y_ABSL_FLAG()` and `Y_ABSL_DECLARE_FLAG()` macros, and get and set flag values
+// using the `y_absl::GetFlag()` and `y_absl::SetFlag()` functions.
+
+#ifndef Y_ABSL_FLAGS_FLAG_H_
+#define Y_ABSL_FLAGS_FLAG_H_
+
+#include <util/generic/string.h>
+#include <type_traits>
+
+#include "y_absl/base/attributes.h"
+#include "y_absl/base/config.h"
+#include "y_absl/base/optimization.h"
+#include "y_absl/flags/config.h"
+#include "y_absl/flags/internal/flag.h"
+#include "y_absl/flags/internal/registry.h"
+#include "y_absl/strings/string_view.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+
+// Flag
+//
+// An `y_absl::Flag` holds a command-line flag value, providing a runtime
+// parameter to a binary. Such flags should be defined in the global namespace
+// and (preferably) in the module containing the binary's `main()` function.
+//
+// You should not construct and cannot use the `y_absl::Flag` type directly;
+// instead, you should declare flags using the `Y_ABSL_DECLARE_FLAG()` macro
+// within a header file, and define your flag using `Y_ABSL_FLAG()` within your
+// header's associated `.cc` file. Such flags will be named `FLAGS_name`.
+//
+// Example:
+//
+// .h file
+//
+// // Declares usage of a flag named "FLAGS_count"
+// Y_ABSL_DECLARE_FLAG(int, count);
+//
+// .cc file
+//
+// // Defines a flag named "FLAGS_count" with a default `int` value of 0.
+// Y_ABSL_FLAG(int, count, 0, "Count of items to process");
+//
+// No public methods of `y_absl::Flag<T>` are part of the Abseil Flags API.
+//
+// For type support of Abseil Flags, see the marshalling.h header file, which
+// discusses supported standard types, optional flags, and additional Abseil
+// type support.
+#if !defined(_MSC_VER) || defined(__clang__)
+template <typename T>
+using Flag = flags_internal::Flag<T>;
+#else
+#include "y_absl/flags/internal/flag_msvc.inc"
+#endif
+
+// GetFlag()
+//
+// Returns the value (of type `T`) of an `y_absl::Flag<T>` instance, by value. Do
+// not construct an `y_absl::Flag<T>` directly and call `y_absl::GetFlag()`;
+// instead, refer to flag's constructed variable name (e.g. `FLAGS_name`).
+// Because this function returns by value and not by reference, it is
+// thread-safe, but note that the operation may be expensive; as a result, avoid
+// `y_absl::GetFlag()` within any tight loops.
+//
+// Example:
+//
+// // FLAGS_count is a Flag of type `int`
+// int my_count = y_absl::GetFlag(FLAGS_count);
+//
+// // FLAGS_firstname is a Flag of type `TString`
+// TString first_name = y_absl::GetFlag(FLAGS_firstname);
+template <typename T>
+Y_ABSL_MUST_USE_RESULT T GetFlag(const y_absl::Flag<T>& flag) {
+ return flags_internal::FlagImplPeer::InvokeGet<T>(flag);
+}
+
+// SetFlag()
+//
+// Sets the value of an `y_absl::Flag` to the value `v`. Do not construct an
+// `y_absl::Flag<T>` directly and call `y_absl::SetFlag()`; instead, use the
+// flag's variable name (e.g. `FLAGS_name`). This function is
+// thread-safe, but is potentially expensive. Avoid setting flags in general,
+// but especially within performance-critical code.
+template <typename T>
+void SetFlag(y_absl::Flag<T>* flag, const T& v) {
+ flags_internal::FlagImplPeer::InvokeSet(*flag, v);
+}
+
+// Overload of `SetFlag()` to allow callers to pass in a value that is
+// convertible to `T`. E.g., use this overload to pass a "const char*" when `T`
+// is `TString`.
+template <typename T, typename V>
+void SetFlag(y_absl::Flag<T>* flag, const V& v) {
+ T value(v);
+ flags_internal::FlagImplPeer::InvokeSet(*flag, value);
+}
+
+// GetFlagReflectionHandle()
+//
+// Returns the reflection handle corresponding to specified Abseil Flag
+// instance. Use this handle to access flag's reflection information, like name,
+// location, default value etc.
+//
+// Example:
+//
+// TString = y_absl::GetFlagReflectionHandle(FLAGS_count).DefaultValue();
+
+template <typename T>
+const CommandLineFlag& GetFlagReflectionHandle(const y_absl::Flag<T>& f) {
+ return flags_internal::FlagImplPeer::InvokeReflect(f);
+}
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+
+// Y_ABSL_FLAG()
+//
+// This macro defines an `y_absl::Flag<T>` instance of a specified type `T`:
+//
+// Y_ABSL_FLAG(T, name, default_value, help);
+//
+// where:
+//
+// * `T` is a supported flag type (see the list of types in `marshalling.h`),
+// * `name` designates the name of the flag (as a global variable
+// `FLAGS_name`),
+// * `default_value` is an expression holding the default value for this flag
+// (which must be implicitly convertible to `T`),
+// * `help` is the help text, which can also be an expression.
+//
+// This macro expands to a flag named 'FLAGS_name' of type 'T':
+//
+// y_absl::Flag<T> FLAGS_name = ...;
+//
+// Note that all such instances are created as global variables.
+//
+// For `Y_ABSL_FLAG()` values that you wish to expose to other translation units,
+// it is recommended to define those flags within the `.cc` file associated with
+// the header where the flag is declared.
+//
+// Note: do not construct objects of type `y_absl::Flag<T>` directly. Only use the
+// `Y_ABSL_FLAG()` macro for such construction.
+#define Y_ABSL_FLAG(Type, name, default_value, help) \
+ Y_ABSL_FLAG_IMPL(Type, name, default_value, help)
+
+// Y_ABSL_FLAG().OnUpdate()
+//
+// Defines a flag of type `T` with a callback attached:
+//
+// Y_ABSL_FLAG(T, name, default_value, help).OnUpdate(callback);
+//
+// `callback` should be convertible to `void (*)()`.
+//
+// After any setting of the flag value, the callback will be called at least
+// once. A rapid sequence of changes may be merged together into the same
+// callback. No concurrent calls to the callback will be made for the same
+// flag. Callbacks are allowed to read the current value of the flag but must
+// not mutate that flag.
+//
+// The update mechanism guarantees "eventual consistency"; if the callback
+// derives an auxiliary data structure from the flag value, it is guaranteed
+// that eventually the flag value and the derived data structure will be
+// consistent.
+//
+// Note: Y_ABSL_FLAG.OnUpdate() does not have a public definition. Hence, this
+// comment serves as its API documentation.
+
+// -----------------------------------------------------------------------------
+// Implementation details below this section
+// -----------------------------------------------------------------------------
+
+// Y_ABSL_FLAG_IMPL macro definition conditional on Y_ABSL_FLAGS_STRIP_NAMES
+#if !defined(_MSC_VER) || defined(__clang__)
+#define Y_ABSL_FLAG_IMPL_FLAG_PTR(flag) flag
+#define Y_ABSL_FLAG_IMPL_HELP_ARG(name) \
+ y_absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>( \
+ FLAGS_help_storage_##name)
+#define Y_ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) \
+ y_absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0)
+#else
+#define Y_ABSL_FLAG_IMPL_FLAG_PTR(flag) flag.GetImpl()
+#define Y_ABSL_FLAG_IMPL_HELP_ARG(name) &AbslFlagHelpGenFor##name::NonConst
+#define Y_ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) &AbslFlagDefaultGenFor##name::Gen
+#endif
+
+#if Y_ABSL_FLAGS_STRIP_NAMES
+#define Y_ABSL_FLAG_IMPL_FLAGNAME(txt) ""
+#define Y_ABSL_FLAG_IMPL_FILENAME() ""
+#define Y_ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
+ y_absl::flags_internal::FlagRegistrar<T, false>(Y_ABSL_FLAG_IMPL_FLAG_PTR(flag), \
+ nullptr)
+#else
+#define Y_ABSL_FLAG_IMPL_FLAGNAME(txt) txt
+#define Y_ABSL_FLAG_IMPL_FILENAME() __FILE__
+#define Y_ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
+ y_absl::flags_internal::FlagRegistrar<T, true>(Y_ABSL_FLAG_IMPL_FLAG_PTR(flag), \
+ __FILE__)
+#endif
+
+// Y_ABSL_FLAG_IMPL macro definition conditional on Y_ABSL_FLAGS_STRIP_HELP
+
+#if Y_ABSL_FLAGS_STRIP_HELP
+#define Y_ABSL_FLAG_IMPL_FLAGHELP(txt) y_absl::flags_internal::kStrippedFlagHelp
+#else
+#define Y_ABSL_FLAG_IMPL_FLAGHELP(txt) txt
+#endif
+
+// AbslFlagHelpGenFor##name is used to encapsulate both immediate (method Const)
+// and lazy (method NonConst) evaluation of help message expression. We choose
+// between the two via the call to HelpArg in y_absl::Flag instantiation below.
+// If help message expression is constexpr evaluable compiler will optimize
+// away this whole struct.
+// TODO(rogeeff): place these generated structs into local namespace and apply
+// Y_ABSL_INTERNAL_UNIQUE_SHORT_NAME.
+// TODO(rogeeff): Apply __attribute__((nodebug)) to FLAGS_help_storage_##name
+#define Y_ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt) \
+ struct AbslFlagHelpGenFor##name { \
+ /* The expression is run in the caller as part of the */ \
+ /* default value argument. That keeps temporaries alive */ \
+ /* long enough for NonConst to work correctly. */ \
+ static constexpr y_absl::string_view Value( \
+ y_absl::string_view absl_flag_help = Y_ABSL_FLAG_IMPL_FLAGHELP(txt)) { \
+ return absl_flag_help; \
+ } \
+ static TString NonConst() { return TString(Value()); } \
+ }; \
+ constexpr auto FLAGS_help_storage_##name Y_ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
+ Y_ABSL_ATTRIBUTE_SECTION_VARIABLE(flags_help_cold) = \
+ y_absl::flags_internal::HelpStringAsArray<AbslFlagHelpGenFor##name>( \
+ 0);
+
+#define Y_ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
+ struct AbslFlagDefaultGenFor##name { \
+ Type value = y_absl::flags_internal::InitDefaultValue<Type>(default_value); \
+ static void Gen(void* absl_flag_default_loc) { \
+ new (absl_flag_default_loc) Type(AbslFlagDefaultGenFor##name{}.value); \
+ } \
+ };
+
+// Y_ABSL_FLAG_IMPL
+//
+// Note: Name of registrar object is not arbitrary. It is used to "grab"
+// global name for FLAGS_no<flag_name> symbol, thus preventing the possibility
+// of defining two flags with names foo and nofoo.
+#define Y_ABSL_FLAG_IMPL(Type, name, default_value, help) \
+ extern ::y_absl::Flag<Type> FLAGS_##name; \
+ namespace y_absl /* block flags in namespaces */ {} \
+ Y_ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
+ Y_ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help) \
+ Y_ABSL_CONST_INIT y_absl::Flag<Type> FLAGS_##name{ \
+ Y_ABSL_FLAG_IMPL_FLAGNAME(#name), Y_ABSL_FLAG_IMPL_FILENAME(), \
+ Y_ABSL_FLAG_IMPL_HELP_ARG(name), Y_ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)}; \
+ extern y_absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name; \
+ y_absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name = \
+ Y_ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
+
+// Y_ABSL_RETIRED_FLAG
+//
+// Designates the flag (which is usually pre-existing) as "retired." A retired
+// flag is a flag that is now unused by the program, but may still be passed on
+// the command line, usually by production scripts. A retired flag is ignored
+// and code can't access it at runtime.
+//
+// This macro registers a retired flag with given name and type, with a name
+// identical to the name of the original flag you are retiring. The retired
+// flag's type can change over time, so that you can retire code to support a
+// custom flag type.
+//
+// This macro has the same signature as `Y_ABSL_FLAG`. To retire a flag, simply
+// replace an `Y_ABSL_FLAG` definition with `Y_ABSL_RETIRED_FLAG`, leaving the
+// arguments unchanged (unless of course you actually want to retire the flag
+// type at this time as well).
+//
+// `default_value` is only used as a double check on the type. `explanation` is
+// unused.
+// TODO(rogeeff): replace RETIRED_FLAGS with FLAGS once forward declarations of
+// retired flags are cleaned up.
+#define Y_ABSL_RETIRED_FLAG(type, name, default_value, explanation) \
+ static y_absl::flags_internal::RetiredFlag<type> RETIRED_FLAGS_##name; \
+ Y_ABSL_ATTRIBUTE_UNUSED static const auto RETIRED_FLAGS_REG_##name = \
+ (RETIRED_FLAGS_##name.Retire(#name), \
+ ::y_absl::flags_internal::FlagRegistrarEmpty{})
+
+#endif // Y_ABSL_FLAGS_FLAG_H_
diff --git a/contrib/libs/grpc/src/core/lib/gprpp/global_config_custom.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/commandlineflag.cc
index e1e06e6a19..d9c0f4d40e 100644
--- a/contrib/libs/grpc/src/core/lib/gprpp/global_config_custom.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/commandlineflag.cc
@@ -1,29 +1,26 @@
//
-//
-// Copyright 2019 gRPC authors.
+// Copyright 2020 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
-//
-#ifndef GRPC_SRC_CORE_LIB_GPRPP_GLOBAL_CONFIG_CUSTOM_H
-#define GRPC_SRC_CORE_LIB_GPRPP_GLOBAL_CONFIG_CUSTOM_H
+#include "y_absl/flags/internal/commandlineflag.h"
-// This is a placeholder for custom global configuration implementation.
-// To use the custom one, please define following macros here.
-//
-// GPR_GLOBAL_CONFIG_DEFINE_BOOL
-// GPR_GLOBAL_CONFIG_DEFINE_INT32
-// GPR_GLOBAL_CONFIG_DEFINE_STRING
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+FlagStateInterface::~FlagStateInterface() {}
-#endif // GRPC_SRC_CORE_LIB_GPRPP_GLOBAL_CONFIG_CUSTOM_H
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/commandlineflag.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/commandlineflag.h
new file mode 100644
index 0000000000..70d90d5441
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/commandlineflag.h
@@ -0,0 +1,68 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef Y_ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
+#define Y_ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
+
+#include "y_absl/base/config.h"
+#include "y_absl/base/internal/fast_type_id.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// An alias for flag fast type id. This value identifies the flag value type
+// similarly to typeid(T), without relying on RTTI being available. In most
+// cases this id is enough to uniquely identify the flag's value type. In a few
+// cases we'll have to resort to using actual RTTI implementation if it is
+// available.
+using FlagFastTypeId = y_absl::base_internal::FastTypeIdType;
+
+// Options that control SetCommandLineOptionWithMode.
+enum FlagSettingMode {
+ // update the flag's value unconditionally (can call this multiple times).
+ SET_FLAGS_VALUE,
+ // update the flag's value, but *only if* it has not yet been updated
+ // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
+ SET_FLAG_IF_DEFAULT,
+ // set the flag's default value to this. If the flag has not been updated
+ // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
+ // change the flag's current value to the new default value as well.
+ SET_FLAGS_DEFAULT
+};
+
+// Options that control ParseFrom: Source of a value.
+enum ValueSource {
+ // Flag is being set by value specified on a command line.
+ kCommandLine,
+ // Flag is being set by value specified in the code.
+ kProgrammaticChange,
+};
+
+// Handle to FlagState objects. Specific flag state objects will restore state
+// of a flag produced this flag state from method CommandLineFlag::SaveState().
+class FlagStateInterface {
+ public:
+ virtual ~FlagStateInterface();
+
+ // Restores the flag originated this object to the saved state.
+ virtual void Restore() const = 0;
+};
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag.cc
new file mode 100644
index 0000000000..30fcfb0eb0
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag.cc
@@ -0,0 +1,615 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "y_absl/flags/internal/flag.h"
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <array>
+#include <atomic>
+#include <memory>
+#include <new>
+#include <util/generic/string.h>
+#include <typeinfo>
+
+#include "y_absl/base/call_once.h"
+#include "y_absl/base/casts.h"
+#include "y_absl/base/config.h"
+#include "y_absl/base/dynamic_annotations.h"
+#include "y_absl/base/optimization.h"
+#include "y_absl/flags/config.h"
+#include "y_absl/flags/internal/commandlineflag.h"
+#include "y_absl/flags/usage_config.h"
+#include "y_absl/memory/memory.h"
+#include "y_absl/strings/str_cat.h"
+#include "y_absl/strings/string_view.h"
+#include "y_absl/synchronization/mutex.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// The help message indicating that the commandline flag has been
+// 'stripped'. It will not show up when doing "-help" and its
+// variants. The flag is stripped if Y_ABSL_FLAGS_STRIP_HELP is set to 1
+// before including y_absl/flags/flag.h
+const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
+
+namespace {
+
+// Currently we only validate flag values for user-defined flag types.
+bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) {
+#define DONT_VALIDATE(T, _) \
+ if (flag_type_id == base_internal::FastTypeId<T>()) return false;
+ Y_ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(DONT_VALIDATE)
+#undef DONT_VALIDATE
+
+ return true;
+}
+
+// RAII helper used to temporarily unlock and relock `y_absl::Mutex`.
+// This is used when we need to ensure that locks are released while
+// invoking user supplied callbacks and then reacquired, since callbacks may
+// need to acquire these locks themselves.
+class MutexRelock {
+ public:
+ explicit MutexRelock(y_absl::Mutex& mu) : mu_(mu) { mu_.Unlock(); }
+ ~MutexRelock() { mu_.Lock(); }
+
+ MutexRelock(const MutexRelock&) = delete;
+ MutexRelock& operator=(const MutexRelock&) = delete;
+
+ private:
+ y_absl::Mutex& mu_;
+};
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// Persistent state of the flag data.
+
+class FlagImpl;
+
+class FlagState : public flags_internal::FlagStateInterface {
+ public:
+ template <typename V>
+ FlagState(FlagImpl& flag_impl, const V& v, bool modified,
+ bool on_command_line, int64_t counter)
+ : flag_impl_(flag_impl),
+ value_(v),
+ modified_(modified),
+ on_command_line_(on_command_line),
+ counter_(counter) {}
+
+ ~FlagState() override {
+ if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer &&
+ flag_impl_.ValueStorageKind() != FlagValueStorageKind::kSequenceLocked)
+ return;
+ flags_internal::Delete(flag_impl_.op_, value_.heap_allocated);
+ }
+
+ private:
+ friend class FlagImpl;
+
+ // Restores the flag to the saved state.
+ void Restore() const override {
+ if (!flag_impl_.RestoreState(*this)) return;
+
+ Y_ABSL_INTERNAL_LOG(INFO,
+ y_absl::StrCat("Restore saved value of ", flag_impl_.Name(),
+ " to: ", flag_impl_.CurrentValue()));
+ }
+
+ // Flag and saved flag data.
+ FlagImpl& flag_impl_;
+ union SavedValue {
+ explicit SavedValue(void* v) : heap_allocated(v) {}
+ explicit SavedValue(int64_t v) : one_word(v) {}
+
+ void* heap_allocated;
+ int64_t one_word;
+ } value_;
+ bool modified_;
+ bool on_command_line_;
+ int64_t counter_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag implementation, which does not depend on flag value type.
+
+DynValueDeleter::DynValueDeleter(FlagOpFn op_arg) : op(op_arg) {}
+
+void DynValueDeleter::operator()(void* ptr) const {
+ if (op == nullptr) return;
+
+ Delete(op, ptr);
+}
+
+void FlagImpl::Init() {
+ new (&data_guard_) y_absl::Mutex;
+
+ auto def_kind = static_cast<FlagDefaultKind>(def_kind_);
+
+ switch (ValueStorageKind()) {
+ case FlagValueStorageKind::kValueAndInitBit:
+ case FlagValueStorageKind::kOneWordAtomic: {
+ alignas(int64_t) std::array<char, sizeof(int64_t)> buf{};
+ if (def_kind == FlagDefaultKind::kGenFunc) {
+ (*default_value_.gen_func)(buf.data());
+ } else {
+ assert(def_kind != FlagDefaultKind::kDynamicValue);
+ std::memcpy(buf.data(), &default_value_, Sizeof(op_));
+ }
+ if (ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit) {
+ // We presume here the memory layout of FlagValueAndInitBit struct.
+ uint8_t initialized = 1;
+ std::memcpy(buf.data() + Sizeof(op_), &initialized,
+ sizeof(initialized));
+ }
+ // Type can contain valid uninitialized bits, e.g. padding.
+ Y_ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(buf.data(), buf.size());
+ OneWordValue().store(y_absl::bit_cast<int64_t>(buf),
+ std::memory_order_release);
+ break;
+ }
+ case FlagValueStorageKind::kSequenceLocked: {
+ // For this storage kind the default_value_ always points to gen_func
+ // during initialization.
+ assert(def_kind == FlagDefaultKind::kGenFunc);
+ (*default_value_.gen_func)(AtomicBufferValue());
+ break;
+ }
+ case FlagValueStorageKind::kAlignedBuffer:
+ // For this storage kind the default_value_ always points to gen_func
+ // during initialization.
+ assert(def_kind == FlagDefaultKind::kGenFunc);
+ (*default_value_.gen_func)(AlignedBufferValue());
+ break;
+ }
+ seq_lock_.MarkInitialized();
+}
+
+y_absl::Mutex* FlagImpl::DataGuard() const {
+ y_absl::call_once(const_cast<FlagImpl*>(this)->init_control_, &FlagImpl::Init,
+ const_cast<FlagImpl*>(this));
+
+ // data_guard_ is initialized inside Init.
+ return reinterpret_cast<y_absl::Mutex*>(&data_guard_);
+}
+
+void FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id,
+ const std::type_info* (*gen_rtti)()) const {
+ FlagFastTypeId lhs_type_id = flags_internal::FastTypeId(op_);
+
+ // `rhs_type_id` is the fast type id corresponding to the declaration
+ // visibile at the call site. `lhs_type_id` is the fast type id
+ // corresponding to the type specified in flag definition. They must match
+ // for this operation to be well-defined.
+ if (Y_ABSL_PREDICT_TRUE(lhs_type_id == rhs_type_id)) return;
+
+ const std::type_info* lhs_runtime_type_id =
+ flags_internal::RuntimeTypeId(op_);
+ const std::type_info* rhs_runtime_type_id = (*gen_rtti)();
+
+ if (lhs_runtime_type_id == rhs_runtime_type_id) return;
+
+#ifdef Y_ABSL_INTERNAL_HAS_RTTI
+ if (*lhs_runtime_type_id == *rhs_runtime_type_id) return;
+#endif
+
+ Y_ABSL_INTERNAL_LOG(
+ FATAL, y_absl::StrCat("Flag '", Name(),
+ "' is defined as one type and declared as another"));
+}
+
+std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const {
+ void* res = nullptr;
+ switch (DefaultKind()) {
+ case FlagDefaultKind::kDynamicValue:
+ res = flags_internal::Clone(op_, default_value_.dynamic_value);
+ break;
+ case FlagDefaultKind::kGenFunc:
+ res = flags_internal::Alloc(op_);
+ (*default_value_.gen_func)(res);
+ break;
+ default:
+ res = flags_internal::Clone(op_, &default_value_);
+ break;
+ }
+ return {res, DynValueDeleter{op_}};
+}
+
+void FlagImpl::StoreValue(const void* src) {
+ switch (ValueStorageKind()) {
+ case FlagValueStorageKind::kValueAndInitBit:
+ case FlagValueStorageKind::kOneWordAtomic: {
+ // Load the current value to avoid setting 'init' bit manualy.
+ int64_t one_word_val = OneWordValue().load(std::memory_order_acquire);
+ std::memcpy(&one_word_val, src, Sizeof(op_));
+ OneWordValue().store(one_word_val, std::memory_order_release);
+ seq_lock_.IncrementModificationCount();
+ break;
+ }
+ case FlagValueStorageKind::kSequenceLocked: {
+ seq_lock_.Write(AtomicBufferValue(), src, Sizeof(op_));
+ break;
+ }
+ case FlagValueStorageKind::kAlignedBuffer:
+ Copy(op_, src, AlignedBufferValue());
+ seq_lock_.IncrementModificationCount();
+ break;
+ }
+ modified_ = true;
+ InvokeCallback();
+}
+
+y_absl::string_view FlagImpl::Name() const { return name_; }
+
+TString FlagImpl::Filename() const {
+ return flags_internal::GetUsageConfig().normalize_filename(filename_);
+}
+
+TString FlagImpl::Help() const {
+ return HelpSourceKind() == FlagHelpKind::kLiteral ? help_.literal
+ : help_.gen_func();
+}
+
+FlagFastTypeId FlagImpl::TypeId() const {
+ return flags_internal::FastTypeId(op_);
+}
+
+int64_t FlagImpl::ModificationCount() const {
+ return seq_lock_.ModificationCount();
+}
+
+bool FlagImpl::IsSpecifiedOnCommandLine() const {
+ y_absl::MutexLock l(DataGuard());
+ return on_command_line_;
+}
+
+TString FlagImpl::DefaultValue() const {
+ y_absl::MutexLock l(DataGuard());
+
+ auto obj = MakeInitValue();
+ return flags_internal::Unparse(op_, obj.get());
+}
+
+TString FlagImpl::CurrentValue() const {
+ auto* guard = DataGuard(); // Make sure flag initialized
+ switch (ValueStorageKind()) {
+ case FlagValueStorageKind::kValueAndInitBit:
+ case FlagValueStorageKind::kOneWordAtomic: {
+ const auto one_word_val =
+ y_absl::bit_cast<std::array<char, sizeof(int64_t)>>(
+ OneWordValue().load(std::memory_order_acquire));
+ return flags_internal::Unparse(op_, one_word_val.data());
+ }
+ case FlagValueStorageKind::kSequenceLocked: {
+ std::unique_ptr<void, DynValueDeleter> cloned(flags_internal::Alloc(op_),
+ DynValueDeleter{op_});
+ ReadSequenceLockedData(cloned.get());
+ return flags_internal::Unparse(op_, cloned.get());
+ }
+ case FlagValueStorageKind::kAlignedBuffer: {
+ y_absl::MutexLock l(guard);
+ return flags_internal::Unparse(op_, AlignedBufferValue());
+ }
+ }
+
+ return "";
+}
+
+void FlagImpl::SetCallback(const FlagCallbackFunc mutation_callback) {
+ y_absl::MutexLock l(DataGuard());
+
+ if (callback_ == nullptr) {
+ callback_ = new FlagCallback;
+ }
+ callback_->func = mutation_callback;
+
+ InvokeCallback();
+}
+
+void FlagImpl::InvokeCallback() const {
+ if (!callback_) return;
+
+ // Make a copy of the C-style function pointer that we are about to invoke
+ // before we release the lock guarding it.
+ FlagCallbackFunc cb = callback_->func;
+
+ // If the flag has a mutation callback this function invokes it. While the
+ // callback is being invoked the primary flag's mutex is unlocked and it is
+ // re-locked back after call to callback is completed. Callback invocation is
+ // guarded by flag's secondary mutex instead which prevents concurrent
+ // callback invocation. Note that it is possible for other thread to grab the
+ // primary lock and update flag's value at any time during the callback
+ // invocation. This is by design. Callback can get a value of the flag if
+ // necessary, but it might be different from the value initiated the callback
+ // and it also can be different by the time the callback invocation is
+ // completed. Requires that *primary_lock be held in exclusive mode; it may be
+ // released and reacquired by the implementation.
+ MutexRelock relock(*DataGuard());
+ y_absl::MutexLock lock(&callback_->guard);
+ cb();
+}
+
+std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() {
+ y_absl::MutexLock l(DataGuard());
+
+ bool modified = modified_;
+ bool on_command_line = on_command_line_;
+ switch (ValueStorageKind()) {
+ case FlagValueStorageKind::kValueAndInitBit:
+ case FlagValueStorageKind::kOneWordAtomic: {
+ return y_absl::make_unique<FlagState>(
+ *this, OneWordValue().load(std::memory_order_acquire), modified,
+ on_command_line, ModificationCount());
+ }
+ case FlagValueStorageKind::kSequenceLocked: {
+ void* cloned = flags_internal::Alloc(op_);
+ // Read is guaranteed to be successful because we hold the lock.
+ bool success =
+ seq_lock_.TryRead(cloned, AtomicBufferValue(), Sizeof(op_));
+ assert(success);
+ static_cast<void>(success);
+ return y_absl::make_unique<FlagState>(*this, cloned, modified,
+ on_command_line, ModificationCount());
+ }
+ case FlagValueStorageKind::kAlignedBuffer: {
+ return y_absl::make_unique<FlagState>(
+ *this, flags_internal::Clone(op_, AlignedBufferValue()), modified,
+ on_command_line, ModificationCount());
+ }
+ }
+ return nullptr;
+}
+
+bool FlagImpl::RestoreState(const FlagState& flag_state) {
+ y_absl::MutexLock l(DataGuard());
+ if (flag_state.counter_ == ModificationCount()) {
+ return false;
+ }
+
+ switch (ValueStorageKind()) {
+ case FlagValueStorageKind::kValueAndInitBit:
+ case FlagValueStorageKind::kOneWordAtomic:
+ StoreValue(&flag_state.value_.one_word);
+ break;
+ case FlagValueStorageKind::kSequenceLocked:
+ case FlagValueStorageKind::kAlignedBuffer:
+ StoreValue(flag_state.value_.heap_allocated);
+ break;
+ }
+
+ modified_ = flag_state.modified_;
+ on_command_line_ = flag_state.on_command_line_;
+
+ return true;
+}
+
+template <typename StorageT>
+StorageT* FlagImpl::OffsetValue() const {
+ char* p = reinterpret_cast<char*>(const_cast<FlagImpl*>(this));
+ // The offset is deduced via Flag value type specific op_.
+ ptrdiff_t offset = flags_internal::ValueOffset(op_);
+
+ return reinterpret_cast<StorageT*>(p + offset);
+}
+
+void* FlagImpl::AlignedBufferValue() const {
+ assert(ValueStorageKind() == FlagValueStorageKind::kAlignedBuffer);
+ return OffsetValue<void>();
+}
+
+std::atomic<uint64_t>* FlagImpl::AtomicBufferValue() const {
+ assert(ValueStorageKind() == FlagValueStorageKind::kSequenceLocked);
+ return OffsetValue<std::atomic<uint64_t>>();
+}
+
+std::atomic<int64_t>& FlagImpl::OneWordValue() const {
+ assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic ||
+ ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);
+ return OffsetValue<FlagOneWordValue>()->value;
+}
+
+// Attempts to parse supplied `value` string using parsing routine in the `flag`
+// argument. If parsing successful, this function replaces the dst with newly
+// parsed value. In case if any error is encountered in either step, the error
+// message is stored in 'err'
+std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse(
+ y_absl::string_view value, TString& err) const {
+ std::unique_ptr<void, DynValueDeleter> tentative_value = MakeInitValue();
+
+ TString parse_err;
+ if (!flags_internal::Parse(op_, value, tentative_value.get(), &parse_err)) {
+ y_absl::string_view err_sep = parse_err.empty() ? "" : "; ";
+ err = y_absl::StrCat("Illegal value '", value, "' specified for flag '",
+ Name(), "'", err_sep, parse_err);
+ return nullptr;
+ }
+
+ return tentative_value;
+}
+
+void FlagImpl::Read(void* dst) const {
+ auto* guard = DataGuard(); // Make sure flag initialized
+ switch (ValueStorageKind()) {
+ case FlagValueStorageKind::kValueAndInitBit:
+ case FlagValueStorageKind::kOneWordAtomic: {
+ const int64_t one_word_val =
+ OneWordValue().load(std::memory_order_acquire);
+ std::memcpy(dst, &one_word_val, Sizeof(op_));
+ break;
+ }
+ case FlagValueStorageKind::kSequenceLocked: {
+ ReadSequenceLockedData(dst);
+ break;
+ }
+ case FlagValueStorageKind::kAlignedBuffer: {
+ y_absl::MutexLock l(guard);
+ flags_internal::CopyConstruct(op_, AlignedBufferValue(), dst);
+ break;
+ }
+ }
+}
+
+int64_t FlagImpl::ReadOneWord() const {
+ assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic ||
+ ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);
+ auto* guard = DataGuard(); // Make sure flag initialized
+ (void)guard;
+ return OneWordValue().load(std::memory_order_acquire);
+}
+
+bool FlagImpl::ReadOneBool() const {
+ assert(ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);
+ auto* guard = DataGuard(); // Make sure flag initialized
+ (void)guard;
+ return y_absl::bit_cast<FlagValueAndInitBit<bool>>(
+ OneWordValue().load(std::memory_order_acquire))
+ .value;
+}
+
+void FlagImpl::ReadSequenceLockedData(void* dst) const {
+ size_t size = Sizeof(op_);
+ // Attempt to read using the sequence lock.
+ if (Y_ABSL_PREDICT_TRUE(seq_lock_.TryRead(dst, AtomicBufferValue(), size))) {
+ return;
+ }
+ // We failed due to contention. Acquire the lock to prevent contention
+ // and try again.
+ y_absl::ReaderMutexLock l(DataGuard());
+ bool success = seq_lock_.TryRead(dst, AtomicBufferValue(), size);
+ assert(success);
+ static_cast<void>(success);
+}
+
+void FlagImpl::Write(const void* src) {
+ y_absl::MutexLock l(DataGuard());
+
+ if (ShouldValidateFlagValue(flags_internal::FastTypeId(op_))) {
+ std::unique_ptr<void, DynValueDeleter> obj{flags_internal::Clone(op_, src),
+ DynValueDeleter{op_}};
+ TString ignored_error;
+ TString src_as_str = flags_internal::Unparse(op_, src);
+ if (!flags_internal::Parse(op_, src_as_str, obj.get(), &ignored_error)) {
+ Y_ABSL_INTERNAL_LOG(ERROR, y_absl::StrCat("Attempt to set flag '", Name(),
+ "' to invalid value ", src_as_str));
+ }
+ }
+
+ StoreValue(src);
+}
+
+// Sets the value of the flag based on specified string `value`. If the flag
+// was successfully set to new value, it returns true. Otherwise, sets `err`
+// to indicate the error, leaves the flag unchanged, and returns false. There
+// are three ways to set the flag's value:
+// * Update the current flag value
+// * Update the flag's default value
+// * Update the current flag value if it was never set before
+// The mode is selected based on 'set_mode' parameter.
+bool FlagImpl::ParseFrom(y_absl::string_view value, FlagSettingMode set_mode,
+ ValueSource source, TString& err) {
+ y_absl::MutexLock l(DataGuard());
+
+ switch (set_mode) {
+ case SET_FLAGS_VALUE: {
+ // set or modify the flag's value
+ auto tentative_value = TryParse(value, err);
+ if (!tentative_value) return false;
+
+ StoreValue(tentative_value.get());
+
+ if (source == kCommandLine) {
+ on_command_line_ = true;
+ }
+ break;
+ }
+ case SET_FLAG_IF_DEFAULT: {
+ // set the flag's value, but only if it hasn't been set by someone else
+ if (modified_) {
+ // TODO(rogeeff): review and fix this semantic. Currently we do not fail
+ // in this case if flag is modified. This is misleading since the flag's
+ // value is not updated even though we return true.
+ // *err = y_absl::StrCat(Name(), " is already set to ",
+ // CurrentValue(), "\n");
+ // return false;
+ return true;
+ }
+ auto tentative_value = TryParse(value, err);
+ if (!tentative_value) return false;
+
+ StoreValue(tentative_value.get());
+ break;
+ }
+ case SET_FLAGS_DEFAULT: {
+ auto tentative_value = TryParse(value, err);
+ if (!tentative_value) return false;
+
+ if (DefaultKind() == FlagDefaultKind::kDynamicValue) {
+ void* old_value = default_value_.dynamic_value;
+ default_value_.dynamic_value = tentative_value.release();
+ tentative_value.reset(old_value);
+ } else {
+ default_value_.dynamic_value = tentative_value.release();
+ def_kind_ = static_cast<uint8_t>(FlagDefaultKind::kDynamicValue);
+ }
+
+ if (!modified_) {
+ // Need to set both default value *and* current, in this case.
+ StoreValue(default_value_.dynamic_value);
+ modified_ = false;
+ }
+ break;
+ }
+ }
+
+ return true;
+}
+
+void FlagImpl::CheckDefaultValueParsingRoundtrip() const {
+ TString v = DefaultValue();
+
+ y_absl::MutexLock lock(DataGuard());
+
+ auto dst = MakeInitValue();
+ TString error;
+ if (!flags_internal::Parse(op_, v, dst.get(), &error)) {
+ Y_ABSL_INTERNAL_LOG(
+ FATAL,
+ y_absl::StrCat("Flag ", Name(), " (from ", Filename(),
+ "): string form of default value '", v,
+ "' could not be parsed; error=", error));
+ }
+
+ // We do not compare dst to def since parsing/unparsing may make
+ // small changes, e.g., precision loss for floating point types.
+}
+
+bool FlagImpl::ValidateInputValue(y_absl::string_view value) const {
+ y_absl::MutexLock l(DataGuard());
+
+ auto obj = MakeInitValue();
+ TString ignored_error;
+ return flags_internal::Parse(op_, value, obj.get(), &ignored_error);
+}
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag.h
new file mode 100644
index 0000000000..bce5e32656
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag.h
@@ -0,0 +1,800 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef Y_ABSL_FLAGS_INTERNAL_FLAG_H_
+#define Y_ABSL_FLAGS_INTERNAL_FLAG_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+#include <cstring>
+#include <memory>
+#include <new>
+#include <util/generic/string.h>
+#include <type_traits>
+#include <typeinfo>
+
+#include "y_absl/base/attributes.h"
+#include "y_absl/base/call_once.h"
+#include "y_absl/base/casts.h"
+#include "y_absl/base/config.h"
+#include "y_absl/base/optimization.h"
+#include "y_absl/base/thread_annotations.h"
+#include "y_absl/flags/commandlineflag.h"
+#include "y_absl/flags/config.h"
+#include "y_absl/flags/internal/commandlineflag.h"
+#include "y_absl/flags/internal/registry.h"
+#include "y_absl/flags/internal/sequence_lock.h"
+#include "y_absl/flags/marshalling.h"
+#include "y_absl/meta/type_traits.h"
+#include "y_absl/strings/string_view.h"
+#include "y_absl/synchronization/mutex.h"
+#include "y_absl/utility/utility.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Forward declaration of y_absl::Flag<T> public API.
+namespace flags_internal {
+template <typename T>
+class Flag;
+} // namespace flags_internal
+
+#if defined(_MSC_VER) && !defined(__clang__)
+template <typename T>
+class Flag;
+#else
+template <typename T>
+using Flag = flags_internal::Flag<T>;
+#endif
+
+template <typename T>
+Y_ABSL_MUST_USE_RESULT T GetFlag(const y_absl::Flag<T>& flag);
+
+template <typename T>
+void SetFlag(y_absl::Flag<T>* flag, const T& v);
+
+template <typename T, typename V>
+void SetFlag(y_absl::Flag<T>* flag, const V& v);
+
+template <typename U>
+const CommandLineFlag& GetFlagReflectionHandle(const y_absl::Flag<U>& f);
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag value type operations, eg., parsing, copying, etc. are provided
+// by function specific to that type with a signature matching FlagOpFn.
+
+namespace flags_internal {
+
+enum class FlagOp {
+ kAlloc,
+ kDelete,
+ kCopy,
+ kCopyConstruct,
+ kSizeof,
+ kFastTypeId,
+ kRuntimeTypeId,
+ kParse,
+ kUnparse,
+ kValueOffset,
+};
+using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*);
+
+// Forward declaration for Flag value specific operations.
+template <typename T>
+void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3);
+
+// Allocate aligned memory for a flag value.
+inline void* Alloc(FlagOpFn op) {
+ return op(FlagOp::kAlloc, nullptr, nullptr, nullptr);
+}
+// Deletes memory interpreting obj as flag value type pointer.
+inline void Delete(FlagOpFn op, void* obj) {
+ op(FlagOp::kDelete, nullptr, obj, nullptr);
+}
+// Copies src to dst interpreting as flag value type pointers.
+inline void Copy(FlagOpFn op, const void* src, void* dst) {
+ op(FlagOp::kCopy, src, dst, nullptr);
+}
+// Construct a copy of flag value in a location pointed by dst
+// based on src - pointer to the flag's value.
+inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
+ op(FlagOp::kCopyConstruct, src, dst, nullptr);
+}
+// Makes a copy of flag value pointed by obj.
+inline void* Clone(FlagOpFn op, const void* obj) {
+ void* res = flags_internal::Alloc(op);
+ flags_internal::CopyConstruct(op, obj, res);
+ return res;
+}
+// Returns true if parsing of input text is successfull.
+inline bool Parse(FlagOpFn op, y_absl::string_view text, void* dst,
+ TString* error) {
+ return op(FlagOp::kParse, &text, dst, error) != nullptr;
+}
+// Returns string representing supplied value.
+inline TString Unparse(FlagOpFn op, const void* val) {
+ TString result;
+ op(FlagOp::kUnparse, val, &result, nullptr);
+ return result;
+}
+// Returns size of flag value type.
+inline size_t Sizeof(FlagOpFn op) {
+ // This sequence of casts reverses the sequence from
+ // `flags_internal::FlagOps()`
+ return static_cast<size_t>(reinterpret_cast<intptr_t>(
+ op(FlagOp::kSizeof, nullptr, nullptr, nullptr)));
+}
+// Returns fast type id coresponding to the value type.
+inline FlagFastTypeId FastTypeId(FlagOpFn op) {
+ return reinterpret_cast<FlagFastTypeId>(
+ op(FlagOp::kFastTypeId, nullptr, nullptr, nullptr));
+}
+// Returns fast type id coresponding to the value type.
+inline const std::type_info* RuntimeTypeId(FlagOpFn op) {
+ return reinterpret_cast<const std::type_info*>(
+ op(FlagOp::kRuntimeTypeId, nullptr, nullptr, nullptr));
+}
+// Returns offset of the field value_ from the field impl_ inside of
+// y_absl::Flag<T> data. Given FlagImpl pointer p you can get the
+// location of the corresponding value as:
+// reinterpret_cast<char*>(p) + ValueOffset().
+inline ptrdiff_t ValueOffset(FlagOpFn op) {
+ // This sequence of casts reverses the sequence from
+ // `flags_internal::FlagOps()`
+ return static_cast<ptrdiff_t>(reinterpret_cast<intptr_t>(
+ op(FlagOp::kValueOffset, nullptr, nullptr, nullptr)));
+}
+
+// Returns an address of RTTI's typeid(T).
+template <typename T>
+inline const std::type_info* GenRuntimeTypeId() {
+#ifdef Y_ABSL_INTERNAL_HAS_RTTI
+ return &typeid(T);
+#else
+ return nullptr;
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag help auxiliary structs.
+
+// This is help argument for y_absl::Flag encapsulating the string literal pointer
+// or pointer to function generating it as well as enum descriminating two
+// cases.
+using HelpGenFunc = TString (*)();
+
+template <size_t N>
+struct FixedCharArray {
+ char value[N];
+
+ template <size_t... I>
+ static constexpr FixedCharArray<N> FromLiteralString(
+ y_absl::string_view str, y_absl::index_sequence<I...>) {
+ return (void)str, FixedCharArray<N>({{str[I]..., '\0'}});
+ }
+};
+
+template <typename Gen, size_t N = Gen::Value().size()>
+constexpr FixedCharArray<N + 1> HelpStringAsArray(int) {
+ return FixedCharArray<N + 1>::FromLiteralString(
+ Gen::Value(), y_absl::make_index_sequence<N>{});
+}
+
+template <typename Gen>
+constexpr std::false_type HelpStringAsArray(char) {
+ return std::false_type{};
+}
+
+union FlagHelpMsg {
+ constexpr explicit FlagHelpMsg(const char* help_msg) : literal(help_msg) {}
+ constexpr explicit FlagHelpMsg(HelpGenFunc help_gen) : gen_func(help_gen) {}
+
+ const char* literal;
+ HelpGenFunc gen_func;
+};
+
+enum class FlagHelpKind : uint8_t { kLiteral = 0, kGenFunc = 1 };
+
+struct FlagHelpArg {
+ FlagHelpMsg source;
+ FlagHelpKind kind;
+};
+
+extern const char kStrippedFlagHelp[];
+
+// These two HelpArg overloads allows us to select at compile time one of two
+// way to pass Help argument to y_absl::Flag. We'll be passing
+// AbslFlagHelpGenFor##name as Gen and integer 0 as a single argument to prefer
+// first overload if possible. If help message is evaluatable on constexpr
+// context We'll be able to make FixedCharArray out of it and we'll choose first
+// overload. In this case the help message expression is immediately evaluated
+// and is used to construct the y_absl::Flag. No additionl code is generated by
+// Y_ABSL_FLAG Otherwise SFINAE kicks in and first overload is dropped from the
+// consideration, in which case the second overload will be used. The second
+// overload does not attempt to evaluate the help message expression
+// immediately and instead delays the evaluation by returing the function
+// pointer (&T::NonConst) genering the help message when necessary. This is
+// evaluatable in constexpr context, but the cost is an extra function being
+// generated in the Y_ABSL_FLAG code.
+template <typename Gen, size_t N>
+constexpr FlagHelpArg HelpArg(const FixedCharArray<N>& value) {
+ return {FlagHelpMsg(value.value), FlagHelpKind::kLiteral};
+}
+
+template <typename Gen>
+constexpr FlagHelpArg HelpArg(std::false_type) {
+ return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc};
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag default value auxiliary structs.
+
+// Signature for the function generating the initial flag value (usually
+// based on default value supplied in flag's definition)
+using FlagDfltGenFunc = void (*)(void*);
+
+union FlagDefaultSrc {
+ constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg)
+ : gen_func(gen_func_arg) {}
+
+#define Y_ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE(T, name) \
+ T name##_value; \
+ constexpr explicit FlagDefaultSrc(T value) : name##_value(value) {} // NOLINT
+ Y_ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(Y_ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE)
+#undef Y_ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE
+
+ void* dynamic_value;
+ FlagDfltGenFunc gen_func;
+};
+
+enum class FlagDefaultKind : uint8_t {
+ kDynamicValue = 0,
+ kGenFunc = 1,
+ kOneWord = 2 // for default values UP to one word in size
+};
+
+struct FlagDefaultArg {
+ FlagDefaultSrc source;
+ FlagDefaultKind kind;
+};
+
+// This struct and corresponding overload to InitDefaultValue are used to
+// facilitate usage of {} as default value in Y_ABSL_FLAG macro.
+// TODO(rogeeff): Fix handling types with explicit constructors.
+struct EmptyBraces {};
+
+template <typename T>
+constexpr T InitDefaultValue(T t) {
+ return t;
+}
+
+template <typename T>
+constexpr T InitDefaultValue(EmptyBraces) {
+ return T{};
+}
+
+template <typename ValueT, typename GenT,
+ typename std::enable_if<std::is_integral<ValueT>::value, int>::type =
+ ((void)GenT{}, 0)>
+constexpr FlagDefaultArg DefaultArg(int) {
+ return {FlagDefaultSrc(GenT{}.value), FlagDefaultKind::kOneWord};
+}
+
+template <typename ValueT, typename GenT>
+constexpr FlagDefaultArg DefaultArg(char) {
+ return {FlagDefaultSrc(&GenT::Gen), FlagDefaultKind::kGenFunc};
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag current value auxiliary structs.
+
+constexpr int64_t UninitializedFlagValue() {
+ return static_cast<int64_t>(0xababababababababll);
+}
+
+template <typename T>
+using FlagUseValueAndInitBitStorage = std::integral_constant<
+ bool, y_absl::type_traits_internal::is_trivially_copyable<T>::value &&
+ std::is_default_constructible<T>::value && (sizeof(T) < 8)>;
+
+template <typename T>
+using FlagUseOneWordStorage = std::integral_constant<
+ bool, y_absl::type_traits_internal::is_trivially_copyable<T>::value &&
+ (sizeof(T) <= 8)>;
+
+template <class T>
+using FlagUseSequenceLockStorage = std::integral_constant<
+ bool, y_absl::type_traits_internal::is_trivially_copyable<T>::value &&
+ (sizeof(T) > 8)>;
+
+enum class FlagValueStorageKind : uint8_t {
+ kValueAndInitBit = 0,
+ kOneWordAtomic = 1,
+ kSequenceLocked = 2,
+ kAlignedBuffer = 3,
+};
+
+template <typename T>
+static constexpr FlagValueStorageKind StorageKind() {
+ return FlagUseValueAndInitBitStorage<T>::value
+ ? FlagValueStorageKind::kValueAndInitBit
+ : FlagUseOneWordStorage<T>::value
+ ? FlagValueStorageKind::kOneWordAtomic
+ : FlagUseSequenceLockStorage<T>::value
+ ? FlagValueStorageKind::kSequenceLocked
+ : FlagValueStorageKind::kAlignedBuffer;
+}
+
+struct FlagOneWordValue {
+ constexpr explicit FlagOneWordValue(int64_t v) : value(v) {}
+ std::atomic<int64_t> value;
+};
+
+template <typename T>
+struct alignas(8) FlagValueAndInitBit {
+ T value;
+ // Use an int instead of a bool to guarantee that a non-zero value has
+ // a bit set.
+ uint8_t init;
+};
+
+template <typename T,
+ FlagValueStorageKind Kind = flags_internal::StorageKind<T>()>
+struct FlagValue;
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kValueAndInitBit> : FlagOneWordValue {
+ constexpr FlagValue() : FlagOneWordValue(0) {}
+ bool Get(const SequenceLock&, T& dst) const {
+ int64_t storage = value.load(std::memory_order_acquire);
+ if (Y_ABSL_PREDICT_FALSE(storage == 0)) {
+ return false;
+ }
+ dst = y_absl::bit_cast<FlagValueAndInitBit<T>>(storage).value;
+ return true;
+ }
+};
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue {
+ constexpr FlagValue() : FlagOneWordValue(UninitializedFlagValue()) {}
+ bool Get(const SequenceLock&, T& dst) const {
+ int64_t one_word_val = value.load(std::memory_order_acquire);
+ if (Y_ABSL_PREDICT_FALSE(one_word_val == UninitializedFlagValue())) {
+ return false;
+ }
+ std::memcpy(&dst, static_cast<const void*>(&one_word_val), sizeof(T));
+ return true;
+ }
+};
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kSequenceLocked> {
+ bool Get(const SequenceLock& lock, T& dst) const {
+ return lock.TryRead(&dst, value_words, sizeof(T));
+ }
+
+ static constexpr int kNumWords =
+ flags_internal::AlignUp(sizeof(T), sizeof(uint64_t)) / sizeof(uint64_t);
+
+ alignas(T) alignas(
+ std::atomic<uint64_t>) std::atomic<uint64_t> value_words[kNumWords];
+};
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> {
+ bool Get(const SequenceLock&, T&) const { return false; }
+
+ alignas(T) char value[sizeof(T)];
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag callback auxiliary structs.
+
+// Signature for the mutation callback used by watched Flags
+// The callback is noexcept.
+// TODO(rogeeff): add noexcept after C++17 support is added.
+using FlagCallbackFunc = void (*)();
+
+struct FlagCallback {
+ FlagCallbackFunc func;
+ y_absl::Mutex guard; // Guard for concurrent callback invocations.
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag implementation, which does not depend on flag value type.
+// The class encapsulates the Flag's data and access to it.
+
+struct DynValueDeleter {
+ explicit DynValueDeleter(FlagOpFn op_arg = nullptr);
+ void operator()(void* ptr) const;
+
+ FlagOpFn op;
+};
+
+class FlagState;
+
+class FlagImpl final : public CommandLineFlag {
+ public:
+ constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op,
+ FlagHelpArg help, FlagValueStorageKind value_kind,
+ FlagDefaultArg default_arg)
+ : name_(name),
+ filename_(filename),
+ op_(op),
+ help_(help.source),
+ help_source_kind_(static_cast<uint8_t>(help.kind)),
+ value_storage_kind_(static_cast<uint8_t>(value_kind)),
+ def_kind_(static_cast<uint8_t>(default_arg.kind)),
+ modified_(false),
+ on_command_line_(false),
+ callback_(nullptr),
+ default_value_(default_arg.source),
+ data_guard_{} {}
+
+ // Constant access methods
+ int64_t ReadOneWord() const Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+ bool ReadOneBool() const Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+ void Read(void* dst) const override Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+ void Read(bool* value) const Y_ABSL_LOCKS_EXCLUDED(*DataGuard()) {
+ *value = ReadOneBool();
+ }
+ template <typename T,
+ y_absl::enable_if_t<flags_internal::StorageKind<T>() ==
+ FlagValueStorageKind::kOneWordAtomic,
+ int> = 0>
+ void Read(T* value) const Y_ABSL_LOCKS_EXCLUDED(*DataGuard()) {
+ int64_t v = ReadOneWord();
+ std::memcpy(value, static_cast<const void*>(&v), sizeof(T));
+ }
+ template <typename T,
+ typename std::enable_if<flags_internal::StorageKind<T>() ==
+ FlagValueStorageKind::kValueAndInitBit,
+ int>::type = 0>
+ void Read(T* value) const Y_ABSL_LOCKS_EXCLUDED(*DataGuard()) {
+ *value = y_absl::bit_cast<FlagValueAndInitBit<T>>(ReadOneWord()).value;
+ }
+
+ // Mutating access methods
+ void Write(const void* src) Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ // Interfaces to operate on callbacks.
+ void SetCallback(const FlagCallbackFunc mutation_callback)
+ Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+ void InvokeCallback() const Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
+ // Used in read/write operations to validate source/target has correct type.
+ // For example if flag is declared as y_absl::Flag<int> FLAGS_foo, a call to
+ // y_absl::GetFlag(FLAGS_foo) validates that the type of FLAGS_foo is indeed
+ // int. To do that we pass the "assumed" type id (which is deduced from type
+ // int) as an argument `type_id`, which is in turn is validated against the
+ // type id stored in flag object by flag definition statement.
+ void AssertValidType(FlagFastTypeId type_id,
+ const std::type_info* (*gen_rtti)()) const;
+
+ private:
+ template <typename T>
+ friend class Flag;
+ friend class FlagState;
+
+ // Ensures that `data_guard_` is initialized and returns it.
+ y_absl::Mutex* DataGuard() const
+ Y_ABSL_LOCK_RETURNED(reinterpret_cast<y_absl::Mutex*>(data_guard_));
+ // Returns heap allocated value of type T initialized with default value.
+ std::unique_ptr<void, DynValueDeleter> MakeInitValue() const
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+ // Flag initialization called via y_absl::call_once.
+ void Init();
+
+ // Offset value access methods. One per storage kind. These methods to not
+ // respect const correctness, so be very carefull using them.
+
+ // This is a shared helper routine which encapsulates most of the magic. Since
+ // it is only used inside the three routines below, which are defined in
+ // flag.cc, we can define it in that file as well.
+ template <typename StorageT>
+ StorageT* OffsetValue() const;
+ // This is an accessor for a value stored in an aligned buffer storage
+ // used for non-trivially-copyable data types.
+ // Returns a mutable pointer to the start of a buffer.
+ void* AlignedBufferValue() const;
+
+ // The same as above, but used for sequencelock-protected storage.
+ std::atomic<uint64_t>* AtomicBufferValue() const;
+
+ // This is an accessor for a value stored as one word atomic. Returns a
+ // mutable reference to an atomic value.
+ std::atomic<int64_t>& OneWordValue() const;
+
+ // Attempts to parse supplied `value` string. If parsing is successful,
+ // returns new value. Otherwise returns nullptr.
+ std::unique_ptr<void, DynValueDeleter> TryParse(y_absl::string_view value,
+ TString& err) const
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+ // Stores the flag value based on the pointer to the source.
+ void StoreValue(const void* src) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
+ // Copy the flag data, protected by `seq_lock_` into `dst`.
+ //
+ // REQUIRES: ValueStorageKind() == kSequenceLocked.
+ void ReadSequenceLockedData(void* dst) const
+ Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ FlagHelpKind HelpSourceKind() const {
+ return static_cast<FlagHelpKind>(help_source_kind_);
+ }
+ FlagValueStorageKind ValueStorageKind() const {
+ return static_cast<FlagValueStorageKind>(value_storage_kind_);
+ }
+ FlagDefaultKind DefaultKind() const
+ Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()) {
+ return static_cast<FlagDefaultKind>(def_kind_);
+ }
+
+ // CommandLineFlag interface implementation
+ y_absl::string_view Name() const override;
+ TString Filename() const override;
+ TString Help() const override;
+ FlagFastTypeId TypeId() const override;
+ bool IsSpecifiedOnCommandLine() const override
+ Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+ TString DefaultValue() const override Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+ TString CurrentValue() const override Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+ bool ValidateInputValue(y_absl::string_view value) const override
+ Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+ void CheckDefaultValueParsingRoundtrip() const override
+ Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ int64_t ModificationCount() const Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
+ // Interfaces to save and restore flags to/from persistent state.
+ // Returns current flag state or nullptr if flag does not support
+ // saving and restoring a state.
+ std::unique_ptr<FlagStateInterface> SaveState() override
+ Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ // Restores the flag state to the supplied state object. If there is
+ // nothing to restore returns false. Otherwise returns true.
+ bool RestoreState(const FlagState& flag_state)
+ Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ bool ParseFrom(y_absl::string_view value, FlagSettingMode set_mode,
+ ValueSource source, TString& error) override
+ Y_ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ // Immutable flag's state.
+
+ // Flags name passed to Y_ABSL_FLAG as second arg.
+ const char* const name_;
+ // The file name where Y_ABSL_FLAG resides.
+ const char* const filename_;
+ // Type-specific operations "vtable".
+ const FlagOpFn op_;
+ // Help message literal or function to generate it.
+ const FlagHelpMsg help_;
+ // Indicates if help message was supplied as literal or generator func.
+ const uint8_t help_source_kind_ : 1;
+ // Kind of storage this flag is using for the flag's value.
+ const uint8_t value_storage_kind_ : 2;
+
+ uint8_t : 0; // The bytes containing the const bitfields must not be
+ // shared with bytes containing the mutable bitfields.
+
+ // Mutable flag's state (guarded by `data_guard_`).
+
+ // def_kind_ is not guard by DataGuard() since it is accessed in Init without
+ // locks.
+ uint8_t def_kind_ : 2;
+ // Has this flag's value been modified?
+ bool modified_ : 1 Y_ABSL_GUARDED_BY(*DataGuard());
+ // Has this flag been specified on command line.
+ bool on_command_line_ : 1 Y_ABSL_GUARDED_BY(*DataGuard());
+
+ // Unique tag for y_absl::call_once call to initialize this flag.
+ y_absl::once_flag init_control_;
+
+ // Sequence lock / mutation counter.
+ flags_internal::SequenceLock seq_lock_;
+
+ // Optional flag's callback and y_absl::Mutex to guard the invocations.
+ FlagCallback* callback_ Y_ABSL_GUARDED_BY(*DataGuard());
+ // Either a pointer to the function generating the default value based on the
+ // value specified in Y_ABSL_FLAG or pointer to the dynamically set default
+ // value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish
+ // these two cases.
+ FlagDefaultSrc default_value_;
+
+ // This is reserved space for an y_absl::Mutex to guard flag data. It will be
+ // initialized in FlagImpl::Init via placement new.
+ // We can't use "y_absl::Mutex data_guard_", since this class is not literal.
+ // We do not want to use "y_absl::Mutex* data_guard_", since this would require
+ // heap allocation during initialization, which is both slows program startup
+ // and can fail. Using reserved space + placement new allows us to avoid both
+ // problems.
+ alignas(y_absl::Mutex) mutable char data_guard_[sizeof(y_absl::Mutex)];
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// The Flag object parameterized by the flag's value type. This class implements
+// flag reflection handle interface.
+
+template <typename T>
+class Flag {
+ public:
+ constexpr Flag(const char* name, const char* filename, FlagHelpArg help,
+ const FlagDefaultArg default_arg)
+ : impl_(name, filename, &FlagOps<T>, help,
+ flags_internal::StorageKind<T>(), default_arg),
+ value_() {}
+
+ // CommandLineFlag interface
+ y_absl::string_view Name() const { return impl_.Name(); }
+ TString Filename() const { return impl_.Filename(); }
+ TString Help() const { return impl_.Help(); }
+ // Do not use. To be removed.
+ bool IsSpecifiedOnCommandLine() const {
+ return impl_.IsSpecifiedOnCommandLine();
+ }
+ TString DefaultValue() const { return impl_.DefaultValue(); }
+ TString CurrentValue() const { return impl_.CurrentValue(); }
+
+ private:
+ template <typename, bool>
+ friend class FlagRegistrar;
+ friend class FlagImplPeer;
+
+ T Get() const {
+ // See implementation notes in CommandLineFlag::Get().
+ union U {
+ T value;
+ U() {}
+ ~U() { value.~T(); }
+ };
+ U u;
+
+#if !defined(NDEBUG)
+ impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
+#endif
+
+ if (Y_ABSL_PREDICT_FALSE(!value_.Get(impl_.seq_lock_, u.value))) {
+ impl_.Read(&u.value);
+ }
+ return std::move(u.value);
+ }
+ void Set(const T& v) {
+ impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
+ impl_.Write(&v);
+ }
+
+ // Access to the reflection.
+ const CommandLineFlag& Reflect() const { return impl_; }
+
+ // Flag's data
+ // The implementation depends on value_ field to be placed exactly after the
+ // impl_ field, so that impl_ can figure out the offset to the value and
+ // access it.
+ FlagImpl impl_;
+ FlagValue<T> value_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Trampoline for friend access
+
+class FlagImplPeer {
+ public:
+ template <typename T, typename FlagType>
+ static T InvokeGet(const FlagType& flag) {
+ return flag.Get();
+ }
+ template <typename FlagType, typename T>
+ static void InvokeSet(FlagType& flag, const T& v) {
+ flag.Set(v);
+ }
+ template <typename FlagType>
+ static const CommandLineFlag& InvokeReflect(const FlagType& f) {
+ return f.Reflect();
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Implementation of Flag value specific operations routine.
+template <typename T>
+void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
+ switch (op) {
+ case FlagOp::kAlloc: {
+ std::allocator<T> alloc;
+ return std::allocator_traits<std::allocator<T>>::allocate(alloc, 1);
+ }
+ case FlagOp::kDelete: {
+ T* p = static_cast<T*>(v2);
+ p->~T();
+ std::allocator<T> alloc;
+ std::allocator_traits<std::allocator<T>>::deallocate(alloc, p, 1);
+ return nullptr;
+ }
+ case FlagOp::kCopy:
+ *static_cast<T*>(v2) = *static_cast<const T*>(v1);
+ return nullptr;
+ case FlagOp::kCopyConstruct:
+ new (v2) T(*static_cast<const T*>(v1));
+ return nullptr;
+ case FlagOp::kSizeof:
+ return reinterpret_cast<void*>(static_cast<uintptr_t>(sizeof(T)));
+ case FlagOp::kFastTypeId:
+ return const_cast<void*>(base_internal::FastTypeId<T>());
+ case FlagOp::kRuntimeTypeId:
+ return const_cast<std::type_info*>(GenRuntimeTypeId<T>());
+ case FlagOp::kParse: {
+ // Initialize the temporary instance of type T based on current value in
+ // destination (which is going to be flag's default value).
+ T temp(*static_cast<T*>(v2));
+ if (!y_absl::ParseFlag<T>(*static_cast<const y_absl::string_view*>(v1), &temp,
+ static_cast<TString*>(v3))) {
+ return nullptr;
+ }
+ *static_cast<T*>(v2) = std::move(temp);
+ return v2;
+ }
+ case FlagOp::kUnparse:
+ *static_cast<TString*>(v2) =
+ y_absl::UnparseFlag<T>(*static_cast<const T*>(v1));
+ return nullptr;
+ case FlagOp::kValueOffset: {
+ // Round sizeof(FlagImp) to a multiple of alignof(FlagValue<T>) to get the
+ // offset of the data.
+ size_t round_to = alignof(FlagValue<T>);
+ size_t offset =
+ (sizeof(FlagImpl) + round_to - 1) / round_to * round_to;
+ return reinterpret_cast<void*>(offset);
+ }
+ }
+ return nullptr;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// This class facilitates Flag object registration and tail expression-based
+// flag definition, for example:
+// Y_ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher);
+struct FlagRegistrarEmpty {};
+template <typename T, bool do_register>
+class FlagRegistrar {
+ public:
+ explicit FlagRegistrar(Flag<T>& flag, const char* filename) : flag_(flag) {
+ if (do_register)
+ flags_internal::RegisterCommandLineFlag(flag_.impl_, filename);
+ }
+
+ FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {
+ flag_.impl_.SetCallback(cb);
+ return *this;
+ }
+
+ // Make the registrar "die" gracefully as an empty struct on a line where
+ // registration happens. Registrar objects are intended to live only as
+ // temporary.
+ operator FlagRegistrarEmpty() const { return {}; } // NOLINT
+
+ private:
+ Flag<T>& flag_; // Flag being registered (not owned).
+};
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_INTERNAL_FLAG_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag_msvc.inc b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag_msvc.inc
new file mode 100644
index 0000000000..f9beb09f90
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/flag_msvc.inc
@@ -0,0 +1,116 @@
+//
+// Copyright 2021 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Do not include this file directly.
+// Include y_absl/flags/flag.h instead.
+
+// MSVC debug builds do not implement initialization with constexpr constructors
+// correctly. To work around this we add a level of indirection, so that the
+// class `y_absl::Flag` contains an `internal::Flag*` (instead of being an alias
+// to that class) and dynamically allocates an instance when necessary. We also
+// forward all calls to internal::Flag methods via trampoline methods. In this
+// setup the `y_absl::Flag` class does not have constructor and virtual methods,
+// all the data members are public and thus MSVC is able to initialize it at
+// link time. To deal with multiple threads accessing the flag for the first
+// time concurrently we use an atomic boolean indicating if flag object is
+// initialized. We also employ the double-checked locking pattern where the
+// second level of protection is a global Mutex, so if two threads attempt to
+// construct the flag concurrently only one wins.
+//
+// This solution is based on a recomendation here:
+// https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html?childToView=648454#comment-648454
+
+namespace flags_internal {
+y_absl::Mutex* GetGlobalConstructionGuard();
+} // namespace flags_internal
+
+// Public methods of `y_absl::Flag<T>` are NOT part of the Abseil Flags API.
+// See https://abseil.io/docs/cpp/guides/flags
+template <typename T>
+class Flag {
+ public:
+ // No constructor and destructor to ensure this is an aggregate type.
+ // Visual Studio 2015 still requires the constructor for class to be
+ // constexpr initializable.
+#if _MSC_VER <= 1900
+ constexpr Flag(const char* name, const char* filename,
+ const flags_internal::HelpGenFunc help_gen,
+ const flags_internal::FlagDfltGenFunc default_value_gen)
+ : name_(name),
+ filename_(filename),
+ help_gen_(help_gen),
+ default_value_gen_(default_value_gen),
+ inited_(false),
+ impl_(nullptr) {}
+#endif
+
+ flags_internal::Flag<T>& GetImpl() const {
+ if (!inited_.load(std::memory_order_acquire)) {
+ y_absl::MutexLock l(flags_internal::GetGlobalConstructionGuard());
+
+ if (inited_.load(std::memory_order_acquire)) {
+ return *impl_;
+ }
+
+ impl_ = new flags_internal::Flag<T>(
+ name_, filename_,
+ {flags_internal::FlagHelpMsg(help_gen_),
+ flags_internal::FlagHelpKind::kGenFunc},
+ {flags_internal::FlagDefaultSrc(default_value_gen_),
+ flags_internal::FlagDefaultKind::kGenFunc});
+ inited_.store(true, std::memory_order_release);
+ }
+
+ return *impl_;
+ }
+
+ // Public methods of `y_absl::Flag<T>` are NOT part of the Abseil Flags API.
+ // See https://abseil.io/docs/cpp/guides/flags
+ bool IsRetired() const { return GetImpl().IsRetired(); }
+ y_absl::string_view Name() const { return GetImpl().Name(); }
+ TString Help() const { return GetImpl().Help(); }
+ bool IsModified() const { return GetImpl().IsModified(); }
+ bool IsSpecifiedOnCommandLine() const {
+ return GetImpl().IsSpecifiedOnCommandLine();
+ }
+ TString Filename() const { return GetImpl().Filename(); }
+ TString DefaultValue() const { return GetImpl().DefaultValue(); }
+ TString CurrentValue() const { return GetImpl().CurrentValue(); }
+ template <typename U>
+ inline bool IsOfType() const {
+ return GetImpl().template IsOfType<U>();
+ }
+ T Get() const {
+ return flags_internal::FlagImplPeer::InvokeGet<T>(GetImpl());
+ }
+ void Set(const T& v) {
+ flags_internal::FlagImplPeer::InvokeSet(GetImpl(), v);
+ }
+ void InvokeCallback() { GetImpl().InvokeCallback(); }
+
+ const CommandLineFlag& Reflect() const {
+ return flags_internal::FlagImplPeer::InvokeReflect(GetImpl());
+ }
+
+ // The data members are logically private, but they need to be public for
+ // this to be an aggregate type.
+ const char* name_;
+ const char* filename_;
+ const flags_internal::HelpGenFunc help_gen_;
+ const flags_internal::FlagDfltGenFunc default_value_gen_;
+
+ mutable std::atomic<bool> inited_;
+ mutable flags_internal::Flag<T>* impl_;
+};
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/parse.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/parse.h
new file mode 100644
index 0000000000..9ef0f310af
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/parse.h
@@ -0,0 +1,63 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef Y_ABSL_FLAGS_INTERNAL_PARSE_H_
+#define Y_ABSL_FLAGS_INTERNAL_PARSE_H_
+
+#include <util/generic/string.h>
+#include <vector>
+
+#include "y_absl/base/config.h"
+#include "y_absl/flags/declare.h"
+#include "y_absl/strings/string_view.h"
+
+Y_ABSL_DECLARE_FLAG(std::vector<TString>, flagfile);
+Y_ABSL_DECLARE_FLAG(std::vector<TString>, fromenv);
+Y_ABSL_DECLARE_FLAG(std::vector<TString>, tryfromenv);
+Y_ABSL_DECLARE_FLAG(std::vector<TString>, undefok);
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+enum class ArgvListAction { kRemoveParsedArgs, kKeepParsedArgs };
+enum class UsageFlagsAction { kHandleUsage, kIgnoreUsage };
+enum class OnUndefinedFlag {
+ kIgnoreUndefined,
+ kReportUndefined,
+ kAbortIfUndefined
+};
+
+std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
+ ArgvListAction arg_list_act,
+ UsageFlagsAction usage_flag_act,
+ OnUndefinedFlag on_undef_flag);
+
+// --------------------------------------------------------------------
+// Inspect original command line
+
+// Returns true if flag with specified name was either present on the original
+// command line or specified in flag file present on the original command line.
+bool WasPresentOnCommandLine(y_absl::string_view flag_name);
+
+// Return existing flags similar to the parameter, in order to help in case of
+// misspellings.
+std::vector<TString> GetMisspellingHints(y_absl::string_view flag);
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_INTERNAL_PARSE_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/path_util.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/path_util.h
new file mode 100644
index 0000000000..7c382c87db
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/path_util.h
@@ -0,0 +1,62 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef Y_ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
+#define Y_ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
+
+#include "y_absl/base/config.h"
+#include "y_absl/strings/string_view.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// A portable interface that returns the basename of the filename passed as an
+// argument. It is similar to basename(3)
+// <https://linux.die.net/man/3/basename>.
+// For example:
+// flags_internal::Basename("a/b/prog/file.cc")
+// returns "file.cc"
+// flags_internal::Basename("file.cc")
+// returns "file.cc"
+inline y_absl::string_view Basename(y_absl::string_view filename) {
+ auto last_slash_pos = filename.find_last_of("/\\");
+
+ return last_slash_pos == y_absl::string_view::npos
+ ? filename
+ : filename.substr(last_slash_pos + 1);
+}
+
+// A portable interface that returns the directory name of the filename
+// passed as an argument, including the trailing slash.
+// Returns the empty string if a slash is not found in the input file name.
+// For example:
+// flags_internal::Package("a/b/prog/file.cc")
+// returns "a/b/prog/"
+// flags_internal::Package("file.cc")
+// returns ""
+inline y_absl::string_view Package(y_absl::string_view filename) {
+ auto last_slash_pos = filename.find_last_of("/\\");
+
+ return last_slash_pos == y_absl::string_view::npos
+ ? y_absl::string_view()
+ : filename.substr(0, last_slash_pos + 1);
+}
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/private_handle_accessor.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/private_handle_accessor.cc
new file mode 100644
index 0000000000..4bba3943dc
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/private_handle_accessor.cc
@@ -0,0 +1,65 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "y_absl/flags/internal/private_handle_accessor.h"
+
+#include <memory>
+#include <util/generic/string.h>
+
+#include "y_absl/base/config.h"
+#include "y_absl/flags/commandlineflag.h"
+#include "y_absl/flags/internal/commandlineflag.h"
+#include "y_absl/strings/string_view.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+FlagFastTypeId PrivateHandleAccessor::TypeId(const CommandLineFlag& flag) {
+ return flag.TypeId();
+}
+
+std::unique_ptr<FlagStateInterface> PrivateHandleAccessor::SaveState(
+ CommandLineFlag& flag) {
+ return flag.SaveState();
+}
+
+bool PrivateHandleAccessor::IsSpecifiedOnCommandLine(
+ const CommandLineFlag& flag) {
+ return flag.IsSpecifiedOnCommandLine();
+}
+
+bool PrivateHandleAccessor::ValidateInputValue(const CommandLineFlag& flag,
+ y_absl::string_view value) {
+ return flag.ValidateInputValue(value);
+}
+
+void PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
+ const CommandLineFlag& flag) {
+ flag.CheckDefaultValueParsingRoundtrip();
+}
+
+bool PrivateHandleAccessor::ParseFrom(CommandLineFlag& flag,
+ y_absl::string_view value,
+ flags_internal::FlagSettingMode set_mode,
+ flags_internal::ValueSource source,
+ TString& error) {
+ return flag.ParseFrom(value, set_mode, source, error);
+}
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/private_handle_accessor.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/private_handle_accessor.h
new file mode 100644
index 0000000000..889a09537f
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/private_handle_accessor.h
@@ -0,0 +1,61 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef Y_ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
+#define Y_ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
+
+#include <memory>
+#include <util/generic/string.h>
+
+#include "y_absl/base/config.h"
+#include "y_absl/flags/commandlineflag.h"
+#include "y_absl/flags/internal/commandlineflag.h"
+#include "y_absl/strings/string_view.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// This class serves as a trampoline to access private methods of
+// CommandLineFlag. This class is intended for use exclusively internally inside
+// of the Abseil Flags implementation.
+class PrivateHandleAccessor {
+ public:
+ // Access to CommandLineFlag::TypeId.
+ static FlagFastTypeId TypeId(const CommandLineFlag& flag);
+
+ // Access to CommandLineFlag::SaveState.
+ static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag& flag);
+
+ // Access to CommandLineFlag::IsSpecifiedOnCommandLine.
+ static bool IsSpecifiedOnCommandLine(const CommandLineFlag& flag);
+
+ // Access to CommandLineFlag::ValidateInputValue.
+ static bool ValidateInputValue(const CommandLineFlag& flag,
+ y_absl::string_view value);
+
+ // Access to CommandLineFlag::CheckDefaultValueParsingRoundtrip.
+ static void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag);
+
+ static bool ParseFrom(CommandLineFlag& flag, y_absl::string_view value,
+ flags_internal::FlagSettingMode set_mode,
+ flags_internal::ValueSource source, TString& error);
+};
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/program_name.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/program_name.cc
new file mode 100644
index 0000000000..7739f99089
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/program_name.cc
@@ -0,0 +1,60 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "y_absl/flags/internal/program_name.h"
+
+#include <util/generic/string.h>
+
+#include "y_absl/base/attributes.h"
+#include "y_absl/base/config.h"
+#include "y_absl/base/const_init.h"
+#include "y_absl/base/thread_annotations.h"
+#include "y_absl/flags/internal/path_util.h"
+#include "y_absl/strings/string_view.h"
+#include "y_absl/synchronization/mutex.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+Y_ABSL_CONST_INIT static y_absl::Mutex program_name_guard(y_absl::kConstInit);
+Y_ABSL_CONST_INIT static TString* program_name
+ Y_ABSL_GUARDED_BY(program_name_guard) = nullptr;
+
+TString ProgramInvocationName() {
+ y_absl::MutexLock l(&program_name_guard);
+
+ return program_name ? *program_name : "UNKNOWN";
+}
+
+TString ShortProgramInvocationName() {
+ y_absl::MutexLock l(&program_name_guard);
+
+ return program_name ? TString(flags_internal::Basename(*program_name))
+ : "UNKNOWN";
+}
+
+void SetProgramInvocationName(y_absl::string_view prog_name_str) {
+ y_absl::MutexLock l(&program_name_guard);
+
+ if (!program_name)
+ program_name = new TString(prog_name_str);
+ else
+ program_name->assign(prog_name_str.data(), prog_name_str.size());
+}
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/program_name.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/program_name.h
new file mode 100644
index 0000000000..817f93e094
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/program_name.h
@@ -0,0 +1,50 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef Y_ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_
+#define Y_ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_
+
+#include <util/generic/string.h>
+
+#include "y_absl/base/config.h"
+#include "y_absl/strings/string_view.h"
+
+// --------------------------------------------------------------------
+// Program name
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// Returns program invocation name or "UNKNOWN" if `SetProgramInvocationName()`
+// is never called. At the moment this is always set to argv[0] as part of
+// library initialization.
+TString ProgramInvocationName();
+
+// Returns base name for program invocation name. For example, if
+// ProgramInvocationName() == "a/b/mybinary"
+// then
+// ShortProgramInvocationName() == "mybinary"
+TString ShortProgramInvocationName();
+
+// Sets program invocation name to a new value. Should only be called once
+// during program initialization, before any threads are spawned.
+void SetProgramInvocationName(y_absl::string_view prog_name_str);
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/registry.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/registry.h
new file mode 100644
index 0000000000..cb3afdd890
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/registry.h
@@ -0,0 +1,97 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef Y_ABSL_FLAGS_INTERNAL_REGISTRY_H_
+#define Y_ABSL_FLAGS_INTERNAL_REGISTRY_H_
+
+#include <functional>
+
+#include "y_absl/base/config.h"
+#include "y_absl/flags/commandlineflag.h"
+#include "y_absl/flags/internal/commandlineflag.h"
+#include "y_absl/strings/string_view.h"
+
+// --------------------------------------------------------------------
+// Global flags registry API.
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// Executes specified visitor for each non-retired flag in the registry. While
+// callback are executed, the registry is locked and can't be changed.
+void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
+
+//-----------------------------------------------------------------------------
+
+bool RegisterCommandLineFlag(CommandLineFlag&, const char* filename);
+
+void FinalizeRegistry();
+
+//-----------------------------------------------------------------------------
+// Retired registrations:
+//
+// Retired flag registrations are treated specially. A 'retired' flag is
+// provided only for compatibility with automated invocations that still
+// name it. A 'retired' flag:
+// - is not bound to a C++ FLAGS_ reference.
+// - has a type and a value, but that value is intentionally inaccessible.
+// - does not appear in --help messages.
+// - is fully supported by _all_ flag parsing routines.
+// - consumes args normally, and complains about type mismatches in its
+// argument.
+// - emits a complaint but does not die (e.g. LOG(ERROR)) if it is
+// accessed by name through the flags API for parsing or otherwise.
+//
+// The registrations for a flag happen in an unspecified order as the
+// initializers for the namespace-scope objects of a program are run.
+// Any number of weak registrations for a flag can weakly define the flag.
+// One non-weak registration will upgrade the flag from weak to non-weak.
+// Further weak registrations of a non-weak flag are ignored.
+//
+// This mechanism is designed to support moving dead flags into a
+// 'graveyard' library. An example migration:
+//
+// 0: Remove references to this FLAGS_flagname in the C++ codebase.
+// 1: Register as 'retired' in old_lib.
+// 2: Make old_lib depend on graveyard.
+// 3: Add a redundant 'retired' registration to graveyard.
+// 4: Remove the old_lib 'retired' registration.
+// 5: Eventually delete the graveyard registration entirely.
+//
+
+// Retire flag with name "name" and type indicated by ops.
+void Retire(const char* name, FlagFastTypeId type_id, char* buf);
+
+constexpr size_t kRetiredFlagObjSize = 3 * sizeof(void*);
+constexpr size_t kRetiredFlagObjAlignment = alignof(void*);
+
+// Registered a retired flag with name 'flag_name' and type 'T'.
+template <typename T>
+class RetiredFlag {
+ public:
+ void Retire(const char* flag_name) {
+ flags_internal::Retire(flag_name, base_internal::FastTypeId<T>(), buf_);
+ }
+
+ private:
+ alignas(kRetiredFlagObjAlignment) char buf_[kRetiredFlagObjSize];
+};
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_INTERNAL_REGISTRY_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/sequence_lock.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/sequence_lock.h
new file mode 100644
index 0000000000..269b3413c8
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/sequence_lock.h
@@ -0,0 +1,187 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef Y_ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_
+#define Y_ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+#include <cassert>
+#include <cstring>
+
+#include "y_absl/base/optimization.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// Align 'x' up to the nearest 'align' bytes.
+inline constexpr size_t AlignUp(size_t x, size_t align) {
+ return align * ((x + align - 1) / align);
+}
+
+// A SequenceLock implements lock-free reads. A sequence counter is incremented
+// before and after each write, and readers access the counter before and after
+// accessing the protected data. If the counter is verified to not change during
+// the access, and the sequence counter value was even, then the reader knows
+// that the read was race-free and valid. Otherwise, the reader must fall back
+// to a Mutex-based code path.
+//
+// This particular SequenceLock starts in an "uninitialized" state in which
+// TryRead() returns false. It must be enabled by calling MarkInitialized().
+// This serves as a marker that the associated flag value has not yet been
+// initialized and a slow path needs to be taken.
+//
+// The memory reads and writes protected by this lock must use the provided
+// `TryRead()` and `Write()` functions. These functions behave similarly to
+// `memcpy()`, with one oddity: the protected data must be an array of
+// `std::atomic<uint64>`. This is to comply with the C++ standard, which
+// considers data races on non-atomic objects to be undefined behavior. See "Can
+// Seqlocks Get Along With Programming Language Memory Models?"[1] by Hans J.
+// Boehm for more details.
+//
+// [1] https://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf
+class SequenceLock {
+ public:
+ constexpr SequenceLock() : lock_(kUninitialized) {}
+
+ // Mark that this lock is ready for use.
+ void MarkInitialized() {
+ assert(lock_.load(std::memory_order_relaxed) == kUninitialized);
+ lock_.store(0, std::memory_order_release);
+ }
+
+ // Copy "size" bytes of data from "src" to "dst", protected as a read-side
+ // critical section of the sequence lock.
+ //
+ // Unlike traditional sequence lock implementations which loop until getting a
+ // clean read, this implementation returns false in the case of concurrent
+ // calls to `Write`. In such a case, the caller should fall back to a
+ // locking-based slow path.
+ //
+ // Returns false if the sequence lock was not yet marked as initialized.
+ //
+ // NOTE: If this returns false, "dst" may be overwritten with undefined
+ // (potentially uninitialized) data.
+ bool TryRead(void* dst, const std::atomic<uint64_t>* src, size_t size) const {
+ // Acquire barrier ensures that no loads done by f() are reordered
+ // above the first load of the sequence counter.
+ int64_t seq_before = lock_.load(std::memory_order_acquire);
+ if (Y_ABSL_PREDICT_FALSE(seq_before & 1) == 1) return false;
+ RelaxedCopyFromAtomic(dst, src, size);
+ // Another acquire fence ensures that the load of 'lock_' below is
+ // strictly ordered after the RelaxedCopyToAtomic call above.
+ std::atomic_thread_fence(std::memory_order_acquire);
+ int64_t seq_after = lock_.load(std::memory_order_relaxed);
+ return Y_ABSL_PREDICT_TRUE(seq_before == seq_after);
+ }
+
+ // Copy "size" bytes from "src" to "dst" as a write-side critical section
+ // of the sequence lock. Any concurrent readers will be forced to retry
+ // until they get a read that does not conflict with this write.
+ //
+ // This call must be externally synchronized against other calls to Write,
+ // but may proceed concurrently with reads.
+ void Write(std::atomic<uint64_t>* dst, const void* src, size_t size) {
+ // We can use relaxed instructions to increment the counter since we
+ // are extenally synchronized. The std::atomic_thread_fence below
+ // ensures that the counter updates don't get interleaved with the
+ // copy to the data.
+ int64_t orig_seq = lock_.load(std::memory_order_relaxed);
+ assert((orig_seq & 1) == 0); // Must be initially unlocked.
+ lock_.store(orig_seq + 1, std::memory_order_relaxed);
+
+ // We put a release fence between update to lock_ and writes to shared data.
+ // Thus all stores to shared data are effectively release operations and
+ // update to lock_ above cannot be re-ordered past any of them. Note that
+ // this barrier is not for the fetch_add above. A release barrier for the
+ // fetch_add would be before it, not after.
+ std::atomic_thread_fence(std::memory_order_release);
+ RelaxedCopyToAtomic(dst, src, size);
+ // "Release" semantics ensure that none of the writes done by
+ // RelaxedCopyToAtomic() can be reordered after the following modification.
+ lock_.store(orig_seq + 2, std::memory_order_release);
+ }
+
+ // Return the number of times that Write() has been called.
+ //
+ // REQUIRES: This must be externally synchronized against concurrent calls to
+ // `Write()` or `IncrementModificationCount()`.
+ // REQUIRES: `MarkInitialized()` must have been previously called.
+ int64_t ModificationCount() const {
+ int64_t val = lock_.load(std::memory_order_relaxed);
+ assert(val != kUninitialized && (val & 1) == 0);
+ return val / 2;
+ }
+
+ // REQUIRES: This must be externally synchronized against concurrent calls to
+ // `Write()` or `ModificationCount()`.
+ // REQUIRES: `MarkInitialized()` must have been previously called.
+ void IncrementModificationCount() {
+ int64_t val = lock_.load(std::memory_order_relaxed);
+ assert(val != kUninitialized);
+ lock_.store(val + 2, std::memory_order_relaxed);
+ }
+
+ private:
+ // Perform the equivalent of "memcpy(dst, src, size)", but using relaxed
+ // atomics.
+ static void RelaxedCopyFromAtomic(void* dst, const std::atomic<uint64_t>* src,
+ size_t size) {
+ char* dst_byte = static_cast<char*>(dst);
+ while (size >= sizeof(uint64_t)) {
+ uint64_t word = src->load(std::memory_order_relaxed);
+ std::memcpy(dst_byte, &word, sizeof(word));
+ dst_byte += sizeof(word);
+ src++;
+ size -= sizeof(word);
+ }
+ if (size > 0) {
+ uint64_t word = src->load(std::memory_order_relaxed);
+ std::memcpy(dst_byte, &word, size);
+ }
+ }
+
+ // Perform the equivalent of "memcpy(dst, src, size)", but using relaxed
+ // atomics.
+ static void RelaxedCopyToAtomic(std::atomic<uint64_t>* dst, const void* src,
+ size_t size) {
+ const char* src_byte = static_cast<const char*>(src);
+ while (size >= sizeof(uint64_t)) {
+ uint64_t word;
+ std::memcpy(&word, src_byte, sizeof(word));
+ dst->store(word, std::memory_order_relaxed);
+ src_byte += sizeof(word);
+ dst++;
+ size -= sizeof(word);
+ }
+ if (size > 0) {
+ uint64_t word = 0;
+ std::memcpy(&word, src_byte, size);
+ dst->store(word, std::memory_order_relaxed);
+ }
+ }
+
+ static constexpr int64_t kUninitialized = -1;
+ std::atomic<int64_t> lock_;
+};
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/usage.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/usage.cc
new file mode 100644
index 0000000000..a4331c33fa
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/usage.cc
@@ -0,0 +1,526 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "y_absl/flags/internal/usage.h"
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <map>
+#include <ostream>
+#include <util/generic/string.h>
+#include <utility>
+#include <vector>
+
+#include "y_absl/base/config.h"
+#include "y_absl/flags/commandlineflag.h"
+#include "y_absl/flags/flag.h"
+#include "y_absl/flags/internal/flag.h"
+#include "y_absl/flags/internal/path_util.h"
+#include "y_absl/flags/internal/private_handle_accessor.h"
+#include "y_absl/flags/internal/program_name.h"
+#include "y_absl/flags/internal/registry.h"
+#include "y_absl/flags/usage_config.h"
+#include "y_absl/strings/match.h"
+#include "y_absl/strings/str_cat.h"
+#include "y_absl/strings/str_split.h"
+#include "y_absl/strings/string_view.h"
+
+// Dummy global variables to prevent anyone else defining these.
+bool FLAGS_help = false;
+bool FLAGS_helpfull = false;
+bool FLAGS_helpshort = false;
+bool FLAGS_helppackage = false;
+bool FLAGS_version = false;
+bool FLAGS_only_check_args = false;
+bool FLAGS_helpon = false;
+bool FLAGS_helpmatch = false;
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+namespace {
+
+using PerFlagFilter = std::function<bool(const y_absl::CommandLineFlag&)>;
+
+// Maximum length size in a human readable format.
+constexpr size_t kHrfMaxLineLength = 80;
+
+// This class is used to emit an XML element with `tag` and `text`.
+// It adds opening and closing tags and escapes special characters in the text.
+// For example:
+// std::cout << XMLElement("title", "Milk & Cookies");
+// prints "<title>Milk &amp; Cookies</title>"
+class XMLElement {
+ public:
+ XMLElement(y_absl::string_view tag, y_absl::string_view txt)
+ : tag_(tag), txt_(txt) {}
+
+ friend std::ostream& operator<<(std::ostream& out,
+ const XMLElement& xml_elem) {
+ out << "<" << xml_elem.tag_ << ">";
+
+ for (auto c : xml_elem.txt_) {
+ switch (c) {
+ case '"':
+ out << "&quot;";
+ break;
+ case '\'':
+ out << "&apos;";
+ break;
+ case '&':
+ out << "&amp;";
+ break;
+ case '<':
+ out << "&lt;";
+ break;
+ case '>':
+ out << "&gt;";
+ break;
+ default:
+ out << c;
+ break;
+ }
+ }
+
+ return out << "</" << xml_elem.tag_ << ">";
+ }
+
+ private:
+ y_absl::string_view tag_;
+ y_absl::string_view txt_;
+};
+
+// --------------------------------------------------------------------
+// Helper class to pretty-print info about a flag.
+
+class FlagHelpPrettyPrinter {
+ public:
+ // Pretty printer holds on to the std::ostream& reference to direct an output
+ // to that stream.
+ FlagHelpPrettyPrinter(size_t max_line_len, size_t min_line_len,
+ size_t wrapped_line_indent, std::ostream& out)
+ : out_(out),
+ max_line_len_(max_line_len),
+ min_line_len_(min_line_len),
+ wrapped_line_indent_(wrapped_line_indent),
+ line_len_(0),
+ first_line_(true) {}
+
+ void Write(y_absl::string_view str, bool wrap_line = false) {
+ // Empty string - do nothing.
+ if (str.empty()) return;
+
+ std::vector<y_absl::string_view> tokens;
+ if (wrap_line) {
+ for (auto line : y_absl::StrSplit(str, y_absl::ByAnyChar("\n\r"))) {
+ if (!tokens.empty()) {
+ // Keep line separators in the input string.
+ tokens.push_back("\n");
+ }
+ for (auto token :
+ y_absl::StrSplit(line, y_absl::ByAnyChar(" \t"), y_absl::SkipEmpty())) {
+ tokens.push_back(token);
+ }
+ }
+ } else {
+ tokens.push_back(str);
+ }
+
+ for (auto token : tokens) {
+ bool new_line = (line_len_ == 0);
+
+ // Respect line separators in the input string.
+ if (token == "\n") {
+ EndLine();
+ continue;
+ }
+
+ // Write the token, ending the string first if necessary/possible.
+ if (!new_line && (line_len_ + token.size() >= max_line_len_)) {
+ EndLine();
+ new_line = true;
+ }
+
+ if (new_line) {
+ StartLine();
+ } else {
+ out_ << ' ';
+ ++line_len_;
+ }
+
+ out_ << token;
+ line_len_ += token.size();
+ }
+ }
+
+ void StartLine() {
+ if (first_line_) {
+ line_len_ = min_line_len_;
+ first_line_ = false;
+ } else {
+ line_len_ = min_line_len_ + wrapped_line_indent_;
+ }
+ out_ << TString(line_len_, ' ');
+ }
+ void EndLine() {
+ out_ << '\n';
+ line_len_ = 0;
+ }
+
+ private:
+ std::ostream& out_;
+ const size_t max_line_len_;
+ const size_t min_line_len_;
+ const size_t wrapped_line_indent_;
+ size_t line_len_;
+ bool first_line_;
+};
+
+void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
+ FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 4, 2, out);
+
+ // Flag name.
+ printer.Write(y_absl::StrCat("--", flag.Name()));
+
+ // Flag help.
+ printer.Write(y_absl::StrCat("(", flag.Help(), ");"), /*wrap_line=*/true);
+
+ // The listed default value will be the actual default from the flag
+ // definition in the originating source file, unless the value has
+ // subsequently been modified using SetCommandLineOption() with mode
+ // SET_FLAGS_DEFAULT.
+ TString dflt_val = flag.DefaultValue();
+ TString curr_val = flag.CurrentValue();
+ bool is_modified = curr_val != dflt_val;
+
+ if (flag.IsOfType<TString>()) {
+ dflt_val = y_absl::StrCat("\"", dflt_val, "\"");
+ }
+ printer.Write(y_absl::StrCat("default: ", dflt_val, ";"));
+
+ if (is_modified) {
+ if (flag.IsOfType<TString>()) {
+ curr_val = y_absl::StrCat("\"", curr_val, "\"");
+ }
+ printer.Write(y_absl::StrCat("currently: ", curr_val, ";"));
+ }
+
+ printer.EndLine();
+}
+
+// Shows help for every filename which matches any of the filters
+// If filters are empty, shows help for every file.
+// If a flag's help message has been stripped (e.g. by adding '#define
+// STRIP_FLAG_HELP 1' then this flag will not be displayed by '--help'
+// and its variants.
+void FlagsHelpImpl(std::ostream& out, PerFlagFilter filter_cb,
+ HelpFormat format, y_absl::string_view program_usage_message) {
+ if (format == HelpFormat::kHumanReadable) {
+ out << flags_internal::ShortProgramInvocationName() << ": "
+ << program_usage_message << "\n\n";
+ } else {
+ // XML schema is not a part of our public API for now.
+ out << "<?xml version=\"1.0\"?>\n"
+ << "<!-- This output should be used with care. We do not report type "
+ "names for flags with user defined types -->\n"
+ << "<!-- Prefer flag only_check_args for validating flag inputs -->\n"
+ // The document.
+ << "<AllFlags>\n"
+ // The program name and usage.
+ << XMLElement("program", flags_internal::ShortProgramInvocationName())
+ << '\n'
+ << XMLElement("usage", program_usage_message) << '\n';
+ }
+
+ // Ordered map of package name to
+ // map of file name to
+ // vector of flags in the file.
+ // This map is used to output matching flags grouped by package and file
+ // name.
+ std::map<TString,
+ std::map<TString, std::vector<const y_absl::CommandLineFlag*>>>
+ matching_flags;
+
+ flags_internal::ForEachFlag([&](y_absl::CommandLineFlag& flag) {
+ // Ignore retired flags.
+ if (flag.IsRetired()) return;
+
+ // If the flag has been stripped, pretend that it doesn't exist.
+ if (flag.Help() == flags_internal::kStrippedFlagHelp) return;
+
+ // Make sure flag satisfies the filter
+ if (!filter_cb(flag)) return;
+
+ TString flag_filename = flag.Filename();
+
+ matching_flags[TString(flags_internal::Package(flag_filename))]
+ [flag_filename]
+ .push_back(&flag);
+ });
+
+ y_absl::string_view package_separator; // controls blank lines between packages
+ y_absl::string_view file_separator; // controls blank lines between files
+ for (auto& package : matching_flags) {
+ if (format == HelpFormat::kHumanReadable) {
+ out << package_separator;
+ package_separator = "\n\n";
+ }
+
+ file_separator = "";
+ for (auto& flags_in_file : package.second) {
+ if (format == HelpFormat::kHumanReadable) {
+ out << file_separator << " Flags from " << flags_in_file.first
+ << ":\n";
+ file_separator = "\n";
+ }
+
+ std::sort(std::begin(flags_in_file.second),
+ std::end(flags_in_file.second),
+ [](const CommandLineFlag* lhs, const CommandLineFlag* rhs) {
+ return lhs->Name() < rhs->Name();
+ });
+
+ for (const auto* flag : flags_in_file.second) {
+ flags_internal::FlagHelp(out, *flag, format);
+ }
+ }
+ }
+
+ if (format == HelpFormat::kHumanReadable) {
+ FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 0, 0, out);
+
+ if (filter_cb && matching_flags.empty()) {
+ printer.Write("No flags matched.\n", true);
+ }
+ printer.EndLine();
+ printer.Write(
+ "Try --helpfull to get a list of all flags or --help=substring "
+ "shows help for flags which include specified substring in either "
+ "in the name, or description or path.\n",
+ true);
+ } else {
+ // The end of the document.
+ out << "</AllFlags>\n";
+ }
+}
+
+void FlagsHelpImpl(std::ostream& out,
+ flags_internal::FlagKindFilter filename_filter_cb,
+ HelpFormat format, y_absl::string_view program_usage_message) {
+ FlagsHelpImpl(
+ out,
+ [&](const y_absl::CommandLineFlag& flag) {
+ return filename_filter_cb && filename_filter_cb(flag.Filename());
+ },
+ format, program_usage_message);
+}
+
+} // namespace
+
+// --------------------------------------------------------------------
+// Produces the help message describing specific flag.
+void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
+ HelpFormat format) {
+ if (format == HelpFormat::kHumanReadable)
+ flags_internal::FlagHelpHumanReadable(flag, out);
+}
+
+// --------------------------------------------------------------------
+// Produces the help messages for all flags matching the filename filter.
+// If filter is empty produces help messages for all flags.
+void FlagsHelp(std::ostream& out, y_absl::string_view filter, HelpFormat format,
+ y_absl::string_view program_usage_message) {
+ flags_internal::FlagKindFilter filter_cb = [&](y_absl::string_view filename) {
+ return filter.empty() || y_absl::StrContains(filename, filter);
+ };
+ flags_internal::FlagsHelpImpl(out, filter_cb, format, program_usage_message);
+}
+
+// --------------------------------------------------------------------
+// Checks all the 'usage' command line flags to see if any have been set.
+// If so, handles them appropriately.
+int HandleUsageFlags(std::ostream& out,
+ y_absl::string_view program_usage_message) {
+ switch (GetFlagsHelpMode()) {
+ case HelpMode::kNone:
+ break;
+ case HelpMode::kImportant:
+ flags_internal::FlagsHelpImpl(
+ out, flags_internal::GetUsageConfig().contains_help_flags,
+ GetFlagsHelpFormat(), program_usage_message);
+ return 1;
+
+ case HelpMode::kShort:
+ flags_internal::FlagsHelpImpl(
+ out, flags_internal::GetUsageConfig().contains_helpshort_flags,
+ GetFlagsHelpFormat(), program_usage_message);
+ return 1;
+
+ case HelpMode::kFull:
+ flags_internal::FlagsHelp(out, "", GetFlagsHelpFormat(),
+ program_usage_message);
+ return 1;
+
+ case HelpMode::kPackage:
+ flags_internal::FlagsHelpImpl(
+ out, flags_internal::GetUsageConfig().contains_helppackage_flags,
+ GetFlagsHelpFormat(), program_usage_message);
+
+ return 1;
+
+ case HelpMode::kMatch: {
+ TString substr = GetFlagsHelpMatchSubstr();
+ if (substr.empty()) {
+ // show all options
+ flags_internal::FlagsHelp(out, substr, GetFlagsHelpFormat(),
+ program_usage_message);
+ } else {
+ auto filter_cb = [&substr](const y_absl::CommandLineFlag& flag) {
+ if (y_absl::StrContains(flag.Name(), substr)) return true;
+ if (y_absl::StrContains(flag.Filename(), substr)) return true;
+ if (y_absl::StrContains(flag.Help(), substr)) return true;
+
+ return false;
+ };
+ flags_internal::FlagsHelpImpl(
+ out, filter_cb, HelpFormat::kHumanReadable, program_usage_message);
+ }
+
+ return 1;
+ }
+ case HelpMode::kVersion:
+ if (flags_internal::GetUsageConfig().version_string)
+ out << flags_internal::GetUsageConfig().version_string();
+ // Unlike help, we may be asking for version in a script, so return 0
+ return 0;
+
+ case HelpMode::kOnlyCheckArgs:
+ return 0;
+ }
+
+ return -1;
+}
+
+// --------------------------------------------------------------------
+// Globals representing usage reporting flags
+
+namespace {
+
+Y_ABSL_CONST_INIT y_absl::Mutex help_attributes_guard(y_absl::kConstInit);
+Y_ABSL_CONST_INIT TString* match_substr
+ Y_ABSL_GUARDED_BY(help_attributes_guard) = nullptr;
+Y_ABSL_CONST_INIT HelpMode help_mode Y_ABSL_GUARDED_BY(help_attributes_guard) =
+ HelpMode::kNone;
+Y_ABSL_CONST_INIT HelpFormat help_format Y_ABSL_GUARDED_BY(help_attributes_guard) =
+ HelpFormat::kHumanReadable;
+
+} // namespace
+
+TString GetFlagsHelpMatchSubstr() {
+ y_absl::MutexLock l(&help_attributes_guard);
+ if (match_substr == nullptr) return "";
+ return *match_substr;
+}
+
+void SetFlagsHelpMatchSubstr(y_absl::string_view substr) {
+ y_absl::MutexLock l(&help_attributes_guard);
+ if (match_substr == nullptr) match_substr = new TString;
+ match_substr->assign(substr.data(), substr.size());
+}
+
+HelpMode GetFlagsHelpMode() {
+ y_absl::MutexLock l(&help_attributes_guard);
+ return help_mode;
+}
+
+void SetFlagsHelpMode(HelpMode mode) {
+ y_absl::MutexLock l(&help_attributes_guard);
+ help_mode = mode;
+}
+
+HelpFormat GetFlagsHelpFormat() {
+ y_absl::MutexLock l(&help_attributes_guard);
+ return help_format;
+}
+
+void SetFlagsHelpFormat(HelpFormat format) {
+ y_absl::MutexLock l(&help_attributes_guard);
+ help_format = format;
+}
+
+// Deduces usage flags from the input argument in a form --name=value or
+// --name. argument is already split into name and value before we call this
+// function.
+bool DeduceUsageFlags(y_absl::string_view name, y_absl::string_view value) {
+ if (y_absl::ConsumePrefix(&name, "help")) {
+ if (name.empty()) {
+ if (value.empty()) {
+ SetFlagsHelpMode(HelpMode::kImportant);
+ } else {
+ SetFlagsHelpMode(HelpMode::kMatch);
+ SetFlagsHelpMatchSubstr(value);
+ }
+ return true;
+ }
+
+ if (name == "match") {
+ SetFlagsHelpMode(HelpMode::kMatch);
+ SetFlagsHelpMatchSubstr(value);
+ return true;
+ }
+
+ if (name == "on") {
+ SetFlagsHelpMode(HelpMode::kMatch);
+ SetFlagsHelpMatchSubstr(y_absl::StrCat("/", value, "."));
+ return true;
+ }
+
+ if (name == "full") {
+ SetFlagsHelpMode(HelpMode::kFull);
+ return true;
+ }
+
+ if (name == "short") {
+ SetFlagsHelpMode(HelpMode::kShort);
+ return true;
+ }
+
+ if (name == "package") {
+ SetFlagsHelpMode(HelpMode::kPackage);
+ return true;
+ }
+
+ return false;
+ }
+
+ if (name == "version") {
+ SetFlagsHelpMode(HelpMode::kVersion);
+ return true;
+ }
+
+ if (name == "only_check_args") {
+ SetFlagsHelpMode(HelpMode::kOnlyCheckArgs);
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/usage.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/usage.h
new file mode 100644
index 0000000000..cc7adf27cb
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/internal/usage.h
@@ -0,0 +1,104 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef Y_ABSL_FLAGS_INTERNAL_USAGE_H_
+#define Y_ABSL_FLAGS_INTERNAL_USAGE_H_
+
+#include <iosfwd>
+#include <util/generic/string.h>
+
+#include "y_absl/base/config.h"
+#include "y_absl/flags/commandlineflag.h"
+#include "y_absl/flags/declare.h"
+#include "y_absl/strings/string_view.h"
+
+// --------------------------------------------------------------------
+// Usage reporting interfaces
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// The format to report the help messages in.
+enum class HelpFormat {
+ kHumanReadable,
+};
+
+// Streams the help message describing `flag` to `out`.
+// The default value for `flag` is included in the output.
+void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
+ HelpFormat format = HelpFormat::kHumanReadable);
+
+// Produces the help messages for all flags matching the filter. A flag matches
+// the filter if it is defined in a file with a filename which includes
+// filter string as a substring. You can use '/' and '.' to restrict the
+// matching to a specific file names. For example:
+// FlagsHelp(out, "/path/to/file.");
+// restricts help to only flags which resides in files named like:
+// .../path/to/file.<ext>
+// for any extension 'ext'. If the filter is empty this function produces help
+// messages for all flags.
+void FlagsHelp(std::ostream& out, y_absl::string_view filter,
+ HelpFormat format, y_absl::string_view program_usage_message);
+
+// --------------------------------------------------------------------
+
+// If any of the 'usage' related command line flags (listed on the bottom of
+// this file) has been set this routine produces corresponding help message in
+// the specified output stream and returns:
+// 0 - if "version" or "only_check_flags" flags were set and handled.
+// 1 - if some other 'usage' related flag was set and handled.
+// -1 - if no usage flags were set on a commmand line.
+// Non negative return values are expected to be used as an exit code for a
+// binary.
+int HandleUsageFlags(std::ostream& out,
+ y_absl::string_view program_usage_message);
+
+// --------------------------------------------------------------------
+// Globals representing usage reporting flags
+
+enum class HelpMode {
+ kNone,
+ kImportant,
+ kShort,
+ kFull,
+ kPackage,
+ kMatch,
+ kVersion,
+ kOnlyCheckArgs
+};
+
+// Returns substring to filter help output (--help=substr argument)
+TString GetFlagsHelpMatchSubstr();
+// Returns the requested help mode.
+HelpMode GetFlagsHelpMode();
+// Returns the requested help format.
+HelpFormat GetFlagsHelpFormat();
+
+// These are corresponding setters to the attributes above.
+void SetFlagsHelpMatchSubstr(y_absl::string_view);
+void SetFlagsHelpMode(HelpMode);
+void SetFlagsHelpFormat(HelpFormat);
+
+// Deduces usage flags from the input argument in a form --name=value or
+// --name. argument is already split into name and value before we call this
+// function.
+bool DeduceUsageFlags(y_absl::string_view name, y_absl::string_view value);
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_INTERNAL_USAGE_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/marshalling.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/marshalling.cc
new file mode 100644
index 0000000000..51abb779fb
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/marshalling.cc
@@ -0,0 +1,241 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "y_absl/flags/marshalling.h"
+
+#include <stddef.h>
+
+#include <cmath>
+#include <limits>
+#include <util/generic/string.h>
+#include <type_traits>
+#include <vector>
+
+#include "y_absl/base/config.h"
+#include "y_absl/base/log_severity.h"
+#include "y_absl/base/macros.h"
+#include "y_absl/strings/ascii.h"
+#include "y_absl/strings/match.h"
+#include "y_absl/strings/numbers.h"
+#include "y_absl/strings/str_cat.h"
+#include "y_absl/strings/str_format.h"
+#include "y_absl/strings/str_join.h"
+#include "y_absl/strings/str_split.h"
+#include "y_absl/strings/string_view.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// --------------------------------------------------------------------
+// AbslParseFlag specializations for boolean type.
+
+bool AbslParseFlag(y_absl::string_view text, bool* dst, TString*) {
+ const char* kTrue[] = {"1", "t", "true", "y", "yes"};
+ const char* kFalse[] = {"0", "f", "false", "n", "no"};
+ static_assert(sizeof(kTrue) == sizeof(kFalse), "true_false_equal");
+
+ text = y_absl::StripAsciiWhitespace(text);
+
+ for (size_t i = 0; i < Y_ABSL_ARRAYSIZE(kTrue); ++i) {
+ if (y_absl::EqualsIgnoreCase(text, kTrue[i])) {
+ *dst = true;
+ return true;
+ } else if (y_absl::EqualsIgnoreCase(text, kFalse[i])) {
+ *dst = false;
+ return true;
+ }
+ }
+ return false; // didn't match a legal input
+}
+
+// --------------------------------------------------------------------
+// AbslParseFlag for integral types.
+
+// Return the base to use for parsing text as an integer. Leading 0x
+// puts us in base 16. But leading 0 does not put us in base 8. It
+// caused too many bugs when we had that behavior.
+static int NumericBase(y_absl::string_view text) {
+ const bool hex = (text.size() >= 2 && text[0] == '0' &&
+ (text[1] == 'x' || text[1] == 'X'));
+ return hex ? 16 : 10;
+}
+
+template <typename IntType>
+inline bool ParseFlagImpl(y_absl::string_view text, IntType& dst) {
+ text = y_absl::StripAsciiWhitespace(text);
+
+ return y_absl::numbers_internal::safe_strtoi_base(text, &dst,
+ NumericBase(text));
+}
+
+bool AbslParseFlag(y_absl::string_view text, short* dst, TString*) {
+ int val;
+ if (!ParseFlagImpl(text, val)) return false;
+ if (static_cast<short>(val) != val) // worked, but number out of range
+ return false;
+ *dst = static_cast<short>(val);
+ return true;
+}
+
+bool AbslParseFlag(y_absl::string_view text, unsigned short* dst, TString*) {
+ unsigned int val;
+ if (!ParseFlagImpl(text, val)) return false;
+ if (static_cast<unsigned short>(val) !=
+ val) // worked, but number out of range
+ return false;
+ *dst = static_cast<unsigned short>(val);
+ return true;
+}
+
+bool AbslParseFlag(y_absl::string_view text, int* dst, TString*) {
+ return ParseFlagImpl(text, *dst);
+}
+
+bool AbslParseFlag(y_absl::string_view text, unsigned int* dst, TString*) {
+ return ParseFlagImpl(text, *dst);
+}
+
+bool AbslParseFlag(y_absl::string_view text, long* dst, TString*) {
+ return ParseFlagImpl(text, *dst);
+}
+
+bool AbslParseFlag(y_absl::string_view text, unsigned long* dst, TString*) {
+ return ParseFlagImpl(text, *dst);
+}
+
+bool AbslParseFlag(y_absl::string_view text, long long* dst, TString*) {
+ return ParseFlagImpl(text, *dst);
+}
+
+bool AbslParseFlag(y_absl::string_view text, unsigned long long* dst,
+ TString*) {
+ return ParseFlagImpl(text, *dst);
+}
+
+// --------------------------------------------------------------------
+// AbslParseFlag for floating point types.
+
+bool AbslParseFlag(y_absl::string_view text, float* dst, TString*) {
+ return y_absl::SimpleAtof(text, dst);
+}
+
+bool AbslParseFlag(y_absl::string_view text, double* dst, TString*) {
+ return y_absl::SimpleAtod(text, dst);
+}
+
+// --------------------------------------------------------------------
+// AbslParseFlag for strings.
+
+bool AbslParseFlag(y_absl::string_view text, TString* dst, TString*) {
+ dst->assign(text.data(), text.size());
+ return true;
+}
+
+// --------------------------------------------------------------------
+// AbslParseFlag for vector of strings.
+
+bool AbslParseFlag(y_absl::string_view text, std::vector<TString>* dst,
+ TString*) {
+ // An empty flag value corresponds to an empty vector, not a vector
+ // with a single, empty TString.
+ if (text.empty()) {
+ dst->clear();
+ return true;
+ }
+ *dst = y_absl::StrSplit(text, ',', y_absl::AllowEmpty());
+ return true;
+}
+
+// --------------------------------------------------------------------
+// AbslUnparseFlag specializations for various builtin flag types.
+
+TString Unparse(bool v) { return v ? "true" : "false"; }
+TString Unparse(short v) { return y_absl::StrCat(v); }
+TString Unparse(unsigned short v) { return y_absl::StrCat(v); }
+TString Unparse(int v) { return y_absl::StrCat(v); }
+TString Unparse(unsigned int v) { return y_absl::StrCat(v); }
+TString Unparse(long v) { return y_absl::StrCat(v); }
+TString Unparse(unsigned long v) { return y_absl::StrCat(v); }
+TString Unparse(long long v) { return y_absl::StrCat(v); }
+TString Unparse(unsigned long long v) { return y_absl::StrCat(v); }
+template <typename T>
+TString UnparseFloatingPointVal(T v) {
+ // digits10 is guaranteed to roundtrip correctly in string -> value -> string
+ // conversions, but may not be enough to represent all the values correctly.
+ TString digit10_str =
+ y_absl::StrFormat("%.*g", std::numeric_limits<T>::digits10, v);
+ if (std::isnan(v) || std::isinf(v)) return digit10_str;
+
+ T roundtrip_val = 0;
+ TString err;
+ if (y_absl::ParseFlag(digit10_str, &roundtrip_val, &err) &&
+ roundtrip_val == v) {
+ return digit10_str;
+ }
+
+ // max_digits10 is the number of base-10 digits that are necessary to uniquely
+ // represent all distinct values.
+ return y_absl::StrFormat("%.*g", std::numeric_limits<T>::max_digits10, v);
+}
+TString Unparse(float v) { return UnparseFloatingPointVal(v); }
+TString Unparse(double v) { return UnparseFloatingPointVal(v); }
+TString AbslUnparseFlag(y_absl::string_view v) { return TString(v); }
+TString AbslUnparseFlag(const std::vector<TString>& v) {
+ return y_absl::StrJoin(v, ",");
+}
+
+} // namespace flags_internal
+
+bool AbslParseFlag(y_absl::string_view text, y_absl::LogSeverity* dst,
+ TString* err) {
+ text = y_absl::StripAsciiWhitespace(text);
+ if (text.empty()) {
+ *err = "no value provided";
+ return false;
+ }
+ if (text.front() == 'k' || text.front() == 'K') text.remove_prefix(1);
+ if (y_absl::EqualsIgnoreCase(text, "info")) {
+ *dst = y_absl::LogSeverity::kInfo;
+ return true;
+ }
+ if (y_absl::EqualsIgnoreCase(text, "warning")) {
+ *dst = y_absl::LogSeverity::kWarning;
+ return true;
+ }
+ if (y_absl::EqualsIgnoreCase(text, "error")) {
+ *dst = y_absl::LogSeverity::kError;
+ return true;
+ }
+ if (y_absl::EqualsIgnoreCase(text, "fatal")) {
+ *dst = y_absl::LogSeverity::kFatal;
+ return true;
+ }
+ std::underlying_type<y_absl::LogSeverity>::type numeric_value;
+ if (y_absl::ParseFlag(text, &numeric_value, err)) {
+ *dst = static_cast<y_absl::LogSeverity>(numeric_value);
+ return true;
+ }
+ *err = "only integers and y_absl::LogSeverity enumerators are accepted";
+ return false;
+}
+
+TString AbslUnparseFlag(y_absl::LogSeverity v) {
+ if (v == y_absl::NormalizeLogSeverity(v)) return y_absl::LogSeverityName(v);
+ return y_absl::UnparseFlag(static_cast<int>(v));
+}
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/marshalling.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/marshalling.h
new file mode 100644
index 0000000000..237b47a7eb
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/marshalling.h
@@ -0,0 +1,356 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: marshalling.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the API for extending Abseil flag support to
+// custom types, and defines the set of overloads for fundamental types.
+//
+// Out of the box, the Abseil flags library supports the following types:
+//
+// * `bool`
+// * `int16_t`
+// * `uint16_t`
+// * `int32_t`
+// * `uint32_t`
+// * `int64_t`
+// * `uint64_t`
+// * `float`
+// * `double`
+// * `TString`
+// * `std::vector<TString>`
+// * `std::optional<T>`
+// * `y_absl::LogSeverity` (provided natively for layering reasons)
+//
+// Note that support for integral types is implemented using overloads for
+// variable-width fundamental types (`short`, `int`, `long`, etc.). However,
+// you should prefer the fixed-width integral types (`int32_t`, `uint64_t`,
+// etc.) we've noted above within flag definitions.
+//
+// In addition, several Abseil libraries provide their own custom support for
+// Abseil flags. Documentation for these formats is provided in the type's
+// `AbslParseFlag()` definition.
+//
+// The Abseil time library provides the following support for civil time values:
+//
+// * `y_absl::CivilSecond`
+// * `y_absl::CivilMinute`
+// * `y_absl::CivilHour`
+// * `y_absl::CivilDay`
+// * `y_absl::CivilMonth`
+// * `y_absl::CivilYear`
+//
+// and also provides support for the following absolute time values:
+//
+// * `y_absl::Duration`
+// * `y_absl::Time`
+//
+// Additional support for Abseil types will be noted here as it is added.
+//
+// You can also provide your own custom flags by adding overloads for
+// `AbslParseFlag()` and `AbslUnparseFlag()` to your type definitions. (See
+// below.)
+//
+// -----------------------------------------------------------------------------
+// Optional Flags
+// -----------------------------------------------------------------------------
+//
+// The Abseil flags library supports flags of type `std::optional<T>` where
+// `T` is a type of one of the supported flags. We refer to this flag type as
+// an "optional flag." An optional flag is either "valueless", holding no value
+// of type `T` (indicating that the flag has not been set) or a value of type
+// `T`. The valueless state in C++ code is represented by a value of
+// `std::nullopt` for the optional flag.
+//
+// Using `std::nullopt` as an optional flag's default value allows you to check
+// whether such a flag was ever specified on the command line:
+//
+// if (y_absl::GetFlag(FLAGS_foo).has_value()) {
+// // flag was set on command line
+// } else {
+// // flag was not passed on command line
+// }
+//
+// Using an optional flag in this manner avoids common workarounds for
+// indicating such an unset flag (such as using sentinel values to indicate this
+// state).
+//
+// An optional flag also allows a developer to pass a flag in an "unset"
+// valueless state on the command line, allowing the flag to later be set in
+// binary logic. An optional flag's valueless state is indicated by the special
+// notation of passing the value as an empty string through the syntax `--flag=`
+// or `--flag ""`.
+//
+// $ binary_with_optional --flag_in_unset_state=
+// $ binary_with_optional --flag_in_unset_state ""
+//
+// Note: as a result of the above syntax requirements, an optional flag cannot
+// be set to a `T` of any value which unparses to the empty string.
+//
+// -----------------------------------------------------------------------------
+// Adding Type Support for Abseil Flags
+// -----------------------------------------------------------------------------
+//
+// To add support for your user-defined type, add overloads of `AbslParseFlag()`
+// and `AbslUnparseFlag()` as free (non-member) functions to your type. If `T`
+// is a class type, these functions can be friend function definitions. These
+// overloads must be added to the same namespace where the type is defined, so
+// that they can be discovered by Argument-Dependent Lookup (ADL).
+//
+// Example:
+//
+// namespace foo {
+//
+// enum OutputMode { kPlainText, kHtml };
+//
+// // AbslParseFlag converts from a string to OutputMode.
+// // Must be in same namespace as OutputMode.
+//
+// // Parses an OutputMode from the command line flag value `text`. Returns
+// // `true` and sets `*mode` on success; returns `false` and sets `*error`
+// // on failure.
+// bool AbslParseFlag(y_absl::string_view text,
+// OutputMode* mode,
+// TString* error) {
+// if (text == "plaintext") {
+// *mode = kPlainText;
+// return true;
+// }
+// if (text == "html") {
+// *mode = kHtml;
+// return true;
+// }
+// *error = "unknown value for enumeration";
+// return false;
+// }
+//
+// // AbslUnparseFlag converts from an OutputMode to a string.
+// // Must be in same namespace as OutputMode.
+//
+// // Returns a textual flag value corresponding to the OutputMode `mode`.
+// TString AbslUnparseFlag(OutputMode mode) {
+// switch (mode) {
+// case kPlainText: return "plaintext";
+// case kHtml: return "html";
+// }
+// return y_absl::StrCat(mode);
+// }
+//
+// Notice that neither `AbslParseFlag()` nor `AbslUnparseFlag()` are class
+// members, but free functions. `AbslParseFlag/AbslUnparseFlag()` overloads
+// for a type should only be declared in the same file and namespace as said
+// type. The proper `AbslParseFlag/AbslUnparseFlag()` implementations for a
+// given type will be discovered via Argument-Dependent Lookup (ADL).
+//
+// `AbslParseFlag()` may need, in turn, to parse simpler constituent types
+// using `y_absl::ParseFlag()`. For example, a custom struct `MyFlagType`
+// consisting of a `std::pair<int, TString>` would add an `AbslParseFlag()`
+// overload for its `MyFlagType` like so:
+//
+// Example:
+//
+// namespace my_flag_type {
+//
+// struct MyFlagType {
+// std::pair<int, TString> my_flag_data;
+// };
+//
+// bool AbslParseFlag(y_absl::string_view text, MyFlagType* flag,
+// TString* err);
+//
+// TString AbslUnparseFlag(const MyFlagType&);
+//
+// // Within the implementation, `AbslParseFlag()` will, in turn invoke
+// // `y_absl::ParseFlag()` on its constituent `int` and `TString` types
+// // (which have built-in Abseil flag support).
+//
+// bool AbslParseFlag(y_absl::string_view text, MyFlagType* flag,
+// TString* err) {
+// std::pair<y_absl::string_view, y_absl::string_view> tokens =
+// y_absl::StrSplit(text, ',');
+// if (!y_absl::ParseFlag(tokens.first, &flag->my_flag_data.first, err))
+// return false;
+// if (!y_absl::ParseFlag(tokens.second, &flag->my_flag_data.second, err))
+// return false;
+// return true;
+// }
+//
+// // Similarly, for unparsing, we can simply invoke `y_absl::UnparseFlag()` on
+// // the constituent types.
+// TString AbslUnparseFlag(const MyFlagType& flag) {
+// return y_absl::StrCat(y_absl::UnparseFlag(flag.my_flag_data.first),
+// ",",
+// y_absl::UnparseFlag(flag.my_flag_data.second));
+// }
+#ifndef Y_ABSL_FLAGS_MARSHALLING_H_
+#define Y_ABSL_FLAGS_MARSHALLING_H_
+
+#include "y_absl/base/config.h"
+
+#if defined(Y_ABSL_HAVE_STD_OPTIONAL) && !defined(Y_ABSL_USES_STD_OPTIONAL)
+#include <optional>
+#endif
+#include <util/generic/string.h>
+#include <vector>
+
+#include "y_absl/strings/string_view.h"
+#include "y_absl/types/optional.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+
+// Forward declaration to be used inside composable flag parse/unparse
+// implementations
+template <typename T>
+inline bool ParseFlag(y_absl::string_view input, T* dst, TString* error);
+template <typename T>
+inline TString UnparseFlag(const T& v);
+
+namespace flags_internal {
+
+// Overloads of `AbslParseFlag()` and `AbslUnparseFlag()` for fundamental types.
+bool AbslParseFlag(y_absl::string_view, bool*, TString*);
+bool AbslParseFlag(y_absl::string_view, short*, TString*); // NOLINT
+bool AbslParseFlag(y_absl::string_view, unsigned short*, TString*); // NOLINT
+bool AbslParseFlag(y_absl::string_view, int*, TString*); // NOLINT
+bool AbslParseFlag(y_absl::string_view, unsigned int*, TString*); // NOLINT
+bool AbslParseFlag(y_absl::string_view, long*, TString*); // NOLINT
+bool AbslParseFlag(y_absl::string_view, unsigned long*, TString*); // NOLINT
+bool AbslParseFlag(y_absl::string_view, long long*, TString*); // NOLINT
+bool AbslParseFlag(y_absl::string_view, unsigned long long*, // NOLINT
+ TString*);
+bool AbslParseFlag(y_absl::string_view, float*, TString*);
+bool AbslParseFlag(y_absl::string_view, double*, TString*);
+bool AbslParseFlag(y_absl::string_view, TString*, TString*);
+bool AbslParseFlag(y_absl::string_view, std::vector<TString>*, TString*);
+
+template <typename T>
+bool AbslParseFlag(y_absl::string_view text, y_absl::optional<T>* f,
+ TString* err) {
+ if (text.empty()) {
+ *f = y_absl::nullopt;
+ return true;
+ }
+ T value;
+ if (!y_absl::ParseFlag(text, &value, err)) return false;
+
+ *f = std::move(value);
+ return true;
+}
+
+#if defined(Y_ABSL_HAVE_STD_OPTIONAL) && !defined(Y_ABSL_USES_STD_OPTIONAL)
+template <typename T>
+bool AbslParseFlag(y_absl::string_view text, std::optional<T>* f,
+ TString* err) {
+ if (text.empty()) {
+ *f = std::nullopt;
+ return true;
+ }
+ T value;
+ if (!y_absl::ParseFlag(text, &value, err)) return false;
+
+ *f = std::move(value);
+ return true;
+}
+#endif
+
+template <typename T>
+bool InvokeParseFlag(y_absl::string_view input, T* dst, TString* err) {
+ // Comment on next line provides a good compiler error message if T
+ // does not have AbslParseFlag(y_absl::string_view, T*, TString*).
+ return AbslParseFlag(input, dst, err); // Is T missing AbslParseFlag?
+}
+
+// Strings and std:: containers do not have the same overload resolution
+// considerations as fundamental types. Naming these 'AbslUnparseFlag' means we
+// can avoid the need for additional specializations of Unparse (below).
+TString AbslUnparseFlag(y_absl::string_view v);
+TString AbslUnparseFlag(const std::vector<TString>&);
+
+template <typename T>
+TString AbslUnparseFlag(const y_absl::optional<T>& f) {
+ return f.has_value() ? y_absl::UnparseFlag(*f) : "";
+}
+
+#if defined(Y_ABSL_HAVE_STD_OPTIONAL) && !defined(Y_ABSL_USES_STD_OPTIONAL)
+template <typename T>
+TString AbslUnparseFlag(const std::optional<T>& f) {
+ return f.has_value() ? y_absl::UnparseFlag(*f) : "";
+}
+#endif
+
+template <typename T>
+TString Unparse(const T& v) {
+ // Comment on next line provides a good compiler error message if T does not
+ // have UnparseFlag.
+ return AbslUnparseFlag(v); // Is T missing AbslUnparseFlag?
+}
+
+// Overloads for builtin types.
+TString Unparse(bool v);
+TString Unparse(short v); // NOLINT
+TString Unparse(unsigned short v); // NOLINT
+TString Unparse(int v); // NOLINT
+TString Unparse(unsigned int v); // NOLINT
+TString Unparse(long v); // NOLINT
+TString Unparse(unsigned long v); // NOLINT
+TString Unparse(long long v); // NOLINT
+TString Unparse(unsigned long long v); // NOLINT
+TString Unparse(float v);
+TString Unparse(double v);
+
+} // namespace flags_internal
+
+// ParseFlag()
+//
+// Parses a string value into a flag value of type `T`. Do not add overloads of
+// this function for your type directly; instead, add an `AbslParseFlag()`
+// free function as documented above.
+//
+// Some implementations of `AbslParseFlag()` for types which consist of other,
+// constituent types which already have Abseil flag support, may need to call
+// `y_absl::ParseFlag()` on those consituent string values. (See above.)
+template <typename T>
+inline bool ParseFlag(y_absl::string_view input, T* dst, TString* error) {
+ return flags_internal::InvokeParseFlag(input, dst, error);
+}
+
+// UnparseFlag()
+//
+// Unparses a flag value of type `T` into a string value. Do not add overloads
+// of this function for your type directly; instead, add an `AbslUnparseFlag()`
+// free function as documented above.
+//
+// Some implementations of `AbslUnparseFlag()` for types which consist of other,
+// constituent types which already have Abseil flag support, may want to call
+// `y_absl::UnparseFlag()` on those constituent types. (See above.)
+template <typename T>
+inline TString UnparseFlag(const T& v) {
+ return flags_internal::Unparse(v);
+}
+
+// Overloads for `y_absl::LogSeverity` can't (easily) appear alongside that type's
+// definition because it is layered below flags. See proper documentation in
+// base/log_severity.h.
+enum class LogSeverity : int;
+bool AbslParseFlag(y_absl::string_view, y_absl::LogSeverity*, TString*);
+TString AbslUnparseFlag(y_absl::LogSeverity);
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_MARSHALLING_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/parse.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/parse.cc
new file mode 100644
index 0000000000..9eea65e254
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/parse.cc
@@ -0,0 +1,890 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "y_absl/flags/parse.h"
+
+#include <stdlib.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <fstream>
+#include <iostream>
+#include <iterator>
+#include <util/generic/string.h>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "y_absl/algorithm/container.h"
+#include "y_absl/base/attributes.h"
+#include "y_absl/base/config.h"
+#include "y_absl/base/const_init.h"
+#include "y_absl/base/thread_annotations.h"
+#include "y_absl/flags/commandlineflag.h"
+#include "y_absl/flags/config.h"
+#include "y_absl/flags/flag.h"
+#include "y_absl/flags/internal/commandlineflag.h"
+#include "y_absl/flags/internal/flag.h"
+#include "y_absl/flags/internal/parse.h"
+#include "y_absl/flags/internal/private_handle_accessor.h"
+#include "y_absl/flags/internal/program_name.h"
+#include "y_absl/flags/internal/usage.h"
+#include "y_absl/flags/reflection.h"
+#include "y_absl/flags/usage.h"
+#include "y_absl/flags/usage_config.h"
+#include "y_absl/strings/ascii.h"
+#include "y_absl/strings/internal/damerau_levenshtein_distance.h"
+#include "y_absl/strings/str_cat.h"
+#include "y_absl/strings/str_join.h"
+#include "y_absl/strings/string_view.h"
+#include "y_absl/strings/strip.h"
+#include "y_absl/synchronization/mutex.h"
+
+// --------------------------------------------------------------------
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+namespace {
+
+Y_ABSL_CONST_INIT y_absl::Mutex processing_checks_guard(y_absl::kConstInit);
+
+Y_ABSL_CONST_INIT bool flagfile_needs_processing
+ Y_ABSL_GUARDED_BY(processing_checks_guard) = false;
+Y_ABSL_CONST_INIT bool fromenv_needs_processing
+ Y_ABSL_GUARDED_BY(processing_checks_guard) = false;
+Y_ABSL_CONST_INIT bool tryfromenv_needs_processing
+ Y_ABSL_GUARDED_BY(processing_checks_guard) = false;
+
+Y_ABSL_CONST_INIT y_absl::Mutex specified_flags_guard(y_absl::kConstInit);
+Y_ABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags
+ Y_ABSL_GUARDED_BY(specified_flags_guard) = nullptr;
+
+// Suggesting at most kMaxHints flags in case of misspellings.
+Y_ABSL_CONST_INIT const size_t kMaxHints = 100;
+// Suggesting only flags which have a smaller distance than kMaxDistance.
+Y_ABSL_CONST_INIT const size_t kMaxDistance = 3;
+
+struct SpecifiedFlagsCompare {
+ bool operator()(const CommandLineFlag* a, const CommandLineFlag* b) const {
+ return a->Name() < b->Name();
+ }
+ bool operator()(const CommandLineFlag* a, y_absl::string_view b) const {
+ return a->Name() < b;
+ }
+ bool operator()(y_absl::string_view a, const CommandLineFlag* b) const {
+ return a < b->Name();
+ }
+};
+
+} // namespace
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+Y_ABSL_FLAG(std::vector<TString>, flagfile, {},
+ "comma-separated list of files to load flags from")
+ .OnUpdate([]() {
+ if (y_absl::GetFlag(FLAGS_flagfile).empty()) return;
+
+ y_absl::MutexLock l(&y_absl::flags_internal::processing_checks_guard);
+
+ // Setting this flag twice before it is handled most likely an internal
+ // error and should be reviewed by developers.
+ if (y_absl::flags_internal::flagfile_needs_processing) {
+ Y_ABSL_INTERNAL_LOG(WARNING, "flagfile set twice before it is handled");
+ }
+
+ y_absl::flags_internal::flagfile_needs_processing = true;
+ });
+Y_ABSL_FLAG(std::vector<TString>, fromenv, {},
+ "comma-separated list of flags to set from the environment"
+ " [use 'export FLAGS_flag1=value']")
+ .OnUpdate([]() {
+ if (y_absl::GetFlag(FLAGS_fromenv).empty()) return;
+
+ y_absl::MutexLock l(&y_absl::flags_internal::processing_checks_guard);
+
+ // Setting this flag twice before it is handled most likely an internal
+ // error and should be reviewed by developers.
+ if (y_absl::flags_internal::fromenv_needs_processing) {
+ Y_ABSL_INTERNAL_LOG(WARNING, "fromenv set twice before it is handled.");
+ }
+
+ y_absl::flags_internal::fromenv_needs_processing = true;
+ });
+Y_ABSL_FLAG(std::vector<TString>, tryfromenv, {},
+ "comma-separated list of flags to try to set from the environment if "
+ "present")
+ .OnUpdate([]() {
+ if (y_absl::GetFlag(FLAGS_tryfromenv).empty()) return;
+
+ y_absl::MutexLock l(&y_absl::flags_internal::processing_checks_guard);
+
+ // Setting this flag twice before it is handled most likely an internal
+ // error and should be reviewed by developers.
+ if (y_absl::flags_internal::tryfromenv_needs_processing) {
+ Y_ABSL_INTERNAL_LOG(WARNING,
+ "tryfromenv set twice before it is handled.");
+ }
+
+ y_absl::flags_internal::tryfromenv_needs_processing = true;
+ });
+
+Y_ABSL_FLAG(std::vector<TString>, undefok, {},
+ "comma-separated list of flag names that it is okay to specify "
+ "on the command line even if the program does not define a flag "
+ "with that name");
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+namespace {
+
+class ArgsList {
+ public:
+ ArgsList() : next_arg_(0) {}
+ ArgsList(int argc, char* argv[]) : args_(argv, argv + argc), next_arg_(0) {}
+ explicit ArgsList(const std::vector<TString>& args)
+ : args_(args), next_arg_(0) {}
+
+ // Returns success status: true if parsing successful, false otherwise.
+ bool ReadFromFlagfile(const TString& flag_file_name);
+
+ size_t Size() const { return args_.size() - next_arg_; }
+ size_t FrontIndex() const { return next_arg_; }
+ y_absl::string_view Front() const { return args_[next_arg_]; }
+ void PopFront() { next_arg_++; }
+
+ private:
+ std::vector<TString> args_;
+ size_t next_arg_;
+};
+
+bool ArgsList::ReadFromFlagfile(const TString& flag_file_name) {
+ std::ifstream flag_file(flag_file_name);
+
+ if (!flag_file) {
+ flags_internal::ReportUsageError(
+ y_absl::StrCat("Can't open flagfile ", flag_file_name), true);
+
+ return false;
+ }
+
+ // This argument represents fake argv[0], which should be present in all arg
+ // lists.
+ args_.push_back("");
+
+ std::string line;
+ bool success = true;
+
+ while (std::getline(flag_file, line)) {
+ y_absl::string_view stripped = y_absl::StripLeadingAsciiWhitespace(line);
+
+ if (stripped.empty() || stripped[0] == '#') {
+ // Comment or empty line; just ignore.
+ continue;
+ }
+
+ if (stripped[0] == '-') {
+ if (stripped == "--") {
+ flags_internal::ReportUsageError(
+ "Flagfile can't contain position arguments or --", true);
+
+ success = false;
+ break;
+ }
+
+ args_.push_back(TString(stripped));
+ continue;
+ }
+
+ flags_internal::ReportUsageError(
+ y_absl::StrCat("Unexpected line in the flagfile ", flag_file_name, ": ",
+ line),
+ true);
+
+ success = false;
+ }
+
+ return success;
+}
+
+// --------------------------------------------------------------------
+
+// Reads the environment variable with name `name` and stores results in
+// `value`. If variable is not present in environment returns false, otherwise
+// returns true.
+bool GetEnvVar(const char* var_name, TString& var_value) {
+#ifdef _WIN32
+ char buf[1024];
+ auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));
+ if (get_res >= sizeof(buf)) {
+ return false;
+ }
+
+ if (get_res == 0) {
+ return false;
+ }
+
+ var_value = TString(buf, get_res);
+#else
+ const char* val = ::getenv(var_name);
+ if (val == nullptr) {
+ return false;
+ }
+
+ var_value = val;
+#endif
+
+ return true;
+}
+
+// --------------------------------------------------------------------
+
+// Returns:
+// Flag name or empty if arg= --
+// Flag value after = in --flag=value (empty if --foo)
+// "Is empty value" status. True if arg= --foo=, false otherwise. This is
+// required to separate --foo from --foo=.
+// For example:
+// arg return values
+// "--foo=bar" -> {"foo", "bar", false}.
+// "--foo" -> {"foo", "", false}.
+// "--foo=" -> {"foo", "", true}.
+std::tuple<y_absl::string_view, y_absl::string_view, bool> SplitNameAndValue(
+ y_absl::string_view arg) {
+ // Allow -foo and --foo
+ y_absl::ConsumePrefix(&arg, "-");
+
+ if (arg.empty()) {
+ return std::make_tuple("", "", false);
+ }
+
+ auto equal_sign_pos = arg.find("=");
+
+ y_absl::string_view flag_name = arg.substr(0, equal_sign_pos);
+
+ y_absl::string_view value;
+ bool is_empty_value = false;
+
+ if (equal_sign_pos != y_absl::string_view::npos) {
+ value = arg.substr(equal_sign_pos + 1);
+ is_empty_value = value.empty();
+ }
+
+ return std::make_tuple(flag_name, value, is_empty_value);
+}
+
+// --------------------------------------------------------------------
+
+// Returns:
+// found flag or nullptr
+// is negative in case of --nofoo
+std::tuple<CommandLineFlag*, bool> LocateFlag(y_absl::string_view flag_name) {
+ CommandLineFlag* flag = y_absl::FindCommandLineFlag(flag_name);
+ bool is_negative = false;
+
+ if (!flag && y_absl::ConsumePrefix(&flag_name, "no")) {
+ flag = y_absl::FindCommandLineFlag(flag_name);
+ is_negative = true;
+ }
+
+ return std::make_tuple(flag, is_negative);
+}
+
+// --------------------------------------------------------------------
+
+// Verify that default values of typed flags must be convertible to string and
+// back.
+void CheckDefaultValuesParsingRoundtrip() {
+#ifndef NDEBUG
+ flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+ if (flag.IsRetired()) return;
+
+#define Y_ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _) \
+ if (flag.IsOfType<T>()) return;
+
+ Y_ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(Y_ABSL_FLAGS_INTERNAL_IGNORE_TYPE)
+#undef Y_ABSL_FLAGS_INTERNAL_IGNORE_TYPE
+
+ flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
+ flag);
+ });
+#endif
+}
+
+// --------------------------------------------------------------------
+
+// Returns success status, which is true if we successfully read all flag files,
+// in which case new ArgLists are appended to the input_args in a reverse order
+// of file names in the input flagfiles list. This order ensures that flags from
+// the first flagfile in the input list are processed before the second flagfile
+// etc.
+bool ReadFlagfiles(const std::vector<TString>& flagfiles,
+ std::vector<ArgsList>& input_args) {
+ bool success = true;
+ for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) {
+ ArgsList al;
+
+ if (al.ReadFromFlagfile(*it)) {
+ input_args.push_back(al);
+ } else {
+ success = false;
+ }
+ }
+
+ return success;
+}
+
+// Returns success status, which is true if were able to locate all environment
+// variables correctly or if fail_on_absent_in_env is false. The environment
+// variable names are expected to be of the form `FLAGS_<flag_name>`, where
+// `flag_name` is a string from the input flag_names list. If successful we
+// append a single ArgList at the end of the input_args.
+bool ReadFlagsFromEnv(const std::vector<TString>& flag_names,
+ std::vector<ArgsList>& input_args,
+ bool fail_on_absent_in_env) {
+ bool success = true;
+ std::vector<TString> args;
+
+ // This argument represents fake argv[0], which should be present in all arg
+ // lists.
+ args.push_back("");
+
+ for (const auto& flag_name : flag_names) {
+ // Avoid infinite recursion.
+ if (flag_name == "fromenv" || flag_name == "tryfromenv") {
+ flags_internal::ReportUsageError(
+ y_absl::StrCat("Infinite recursion on flag ", flag_name), true);
+
+ success = false;
+ continue;
+ }
+
+ const TString envname = y_absl::StrCat("FLAGS_", flag_name);
+ TString envval;
+ if (!GetEnvVar(envname.c_str(), envval)) {
+ if (fail_on_absent_in_env) {
+ flags_internal::ReportUsageError(
+ y_absl::StrCat(envname, " not found in environment"), true);
+
+ success = false;
+ }
+
+ continue;
+ }
+
+ args.push_back(y_absl::StrCat("--", flag_name, "=", envval));
+ }
+
+ if (success) {
+ input_args.emplace_back(args);
+ }
+
+ return success;
+}
+
+// --------------------------------------------------------------------
+
+// Returns success status, which is true if were able to handle all generator
+// flags (flagfile, fromenv, tryfromemv) successfully.
+bool HandleGeneratorFlags(std::vector<ArgsList>& input_args,
+ std::vector<TString>& flagfile_value) {
+ bool success = true;
+
+ y_absl::MutexLock l(&flags_internal::processing_checks_guard);
+
+ // flagfile could have been set either on a command line or
+ // programmatically before invoking ParseCommandLine. Note that we do not
+ // actually process arguments specified in the flagfile, but instead
+ // create a secondary arguments list to be processed along with the rest
+ // of the comamnd line arguments. Since we always the process most recently
+ // created list of arguments first, this will result in flagfile argument
+ // being processed before any other argument in the command line. If
+ // FLAGS_flagfile contains more than one file name we create multiple new
+ // levels of arguments in a reverse order of file names. Thus we always
+ // process arguments from first file before arguments containing in a
+ // second file, etc. If flagfile contains another
+ // --flagfile inside of it, it will produce new level of arguments and
+ // processed before the rest of the flagfile. We are also collecting all
+ // flagfiles set on original command line. Unlike the rest of the flags,
+ // this flag can be set multiple times and is expected to be handled
+ // multiple times. We are collecting them all into a single list and set
+ // the value of FLAGS_flagfile to that value at the end of the parsing.
+ if (flags_internal::flagfile_needs_processing) {
+ auto flagfiles = y_absl::GetFlag(FLAGS_flagfile);
+
+ if (input_args.size() == 1) {
+ flagfile_value.insert(flagfile_value.end(), flagfiles.begin(),
+ flagfiles.end());
+ }
+
+ success &= ReadFlagfiles(flagfiles, input_args);
+
+ flags_internal::flagfile_needs_processing = false;
+ }
+
+ // Similar to flagfile fromenv/tryfromemv can be set both
+ // programmatically and at runtime on a command line. Unlike flagfile these
+ // can't be recursive.
+ if (flags_internal::fromenv_needs_processing) {
+ auto flags_list = y_absl::GetFlag(FLAGS_fromenv);
+
+ success &= ReadFlagsFromEnv(flags_list, input_args, true);
+
+ flags_internal::fromenv_needs_processing = false;
+ }
+
+ if (flags_internal::tryfromenv_needs_processing) {
+ auto flags_list = y_absl::GetFlag(FLAGS_tryfromenv);
+
+ success &= ReadFlagsFromEnv(flags_list, input_args, false);
+
+ flags_internal::tryfromenv_needs_processing = false;
+ }
+
+ return success;
+}
+
+// --------------------------------------------------------------------
+
+void ResetGeneratorFlags(const std::vector<TString>& flagfile_value) {
+ // Setting flagfile to the value which collates all the values set on a
+ // command line and programmatically. So if command line looked like
+ // --flagfile=f1 --flagfile=f2 the final value of the FLAGS_flagfile flag is
+ // going to be {"f1", "f2"}
+ if (!flagfile_value.empty()) {
+ y_absl::SetFlag(&FLAGS_flagfile, flagfile_value);
+ y_absl::MutexLock l(&flags_internal::processing_checks_guard);
+ flags_internal::flagfile_needs_processing = false;
+ }
+
+ // fromenv/tryfromenv are set to <undefined> value.
+ if (!y_absl::GetFlag(FLAGS_fromenv).empty()) {
+ y_absl::SetFlag(&FLAGS_fromenv, {});
+ }
+ if (!y_absl::GetFlag(FLAGS_tryfromenv).empty()) {
+ y_absl::SetFlag(&FLAGS_tryfromenv, {});
+ }
+
+ y_absl::MutexLock l(&flags_internal::processing_checks_guard);
+ flags_internal::fromenv_needs_processing = false;
+ flags_internal::tryfromenv_needs_processing = false;
+}
+
+// --------------------------------------------------------------------
+
+// Returns:
+// success status
+// deduced value
+// We are also mutating curr_list in case if we need to get a hold of next
+// argument in the input.
+std::tuple<bool, y_absl::string_view> DeduceFlagValue(const CommandLineFlag& flag,
+ y_absl::string_view value,
+ bool is_negative,
+ bool is_empty_value,
+ ArgsList* curr_list) {
+ // Value is either an argument suffix after `=` in "--foo=<value>"
+ // or separate argument in case of "--foo" "<value>".
+
+ // boolean flags have these forms:
+ // --foo
+ // --nofoo
+ // --foo=true
+ // --foo=false
+ // --nofoo=<value> is not supported
+ // --foo <value> is not supported
+
+ // non boolean flags have these forms:
+ // --foo=<value>
+ // --foo <value>
+ // --nofoo is not supported
+
+ if (flag.IsOfType<bool>()) {
+ if (value.empty()) {
+ if (is_empty_value) {
+ // "--bool_flag=" case
+ flags_internal::ReportUsageError(
+ y_absl::StrCat(
+ "Missing the value after assignment for the boolean flag '",
+ flag.Name(), "'"),
+ true);
+ return std::make_tuple(false, "");
+ }
+
+ // "--bool_flag" case
+ value = is_negative ? "0" : "1";
+ } else if (is_negative) {
+ // "--nobool_flag=Y" case
+ flags_internal::ReportUsageError(
+ y_absl::StrCat("Negative form with assignment is not valid for the "
+ "boolean flag '",
+ flag.Name(), "'"),
+ true);
+ return std::make_tuple(false, "");
+ }
+ } else if (is_negative) {
+ // "--noint_flag=1" case
+ flags_internal::ReportUsageError(
+ y_absl::StrCat("Negative form is not valid for the flag '", flag.Name(),
+ "'"),
+ true);
+ return std::make_tuple(false, "");
+ } else if (value.empty() && (!is_empty_value)) {
+ if (curr_list->Size() == 1) {
+ // "--int_flag" case
+ flags_internal::ReportUsageError(
+ y_absl::StrCat("Missing the value for the flag '", flag.Name(), "'"),
+ true);
+ return std::make_tuple(false, "");
+ }
+
+ // "--int_flag" "10" case
+ curr_list->PopFront();
+ value = curr_list->Front();
+
+ // Heuristic to detect the case where someone treats a string arg
+ // like a bool or just forgets to pass a value:
+ // --my_string_var --foo=bar
+ // We look for a flag of string type, whose value begins with a
+ // dash and corresponds to known flag or standalone --.
+ if (!value.empty() && value[0] == '-' && flag.IsOfType<TString>()) {
+ auto maybe_flag_name = std::get<0>(SplitNameAndValue(value.substr(1)));
+
+ if (maybe_flag_name.empty() ||
+ std::get<0>(LocateFlag(maybe_flag_name)) != nullptr) {
+ // "--string_flag" "--known_flag" case
+ Y_ABSL_INTERNAL_LOG(
+ WARNING,
+ y_absl::StrCat("Did you really mean to set flag '", flag.Name(),
+ "' to the value '", value, "'?"));
+ }
+ }
+ }
+
+ return std::make_tuple(true, value);
+}
+
+// --------------------------------------------------------------------
+
+bool CanIgnoreUndefinedFlag(y_absl::string_view flag_name) {
+ auto undefok = y_absl::GetFlag(FLAGS_undefok);
+ if (std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
+ return true;
+ }
+
+ if (y_absl::ConsumePrefix(&flag_name, "no") &&
+ std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace
+
+// --------------------------------------------------------------------
+
+bool WasPresentOnCommandLine(y_absl::string_view flag_name) {
+ y_absl::MutexLock l(&specified_flags_guard);
+ Y_ABSL_INTERNAL_CHECK(specified_flags != nullptr,
+ "ParseCommandLine is not invoked yet");
+
+ return std::binary_search(specified_flags->begin(), specified_flags->end(),
+ flag_name, SpecifiedFlagsCompare{});
+}
+
+// --------------------------------------------------------------------
+
+struct BestHints {
+ explicit BestHints(uint8_t _max) : best_distance(_max + 1) {}
+ bool AddHint(y_absl::string_view hint, uint8_t distance) {
+ if (hints.size() >= kMaxHints) return false;
+ if (distance == best_distance) {
+ hints.emplace_back(hint);
+ }
+ if (distance < best_distance) {
+ best_distance = distance;
+ hints = std::vector<TString>{TString(hint)};
+ }
+ return true;
+ }
+
+ uint8_t best_distance;
+ std::vector<TString> hints;
+};
+
+// Return the list of flags with the smallest Damerau-Levenshtein distance to
+// the given flag.
+std::vector<TString> GetMisspellingHints(const y_absl::string_view flag) {
+ const size_t maxCutoff = std::min(flag.size() / 2 + 1, kMaxDistance);
+ auto undefok = y_absl::GetFlag(FLAGS_undefok);
+ BestHints best_hints(static_cast<uint8_t>(maxCutoff));
+ y_absl::flags_internal::ForEachFlag([&](const CommandLineFlag& f) {
+ if (best_hints.hints.size() >= kMaxHints) return;
+ uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance(
+ flag, f.Name(), best_hints.best_distance);
+ best_hints.AddHint(f.Name(), distance);
+ // For boolean flags, also calculate distance to the negated form.
+ if (f.IsOfType<bool>()) {
+ const TString negated_flag = y_absl::StrCat("no", f.Name());
+ distance = strings_internal::CappedDamerauLevenshteinDistance(
+ flag, negated_flag, best_hints.best_distance);
+ best_hints.AddHint(negated_flag, distance);
+ }
+ });
+ // Finally calculate distance to flags in "undefok".
+ y_absl::c_for_each(undefok, [&](const y_absl::string_view f) {
+ if (best_hints.hints.size() >= kMaxHints) return;
+ uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance(
+ flag, f, best_hints.best_distance);
+ best_hints.AddHint(y_absl::StrCat(f, " (undefok)"), distance);
+ });
+ return best_hints.hints;
+}
+
+// --------------------------------------------------------------------
+
+std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
+ ArgvListAction arg_list_act,
+ UsageFlagsAction usage_flag_act,
+ OnUndefinedFlag on_undef_flag) {
+ Y_ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
+
+ // Once parsing has started we will not have more flag registrations.
+ // If we did, they would be missing during parsing, which is a problem on
+ // itself.
+ flags_internal::FinalizeRegistry();
+
+ // This routine does not return anything since we abort on failure.
+ CheckDefaultValuesParsingRoundtrip();
+
+ std::vector<TString> flagfile_value;
+
+ std::vector<ArgsList> input_args;
+ input_args.push_back(ArgsList(argc, argv));
+
+ std::vector<char*> output_args;
+ std::vector<char*> positional_args;
+ output_args.reserve(static_cast<size_t>(argc));
+
+ // This is the list of undefined flags. The element of the list is the pair
+ // consisting of boolean indicating if flag came from command line (vs from
+ // some flag file we've read) and flag name.
+ // TODO(rogeeff): Eliminate the first element in the pair after cleanup.
+ std::vector<std::pair<bool, TString>> undefined_flag_names;
+
+ // Set program invocation name if it is not set before.
+ if (ProgramInvocationName() == "UNKNOWN") {
+ flags_internal::SetProgramInvocationName(argv[0]);
+ }
+ output_args.push_back(argv[0]);
+
+ y_absl::MutexLock l(&specified_flags_guard);
+ if (specified_flags == nullptr) {
+ specified_flags = new std::vector<const CommandLineFlag*>;
+ } else {
+ specified_flags->clear();
+ }
+
+ // Iterate through the list of the input arguments. First level are arguments
+ // originated from argc/argv. Following levels are arguments originated from
+ // recursive parsing of flagfile(s).
+ bool success = true;
+ while (!input_args.empty()) {
+ // 10. First we process the built-in generator flags.
+ success &= HandleGeneratorFlags(input_args, flagfile_value);
+
+ // 30. Select top-most (most recent) arguments list. If it is empty drop it
+ // and re-try.
+ ArgsList& curr_list = input_args.back();
+
+ curr_list.PopFront();
+
+ if (curr_list.Size() == 0) {
+ input_args.pop_back();
+ continue;
+ }
+
+ // 40. Pick up the front remaining argument in the current list. If current
+ // stack of argument lists contains only one element - we are processing an
+ // argument from the original argv.
+ y_absl::string_view arg(curr_list.Front());
+ bool arg_from_argv = input_args.size() == 1;
+
+ // 50. If argument does not start with - or is just "-" - this is
+ // positional argument.
+ if (!y_absl::ConsumePrefix(&arg, "-") || arg.empty()) {
+ Y_ABSL_INTERNAL_CHECK(arg_from_argv,
+ "Flagfile cannot contain positional argument");
+
+ positional_args.push_back(argv[curr_list.FrontIndex()]);
+ continue;
+ }
+
+ if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs)) {
+ output_args.push_back(argv[curr_list.FrontIndex()]);
+ }
+
+ // 60. Split the current argument on '=' to figure out the argument
+ // name and value. If flag name is empty it means we've got "--". value
+ // can be empty either if there were no '=' in argument string at all or
+ // an argument looked like "--foo=". In a latter case is_empty_value is
+ // true.
+ y_absl::string_view flag_name;
+ y_absl::string_view value;
+ bool is_empty_value = false;
+
+ std::tie(flag_name, value, is_empty_value) = SplitNameAndValue(arg);
+
+ // 70. "--" alone means what it does for GNU: stop flags parsing. We do
+ // not support positional arguments in flagfiles, so we just drop them.
+ if (flag_name.empty()) {
+ Y_ABSL_INTERNAL_CHECK(arg_from_argv,
+ "Flagfile cannot contain positional argument");
+
+ curr_list.PopFront();
+ break;
+ }
+
+ // 80. Locate the flag based on flag name. Handle both --foo and --nofoo
+ CommandLineFlag* flag = nullptr;
+ bool is_negative = false;
+ std::tie(flag, is_negative) = LocateFlag(flag_name);
+
+ if (flag == nullptr) {
+ // Usage flags are not modeled as Abseil flags. Locate them separately.
+ if (flags_internal::DeduceUsageFlags(flag_name, value)) {
+ continue;
+ }
+
+ if (on_undef_flag != OnUndefinedFlag::kIgnoreUndefined) {
+ undefined_flag_names.emplace_back(arg_from_argv,
+ TString(flag_name));
+ }
+ continue;
+ }
+
+ // 90. Deduce flag's value (from this or next argument)
+ auto curr_index = curr_list.FrontIndex();
+ bool value_success = true;
+ std::tie(value_success, value) =
+ DeduceFlagValue(*flag, value, is_negative, is_empty_value, &curr_list);
+ success &= value_success;
+
+ // If above call consumed an argument, it was a standalone value
+ if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs) &&
+ (curr_index != curr_list.FrontIndex())) {
+ output_args.push_back(argv[curr_list.FrontIndex()]);
+ }
+
+ // 100. Set the located flag to a new new value, unless it is retired.
+ // Setting retired flag fails, but we ignoring it here while also reporting
+ // access to retired flag.
+ TString error;
+ if (!flags_internal::PrivateHandleAccessor::ParseFrom(
+ *flag, value, SET_FLAGS_VALUE, kCommandLine, error)) {
+ if (flag->IsRetired()) continue;
+
+ flags_internal::ReportUsageError(error, true);
+ success = false;
+ } else {
+ specified_flags->push_back(flag);
+ }
+ }
+
+ for (const auto& flag_name : undefined_flag_names) {
+ if (CanIgnoreUndefinedFlag(flag_name.second)) continue;
+ // Verify if flag_name has the "no" already removed
+ std::vector<TString> flags;
+ if (flag_name.first) flags = GetMisspellingHints(flag_name.second);
+ if (flags.empty()) {
+ flags_internal::ReportUsageError(
+ y_absl::StrCat("Unknown command line flag '", flag_name.second, "'"),
+ true);
+ } else {
+ flags_internal::ReportUsageError(
+ y_absl::StrCat("Unknown command line flag '", flag_name.second,
+ "'. Did you mean: ", y_absl::StrJoin(flags, ", "), " ?"),
+ true);
+ }
+
+ success = false;
+ }
+
+#if Y_ABSL_FLAGS_STRIP_NAMES
+ if (!success) {
+ flags_internal::ReportUsageError(
+ "NOTE: command line flags are disabled in this build", true);
+ }
+#endif
+
+ if (!success) {
+ flags_internal::HandleUsageFlags(std::cout,
+ ProgramUsageMessage());
+ std::exit(1);
+ }
+
+ if (usage_flag_act == UsageFlagsAction::kHandleUsage) {
+ int exit_code = flags_internal::HandleUsageFlags(
+ std::cout, ProgramUsageMessage());
+
+ if (exit_code != -1) {
+ std::exit(exit_code);
+ }
+ }
+
+ ResetGeneratorFlags(flagfile_value);
+
+ // Reinstate positional args which were intermixed with flags in the arguments
+ // list.
+ for (auto arg : positional_args) {
+ output_args.push_back(arg);
+ }
+
+ // All the remaining arguments are positional.
+ if (!input_args.empty()) {
+ for (size_t arg_index = input_args.back().FrontIndex();
+ arg_index < static_cast<size_t>(argc); ++arg_index) {
+ output_args.push_back(argv[arg_index]);
+ }
+ }
+
+ // Trim and sort the vector.
+ specified_flags->shrink_to_fit();
+ std::sort(specified_flags->begin(), specified_flags->end(),
+ SpecifiedFlagsCompare{});
+ return output_args;
+}
+
+} // namespace flags_internal
+
+// --------------------------------------------------------------------
+
+std::vector<char*> ParseCommandLine(int argc, char* argv[]) {
+ return flags_internal::ParseCommandLineImpl(
+ argc, argv, flags_internal::ArgvListAction::kRemoveParsedArgs,
+ flags_internal::UsageFlagsAction::kHandleUsage,
+ flags_internal::OnUndefinedFlag::kAbortIfUndefined);
+}
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/parse.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/parse.h
new file mode 100644
index 0000000000..c8ee5b21d3
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/parse.h
@@ -0,0 +1,60 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: parse.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the main parsing function for Abseil flags:
+// `y_absl::ParseCommandLine()`.
+
+#ifndef Y_ABSL_FLAGS_PARSE_H_
+#define Y_ABSL_FLAGS_PARSE_H_
+
+#include <vector>
+
+#include "y_absl/base/config.h"
+#include "y_absl/flags/internal/parse.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+
+// ParseCommandLine()
+//
+// Parses the set of command-line arguments passed in the `argc` (argument
+// count) and `argv[]` (argument vector) parameters from `main()`, assigning
+// values to any defined Abseil flags. (Any arguments passed after the
+// flag-terminating delimiter (`--`) are treated as positional arguments and
+// ignored.)
+//
+// Any command-line flags (and arguments to those flags) are parsed into Abseil
+// Flag values, if those flags are defined. Any undefined flags will either
+// return an error, or be ignored if that flag is designated using `undefok` to
+// indicate "undefined is OK."
+//
+// Any command-line positional arguments not part of any command-line flag (or
+// arguments to a flag) are returned in a vector, with the program invocation
+// name at position 0 of that vector. (Note that this includes positional
+// arguments after the flag-terminating delimiter `--`.)
+//
+// After all flags and flag arguments are parsed, this function looks for any
+// built-in usage flags (e.g. `--help`), and if any were specified, it reports
+// help messages and then exits the program.
+std::vector<char*> ParseCommandLine(int argc, char* argv[]);
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_PARSE_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/reflection.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/reflection.cc
new file mode 100644
index 0000000000..8776612249
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/reflection.cc
@@ -0,0 +1,354 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "y_absl/flags/reflection.h"
+
+#include <assert.h>
+
+#include <atomic>
+#include <util/generic/string.h>
+
+#include "y_absl/base/config.h"
+#include "y_absl/base/thread_annotations.h"
+#include "y_absl/container/flat_hash_map.h"
+#include "y_absl/flags/commandlineflag.h"
+#include "y_absl/flags/internal/private_handle_accessor.h"
+#include "y_absl/flags/internal/registry.h"
+#include "y_absl/flags/usage_config.h"
+#include "y_absl/strings/str_cat.h"
+#include "y_absl/strings/string_view.h"
+#include "y_absl/synchronization/mutex.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// --------------------------------------------------------------------
+// FlagRegistry
+// A FlagRegistry singleton object holds all flag objects indexed by their
+// names so that if you know a flag's name, you can access or set it. If the
+// function is named FooLocked(), you must own the registry lock before
+// calling the function; otherwise, you should *not* hold the lock, and the
+// function will acquire it itself if needed.
+// --------------------------------------------------------------------
+
+class FlagRegistry {
+ public:
+ FlagRegistry() = default;
+ ~FlagRegistry() = default;
+
+ // Store a flag in this registry. Takes ownership of *flag.
+ void RegisterFlag(CommandLineFlag& flag, const char* filename);
+
+ void Lock() Y_ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); }
+ void Unlock() Y_ABSL_UNLOCK_FUNCTION(lock_) { lock_.Unlock(); }
+
+ // Returns the flag object for the specified name, or nullptr if not found.
+ // Will emit a warning if a 'retired' flag is specified.
+ CommandLineFlag* FindFlag(y_absl::string_view name);
+
+ static FlagRegistry& GlobalRegistry(); // returns a singleton registry
+
+ private:
+ friend class flags_internal::FlagSaverImpl; // reads all the flags in order
+ // to copy them
+ friend void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
+ friend void FinalizeRegistry();
+
+ // The map from name to flag, for FindFlag().
+ using FlagMap = y_absl::flat_hash_map<y_absl::string_view, CommandLineFlag*>;
+ using FlagIterator = FlagMap::iterator;
+ using FlagConstIterator = FlagMap::const_iterator;
+ FlagMap flags_;
+ std::vector<CommandLineFlag*> flat_flags_;
+ std::atomic<bool> finalized_flags_{false};
+
+ y_absl::Mutex lock_;
+
+ // Disallow
+ FlagRegistry(const FlagRegistry&);
+ FlagRegistry& operator=(const FlagRegistry&);
+};
+
+namespace {
+
+class FlagRegistryLock {
+ public:
+ explicit FlagRegistryLock(FlagRegistry& fr) : fr_(fr) { fr_.Lock(); }
+ ~FlagRegistryLock() { fr_.Unlock(); }
+
+ private:
+ FlagRegistry& fr_;
+};
+
+} // namespace
+
+CommandLineFlag* FlagRegistry::FindFlag(y_absl::string_view name) {
+ if (finalized_flags_.load(std::memory_order_acquire)) {
+ // We could save some gcus here if we make `Name()` be non-virtual.
+ // We could move the `const char*` name to the base class.
+ auto it = std::partition_point(
+ flat_flags_.begin(), flat_flags_.end(),
+ [=](CommandLineFlag* f) { return f->Name() < name; });
+ if (it != flat_flags_.end() && (*it)->Name() == name) return *it;
+ }
+
+ FlagRegistryLock frl(*this);
+ auto it = flags_.find(name);
+ return it != flags_.end() ? it->second : nullptr;
+}
+
+void FlagRegistry::RegisterFlag(CommandLineFlag& flag, const char* filename) {
+ if (filename != nullptr &&
+ flag.Filename() != GetUsageConfig().normalize_filename(filename)) {
+ flags_internal::ReportUsageError(
+ y_absl::StrCat(
+ "Inconsistency between flag object and registration for flag '",
+ flag.Name(),
+ "', likely due to duplicate flags or an ODR violation. Relevant "
+ "files: ",
+ flag.Filename(), " and ", filename),
+ true);
+ std::exit(1);
+ }
+
+ FlagRegistryLock registry_lock(*this);
+
+ std::pair<FlagIterator, bool> ins =
+ flags_.insert(FlagMap::value_type(flag.Name(), &flag));
+ if (ins.second == false) { // means the name was already in the map
+ CommandLineFlag& old_flag = *ins.first->second;
+ if (flag.IsRetired() != old_flag.IsRetired()) {
+ // All registrations must agree on the 'retired' flag.
+ flags_internal::ReportUsageError(
+ y_absl::StrCat(
+ "Retired flag '", flag.Name(), "' was defined normally in file '",
+ (flag.IsRetired() ? old_flag.Filename() : flag.Filename()), "'."),
+ true);
+ } else if (flags_internal::PrivateHandleAccessor::TypeId(flag) !=
+ flags_internal::PrivateHandleAccessor::TypeId(old_flag)) {
+ flags_internal::ReportUsageError(
+ y_absl::StrCat("Flag '", flag.Name(),
+ "' was defined more than once but with "
+ "differing types. Defined in files '",
+ old_flag.Filename(), "' and '", flag.Filename(), "'."),
+ true);
+ } else if (old_flag.IsRetired()) {
+ return;
+ } else if (old_flag.Filename() != flag.Filename()) {
+ flags_internal::ReportUsageError(
+ y_absl::StrCat("Flag '", flag.Name(),
+ "' was defined more than once (in files '",
+ old_flag.Filename(), "' and '", flag.Filename(), "')."),
+ true);
+ } else {
+ flags_internal::ReportUsageError(
+ y_absl::StrCat(
+ "Something is wrong with flag '", flag.Name(), "' in file '",
+ flag.Filename(), "'. One possibility: file '", flag.Filename(),
+ "' is being linked both statically and dynamically into this "
+ "executable. e.g. some files listed as srcs to a test and also "
+ "listed as srcs of some shared lib deps of the same test."),
+ true);
+ }
+ // All cases above are fatal, except for the retired flags.
+ std::exit(1);
+ }
+}
+
+FlagRegistry& FlagRegistry::GlobalRegistry() {
+ static FlagRegistry* global_registry = new FlagRegistry;
+ return *global_registry;
+}
+
+// --------------------------------------------------------------------
+
+void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) {
+ FlagRegistry& registry = FlagRegistry::GlobalRegistry();
+
+ if (registry.finalized_flags_.load(std::memory_order_acquire)) {
+ for (const auto& i : registry.flat_flags_) visitor(*i);
+ }
+
+ FlagRegistryLock frl(registry);
+ for (const auto& i : registry.flags_) visitor(*i.second);
+}
+
+// --------------------------------------------------------------------
+
+bool RegisterCommandLineFlag(CommandLineFlag& flag, const char* filename) {
+ FlagRegistry::GlobalRegistry().RegisterFlag(flag, filename);
+ return true;
+}
+
+void FinalizeRegistry() {
+ auto& registry = FlagRegistry::GlobalRegistry();
+ FlagRegistryLock frl(registry);
+ if (registry.finalized_flags_.load(std::memory_order_relaxed)) {
+ // Was already finalized. Ignore the second time.
+ return;
+ }
+ registry.flat_flags_.reserve(registry.flags_.size());
+ for (const auto& f : registry.flags_) {
+ registry.flat_flags_.push_back(f.second);
+ }
+ std::sort(std::begin(registry.flat_flags_), std::end(registry.flat_flags_),
+ [](const CommandLineFlag* lhs, const CommandLineFlag* rhs) {
+ return lhs->Name() < rhs->Name();
+ });
+ registry.flags_.clear();
+ registry.finalized_flags_.store(true, std::memory_order_release);
+}
+
+// --------------------------------------------------------------------
+
+namespace {
+
+class RetiredFlagObj final : public CommandLineFlag {
+ public:
+ constexpr RetiredFlagObj(const char* name, FlagFastTypeId type_id)
+ : name_(name), type_id_(type_id) {}
+
+ private:
+ y_absl::string_view Name() const override { return name_; }
+ TString Filename() const override {
+ OnAccess();
+ return "RETIRED";
+ }
+ FlagFastTypeId TypeId() const override { return type_id_; }
+ TString Help() const override {
+ OnAccess();
+ return "";
+ }
+ bool IsRetired() const override { return true; }
+ bool IsSpecifiedOnCommandLine() const override {
+ OnAccess();
+ return false;
+ }
+ TString DefaultValue() const override {
+ OnAccess();
+ return "";
+ }
+ TString CurrentValue() const override {
+ OnAccess();
+ return "";
+ }
+
+ // Any input is valid
+ bool ValidateInputValue(y_absl::string_view) const override {
+ OnAccess();
+ return true;
+ }
+
+ std::unique_ptr<flags_internal::FlagStateInterface> SaveState() override {
+ return nullptr;
+ }
+
+ bool ParseFrom(y_absl::string_view, flags_internal::FlagSettingMode,
+ flags_internal::ValueSource, TString&) override {
+ OnAccess();
+ return false;
+ }
+
+ void CheckDefaultValueParsingRoundtrip() const override { OnAccess(); }
+
+ void Read(void*) const override { OnAccess(); }
+
+ void OnAccess() const {
+ flags_internal::ReportUsageError(
+ y_absl::StrCat("Accessing retired flag '", name_, "'"), false);
+ }
+
+ // Data members
+ const char* const name_;
+ const FlagFastTypeId type_id_;
+};
+
+} // namespace
+
+void Retire(const char* name, FlagFastTypeId type_id, char* buf) {
+ static_assert(sizeof(RetiredFlagObj) == kRetiredFlagObjSize, "");
+ static_assert(alignof(RetiredFlagObj) == kRetiredFlagObjAlignment, "");
+ auto* flag = ::new (static_cast<void*>(buf))
+ flags_internal::RetiredFlagObj(name, type_id);
+ FlagRegistry::GlobalRegistry().RegisterFlag(*flag, nullptr);
+}
+
+// --------------------------------------------------------------------
+
+class FlagSaverImpl {
+ public:
+ FlagSaverImpl() = default;
+ FlagSaverImpl(const FlagSaverImpl&) = delete;
+ void operator=(const FlagSaverImpl&) = delete;
+
+ // Saves the flag states from the flag registry into this object.
+ // It's an error to call this more than once.
+ void SaveFromRegistry() {
+ assert(backup_registry_.empty()); // call only once!
+ flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+ if (auto flag_state =
+ flags_internal::PrivateHandleAccessor::SaveState(flag)) {
+ backup_registry_.emplace_back(std::move(flag_state));
+ }
+ });
+ }
+
+ // Restores the saved flag states into the flag registry.
+ void RestoreToRegistry() {
+ for (const auto& flag_state : backup_registry_) {
+ flag_state->Restore();
+ }
+ }
+
+ private:
+ std::vector<std::unique_ptr<flags_internal::FlagStateInterface>>
+ backup_registry_;
+};
+
+} // namespace flags_internal
+
+FlagSaver::FlagSaver() : impl_(new flags_internal::FlagSaverImpl) {
+ impl_->SaveFromRegistry();
+}
+
+FlagSaver::~FlagSaver() {
+ if (!impl_) return;
+
+ impl_->RestoreToRegistry();
+ delete impl_;
+}
+
+// --------------------------------------------------------------------
+
+CommandLineFlag* FindCommandLineFlag(y_absl::string_view name) {
+ if (name.empty()) return nullptr;
+ flags_internal::FlagRegistry& registry =
+ flags_internal::FlagRegistry::GlobalRegistry();
+ return registry.FindFlag(name);
+}
+
+// --------------------------------------------------------------------
+
+y_absl::flat_hash_map<y_absl::string_view, y_absl::CommandLineFlag*> GetAllFlags() {
+ y_absl::flat_hash_map<y_absl::string_view, y_absl::CommandLineFlag*> res;
+ flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+ if (!flag.IsRetired()) res.insert({flag.Name(), &flag});
+ });
+ return res;
+}
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/reflection.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/reflection.h
new file mode 100644
index 0000000000..d2456590da
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/reflection.h
@@ -0,0 +1,90 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: reflection.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the routines to access and operate on an Abseil Flag's
+// reflection handle.
+
+#ifndef Y_ABSL_FLAGS_REFLECTION_H_
+#define Y_ABSL_FLAGS_REFLECTION_H_
+
+#include <util/generic/string.h>
+
+#include "y_absl/base/config.h"
+#include "y_absl/container/flat_hash_map.h"
+#include "y_absl/flags/commandlineflag.h"
+#include "y_absl/flags/internal/commandlineflag.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+class FlagSaverImpl;
+} // namespace flags_internal
+
+// FindCommandLineFlag()
+//
+// Returns the reflection handle of an Abseil flag of the specified name, or
+// `nullptr` if not found. This function will emit a warning if the name of a
+// 'retired' flag is specified.
+y_absl::CommandLineFlag* FindCommandLineFlag(y_absl::string_view name);
+
+// Returns current state of the Flags registry in a form of mapping from flag
+// name to a flag reflection handle.
+y_absl::flat_hash_map<y_absl::string_view, y_absl::CommandLineFlag*> GetAllFlags();
+
+//------------------------------------------------------------------------------
+// FlagSaver
+//------------------------------------------------------------------------------
+//
+// A FlagSaver object stores the state of flags in the scope where the FlagSaver
+// is defined, allowing modification of those flags within that scope and
+// automatic restoration of the flags to their previous state upon leaving the
+// scope.
+//
+// A FlagSaver can be used within tests to temporarily change the test
+// environment and restore the test case to its previous state.
+//
+// Example:
+//
+// void MyFunc() {
+// y_absl::FlagSaver fs;
+// ...
+// y_absl::SetFlag(&FLAGS_myFlag, otherValue);
+// ...
+// } // scope of FlagSaver left, flags return to previous state
+//
+// This class is thread-safe.
+
+class FlagSaver {
+ public:
+ FlagSaver();
+ ~FlagSaver();
+
+ FlagSaver(const FlagSaver&) = delete;
+ void operator=(const FlagSaver&) = delete;
+
+ private:
+ flags_internal::FlagSaverImpl* impl_;
+};
+
+//-----------------------------------------------------------------------------
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_REFLECTION_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage.cc
new file mode 100644
index 0000000000..495bd01fa3
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage.cc
@@ -0,0 +1,65 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "y_absl/flags/usage.h"
+
+#include <stdlib.h>
+
+#include <util/generic/string.h>
+
+#include "y_absl/base/attributes.h"
+#include "y_absl/base/config.h"
+#include "y_absl/base/const_init.h"
+#include "y_absl/base/thread_annotations.h"
+#include "y_absl/flags/internal/usage.h"
+#include "y_absl/strings/string_view.h"
+#include "y_absl/synchronization/mutex.h"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+namespace {
+Y_ABSL_CONST_INIT y_absl::Mutex usage_message_guard(y_absl::kConstInit);
+Y_ABSL_CONST_INIT TString* program_usage_message
+ Y_ABSL_GUARDED_BY(usage_message_guard) = nullptr;
+} // namespace
+} // namespace flags_internal
+
+// --------------------------------------------------------------------
+// Sets the "usage" message to be used by help reporting routines.
+void SetProgramUsageMessage(y_absl::string_view new_usage_message) {
+ y_absl::MutexLock l(&flags_internal::usage_message_guard);
+
+ if (flags_internal::program_usage_message != nullptr) {
+ Y_ABSL_INTERNAL_LOG(FATAL, "SetProgramUsageMessage() called twice.");
+ std::exit(1);
+ }
+
+ flags_internal::program_usage_message = new TString(new_usage_message);
+}
+
+// --------------------------------------------------------------------
+// Returns the usage message set by SetProgramUsageMessage().
+// Note: We able to return string_view here only because calling
+// SetProgramUsageMessage twice is prohibited.
+y_absl::string_view ProgramUsageMessage() {
+ y_absl::MutexLock l(&flags_internal::usage_message_guard);
+
+ return flags_internal::program_usage_message != nullptr
+ ? y_absl::string_view(*flags_internal::program_usage_message)
+ : "Warning: SetProgramUsageMessage() never called";
+}
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage.h
new file mode 100644
index 0000000000..8ce0f1195f
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage.h
@@ -0,0 +1,43 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef Y_ABSL_FLAGS_USAGE_H_
+#define Y_ABSL_FLAGS_USAGE_H_
+
+#include "y_absl/base/config.h"
+#include "y_absl/strings/string_view.h"
+
+// --------------------------------------------------------------------
+// Usage reporting interfaces
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+
+// Sets the "usage" message to be used by help reporting routines.
+// For example:
+// y_absl::SetProgramUsageMessage(
+// y_absl::StrCat("This program does nothing. Sample usage:\n", argv[0],
+// " <uselessarg1> <uselessarg2>"));
+// Do not include commandline flags in the usage: we do that for you!
+// Note: Calling SetProgramUsageMessage twice will trigger a call to std::exit.
+void SetProgramUsageMessage(y_absl::string_view new_usage_message);
+
+// Returns the usage message set by SetProgramUsageMessage().
+y_absl::string_view ProgramUsageMessage();
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+#endif // Y_ABSL_FLAGS_USAGE_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage_config.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage_config.cc
new file mode 100644
index 0000000000..c6cf8296d6
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage_config.cc
@@ -0,0 +1,165 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "y_absl/flags/usage_config.h"
+
+#include <functional>
+#include <iostream>
+#include <util/generic/string.h>
+
+#include "y_absl/base/attributes.h"
+#include "y_absl/base/config.h"
+#include "y_absl/base/const_init.h"
+#include "y_absl/base/thread_annotations.h"
+#include "y_absl/flags/internal/path_util.h"
+#include "y_absl/flags/internal/program_name.h"
+#include "y_absl/strings/match.h"
+#include "y_absl/strings/string_view.h"
+#include "y_absl/strings/strip.h"
+#include "y_absl/synchronization/mutex.h"
+
+extern "C" {
+
+// Additional report of fatal usage error message before we std::exit. Error is
+// fatal if is_fatal argument to ReportUsageError is true.
+Y_ABSL_ATTRIBUTE_WEAK void Y_ABSL_INTERNAL_C_SYMBOL(
+ AbslInternalReportFatalUsageError)(y_absl::string_view) {}
+
+} // extern "C"
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+namespace {
+
+// --------------------------------------------------------------------
+// Returns true if flags defined in the filename should be reported with
+// -helpshort flag.
+
+bool ContainsHelpshortFlags(y_absl::string_view filename) {
+ // By default we only want flags in binary's main. We expect the main
+ // routine to reside in <program>.cc or <program>-main.cc or
+ // <program>_main.cc, where the <program> is the name of the binary
+ // (without .exe on Windows).
+ auto suffix = flags_internal::Basename(filename);
+ auto program_name = flags_internal::ShortProgramInvocationName();
+ y_absl::string_view program_name_ref = program_name;
+#if defined(_WIN32)
+ y_absl::ConsumeSuffix(&program_name_ref, ".exe");
+#endif
+ if (!y_absl::ConsumePrefix(&suffix, program_name_ref))
+ return false;
+ return y_absl::StartsWith(suffix, ".") || y_absl::StartsWith(suffix, "-main.") ||
+ y_absl::StartsWith(suffix, "_main.");
+}
+
+// --------------------------------------------------------------------
+// Returns true if flags defined in the filename should be reported with
+// -helppackage flag.
+
+bool ContainsHelppackageFlags(y_absl::string_view filename) {
+ // TODO(rogeeff): implement properly when registry is available.
+ return ContainsHelpshortFlags(filename);
+}
+
+// --------------------------------------------------------------------
+// Generates program version information into supplied output.
+
+TString VersionString() {
+ TString version_str(flags_internal::ShortProgramInvocationName());
+
+ version_str += "\n";
+
+#if !defined(NDEBUG)
+ version_str += "Debug build (NDEBUG not #defined)\n";
+#endif
+
+ return version_str;
+}
+
+// --------------------------------------------------------------------
+// Normalizes the filename specific to the build system/filesystem used.
+
+TString NormalizeFilename(y_absl::string_view filename) {
+ // Skip any leading slashes
+ auto pos = filename.find_first_not_of("\\/");
+ if (pos == y_absl::string_view::npos) return "";
+
+ filename.remove_prefix(pos);
+ return TString(filename);
+}
+
+// --------------------------------------------------------------------
+
+Y_ABSL_CONST_INIT y_absl::Mutex custom_usage_config_guard(y_absl::kConstInit);
+Y_ABSL_CONST_INIT FlagsUsageConfig* custom_usage_config
+ Y_ABSL_GUARDED_BY(custom_usage_config_guard) = nullptr;
+
+} // namespace
+
+FlagsUsageConfig GetUsageConfig() {
+ y_absl::MutexLock l(&custom_usage_config_guard);
+
+ if (custom_usage_config) return *custom_usage_config;
+
+ FlagsUsageConfig default_config;
+ default_config.contains_helpshort_flags = &ContainsHelpshortFlags;
+ default_config.contains_help_flags = &ContainsHelppackageFlags;
+ default_config.contains_helppackage_flags = &ContainsHelppackageFlags;
+ default_config.version_string = &VersionString;
+ default_config.normalize_filename = &NormalizeFilename;
+
+ return default_config;
+}
+
+void ReportUsageError(y_absl::string_view msg, bool is_fatal) {
+ std::cerr << "ERROR: " << msg << std::endl;
+
+ if (is_fatal) {
+ Y_ABSL_INTERNAL_C_SYMBOL(AbslInternalReportFatalUsageError)(msg);
+ }
+}
+
+} // namespace flags_internal
+
+void SetFlagsUsageConfig(FlagsUsageConfig usage_config) {
+ y_absl::MutexLock l(&flags_internal::custom_usage_config_guard);
+
+ if (!usage_config.contains_helpshort_flags)
+ usage_config.contains_helpshort_flags =
+ flags_internal::ContainsHelpshortFlags;
+
+ if (!usage_config.contains_help_flags)
+ usage_config.contains_help_flags = flags_internal::ContainsHelppackageFlags;
+
+ if (!usage_config.contains_helppackage_flags)
+ usage_config.contains_helppackage_flags =
+ flags_internal::ContainsHelppackageFlags;
+
+ if (!usage_config.version_string)
+ usage_config.version_string = flags_internal::VersionString;
+
+ if (!usage_config.normalize_filename)
+ usage_config.normalize_filename = flags_internal::NormalizeFilename;
+
+ if (flags_internal::custom_usage_config)
+ *flags_internal::custom_usage_config = usage_config;
+ else
+ flags_internal::custom_usage_config = new FlagsUsageConfig(usage_config);
+}
+
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage_config.h b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage_config.h
new file mode 100644
index 0000000000..99b862f5d6
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/usage_config.h
@@ -0,0 +1,135 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: usage_config.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the main usage reporting configuration interfaces and
+// documents Abseil's supported built-in usage flags. If these flags are found
+// when parsing a command-line, Abseil will exit the program and display
+// appropriate help messages.
+#ifndef Y_ABSL_FLAGS_USAGE_CONFIG_H_
+#define Y_ABSL_FLAGS_USAGE_CONFIG_H_
+
+#include <functional>
+#include <util/generic/string.h>
+
+#include "y_absl/base/config.h"
+#include "y_absl/strings/string_view.h"
+
+// -----------------------------------------------------------------------------
+// Built-in Usage Flags
+// -----------------------------------------------------------------------------
+//
+// Abseil supports the following built-in usage flags. When passed, these flags
+// exit the program and :
+//
+// * --help
+// Shows help on important flags for this binary
+// * --helpfull
+// Shows help on all flags
+// * --helpshort
+// Shows help on only the main module for this program
+// * --helppackage
+// Shows help on all modules in the main package
+// * --version
+// Shows the version and build info for this binary and exits
+// * --only_check_args
+// Exits after checking all flags
+// * --helpon
+// Shows help on the modules named by this flag value
+// * --helpmatch
+// Shows help on modules whose name contains the specified substring
+
+namespace y_absl {
+Y_ABSL_NAMESPACE_BEGIN
+
+namespace flags_internal {
+using FlagKindFilter = std::function<bool (y_absl::string_view)>;
+} // namespace flags_internal
+
+// FlagsUsageConfig
+//
+// This structure contains the collection of callbacks for changing the behavior
+// of the usage reporting routines in Abseil Flags.
+struct FlagsUsageConfig {
+ // Returns true if flags defined in the given source code file should be
+ // reported with --helpshort flag. For example, if the file
+ // "path/to/my/code.cc" defines the flag "--my_flag", and
+ // contains_helpshort_flags("path/to/my/code.cc") returns true, invoking the
+ // program with --helpshort will include information about --my_flag in the
+ // program output.
+ flags_internal::FlagKindFilter contains_helpshort_flags;
+
+ // Returns true if flags defined in the filename should be reported with
+ // --help flag. For example, if the file
+ // "path/to/my/code.cc" defines the flag "--my_flag", and
+ // contains_help_flags("path/to/my/code.cc") returns true, invoking the
+ // program with --help will include information about --my_flag in the
+ // program output.
+ flags_internal::FlagKindFilter contains_help_flags;
+
+ // Returns true if flags defined in the filename should be reported with
+ // --helppackage flag. For example, if the file
+ // "path/to/my/code.cc" defines the flag "--my_flag", and
+ // contains_helppackage_flags("path/to/my/code.cc") returns true, invoking the
+ // program with --helppackage will include information about --my_flag in the
+ // program output.
+ flags_internal::FlagKindFilter contains_helppackage_flags;
+
+ // Generates string containing program version. This is the string reported
+ // when user specifies --version in a command line.
+ std::function<TString()> version_string;
+
+ // Normalizes the filename specific to the build system/filesystem used. This
+ // routine is used when we report the information about the flag definition
+ // location. For instance, if your build resides at some location you do not
+ // want to expose in the usage output, you can trim it to show only relevant
+ // part.
+ // For example:
+ // normalize_filename("/my_company/some_long_path/src/project/file.cc")
+ // might produce
+ // "project/file.cc".
+ std::function<TString(y_absl::string_view)> normalize_filename;
+};
+
+// SetFlagsUsageConfig()
+//
+// Sets the usage reporting configuration callbacks. If any of the callbacks are
+// not set in usage_config instance, then the default value of the callback is
+// used.
+void SetFlagsUsageConfig(FlagsUsageConfig usage_config);
+
+namespace flags_internal {
+
+FlagsUsageConfig GetUsageConfig();
+
+void ReportUsageError(y_absl::string_view msg, bool is_fatal);
+
+} // namespace flags_internal
+Y_ABSL_NAMESPACE_END
+} // namespace y_absl
+
+extern "C" {
+
+// Additional report of fatal usage error message before we std::exit. Error is
+// fatal if is_fatal argument to ReportUsageError is true.
+void Y_ABSL_INTERNAL_C_SYMBOL(AbslInternalReportFatalUsageError)(
+ y_absl::string_view);
+
+} // extern "C"
+
+#endif // Y_ABSL_FLAGS_USAGE_CONFIG_H_
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/flags/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/ya.make
new file mode 100644
index 0000000000..f8e0a201f7
--- /dev/null
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/flags/ya.make
@@ -0,0 +1,44 @@
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
+LICENSE(Apache-2.0)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+PEERDIR(
+ contrib/restricted/abseil-cpp-tstring/y_absl/base
+ contrib/restricted/abseil-cpp-tstring/y_absl/container
+ contrib/restricted/abseil-cpp-tstring/y_absl/debugging
+ contrib/restricted/abseil-cpp-tstring/y_absl/hash
+ contrib/restricted/abseil-cpp-tstring/y_absl/memory
+ contrib/restricted/abseil-cpp-tstring/y_absl/numeric
+ contrib/restricted/abseil-cpp-tstring/y_absl/profiling
+ contrib/restricted/abseil-cpp-tstring/y_absl/strings
+ contrib/restricted/abseil-cpp-tstring/y_absl/synchronization
+ contrib/restricted/abseil-cpp-tstring/y_absl/time
+ contrib/restricted/abseil-cpp-tstring/y_absl/types
+)
+
+ADDINCL(
+ GLOBAL contrib/restricted/abseil-cpp-tstring
+)
+
+NO_COMPILER_WARNINGS()
+
+SRCS(
+ commandlineflag.cc
+ flag.cc
+ internal/commandlineflag.cc
+ internal/flag.cc
+ internal/private_handle_accessor.cc
+ internal/program_name.cc
+ internal/usage.cc
+ marshalling.cc
+ parse.cc
+ reflection.cc
+ usage.cc
+ usage_config.cc
+)
+
+END()
diff --git a/yt/yt/core/rpc/grpc/channel.cpp b/yt/yt/core/rpc/grpc/channel.cpp
index 6b117e69e7..6c9b60ff1d 100644
--- a/yt/yt/core/rpc/grpc/channel.cpp
+++ b/yt/yt/core/rpc/grpc/channel.cpp
@@ -34,94 +34,80 @@ using namespace NBus;
////////////////////////////////////////////////////////////////////////////////
class TGrpcCallTracer final
- : public grpc_core::CallTracer
+ : public grpc_core::ServerCallTracer
{
public:
- CallAttemptTracer* StartNewAttempt(bool /*is_transparent_retry*/) override
+ void RecordAnnotation(y_absl::string_view /*annotation*/) override
+ { }
+
+ TString TraceId() override
{
- return &AttemptTracer_;
+ return {};
}
- TError GetError()
+ TString SpanId() override
{
- return AttemptTracer_.GetError();
+ return {};
}
- void RecordAnnotation(y_absl::string_view /*annotation*/) override
- { }
-
-private:
- class TAttemptTracer
- : public CallAttemptTracer
+ bool IsSampled() override
{
- public:
- TAttemptTracer()
- : Error_(y_absl::OkStatus())
- { }
+ return false;
+ }
- ~TAttemptTracer() override
- { }
+ void RecordSendInitialMetadata(
+ grpc_metadata_batch* /*send_initial_metadata*/) override
+ { }
- void RecordSendInitialMetadata(
- grpc_metadata_batch* /*send_initial_metadata*/) override
- { }
+ void RecordSendTrailingMetadata(grpc_metadata_batch* /*send_trailing_metadata*/) override
+ { }
- void RecordOnDoneSendInitialMetadata(gpr_atm* /*peer_string*/) override
- { }
+ void RecordSendMessage(const grpc_core::SliceBuffer& /*send_message*/) override
+ { }
- void RecordSendTrailingMetadata(grpc_metadata_batch* /*send_trailing_metadata*/) override
- { }
+ void RecordReceivedInitialMetadata(grpc_metadata_batch* /*recv_initial_metadata*/) override
+ { }
- void RecordSendMessage(const grpc_core::SliceBuffer& /*send_message*/) override
- { }
+ void RecordSendCompressedMessage(const grpc_core::SliceBuffer& /*send_compressed_message*/) override
+ { }
- void RecordReceivedInitialMetadata(
- grpc_metadata_batch* /*recv_initial_metadata*/,
- uint32_t /*flags*/) override
- { }
+ void RecordReceivedMessage(const grpc_core::SliceBuffer& /*recv_message*/) override
+ { }
- void RecordReceivedMessage(const grpc_core::SliceBuffer& /*recv_message*/) override
- { }
+ void RecordReceivedDecompressedMessage(const grpc_core::SliceBuffer& /*recv_decompressed_message*/) override
+ { }
- void RecordReceivedTrailingMetadata(
- y_absl::Status /*status*/,
- grpc_metadata_batch* /*recv_trailing_metadata*/,
- const grpc_transport_stream_stats* /*transport_stream_stats*/) override
- { }
+ void RecordCancel(grpc_error_handle cancelError) override
+ {
+ auto current = Error_.get();
+ Error_.set(cancelError);
+ }
- void RecordCancel(grpc_error_handle cancelError) override
- {
- auto current = Error_.get();
- Error_.set(cancelError);
+ TError GetError()
+ {
+ auto error = Error_.get();
+ intptr_t statusCode;
+ if (!grpc_error_get_int(error, grpc_core::StatusIntProperty::kRpcStatus, &statusCode)) {
+ statusCode = GRPC_STATUS_UNKNOWN;
+ }
+ TString statusDetail;
+ if (!grpc_error_get_str(error, grpc_core::StatusStrProperty::kDescription, &statusDetail)) {
+ statusDetail = "Unknown error";
}
- void RecordEnd(const gpr_timespec& /*latency*/) override
- { }
-
- void RecordAnnotation(y_absl::string_view /*annotation*/) override
- { }
-
- TError GetError()
- {
- auto error = Error_.get();
- intptr_t statusCode;
- if (!grpc_error_get_int(error, grpc_core::StatusIntProperty::kRpcStatus, &statusCode)) {
- statusCode = GRPC_STATUS_UNKNOWN;
- }
- TString statusDetail;
- if (!grpc_error_get_str(error, grpc_core::StatusStrProperty::kDescription, &statusDetail)) {
- statusDetail = "Unknown error";
- }
+ return TError(StatusCodeToErrorCode(static_cast<grpc_status_code>(statusCode)), statusDetail)
+ << TErrorAttribute("status_code", statusCode);
+ }
- return TError(StatusCodeToErrorCode(static_cast<grpc_status_code>(statusCode)), statusDetail)
- << TErrorAttribute("status_code", statusCode);
- }
+ void RecordReceivedTrailingMetadata(
+ grpc_metadata_batch* /*recv_trailing_metadata*/) override
+ { }
- private:
- AtomicError Error_;
- };
+ void RecordEnd(const grpc_call_final_info* /*final_info*/) override
+ { }
- TAttemptTracer AttemptTracer_;
+private:
+ AtomicError Error_;
};
DECLARE_REFCOUNTED_TYPE(TGrpcCallTracer)