diff options
author | leonidlazarev <leonidlazarev@yandex-team.com> | 2023-08-01 12:39:29 +0300 |
---|---|---|
committer | leonidlazarev <leonidlazarev@yandex-team.com> | 2023-08-01 12:39:29 +0300 |
commit | a3b63938a35abe460ed6b601e55e57bb44449c83 (patch) | |
tree | b6a8b6b9a486f68bf4dd1627fca351e9513897b2 | |
parent | 1ab00fd81ce534b158e55f27450d5559833cb70a (diff) | |
download | ydb-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
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(>m.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 = - >m.recv_trailing_metadata_ready; - SchedulePush(>m.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 & 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 << """; + break; + case '\'': + out << "'"; + break; + case '&': + out << "&"; + break; + case '<': + out << "<"; + break; + case '>': + out << ">"; + 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) |