Merge branch 'master' of git://github.com/grpc/grpc

pull/22638/head
Taras Galkovskyi 5 years ago
commit 2cf920ba0b
  1. 2
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 2
      .github/ISSUE_TEMPLATE/cleanup_request.md
  3. 2
      .github/ISSUE_TEMPLATE/feature_request.md
  4. 2
      .github/pull_request_template.md
  5. 1
      .gitignore
  6. 66
      BUILD
  7. 9
      BUILD.gn
  8. 90
      CMakeLists.txt
  9. 116
      Makefile
  10. 109
      bazel/grpc_deps.bzl
  11. 63
      bazel/update_mirror.sh
  12. 51
      build_autogenerated.yaml
  13. 3
      config.m4
  14. 3
      config.w32
  15. 12
      doc/python/sphinx/conf.py
  16. 34
      doc/python/sphinx/glossary.rst
  17. 7
      doc/xds-test-descriptions.md
  18. 12
      gRPC-C++.podspec
  19. 20
      gRPC-Core.podspec
  20. 9
      grpc.gemspec
  21. 8
      grpc.gyp
  22. 10
      include/grpc/impl/codegen/grpc_types.h
  23. 39
      include/grpcpp/server_impl.h
  24. 9
      package.xml
  25. 365
      setup.py
  26. 3259
      src/boringssl/boringssl_prefix_symbols.h
  27. 6
      src/compiler/php_generator.cc
  28. 11
      src/core/ext/filters/client_channel/backend_metric.cc
  29. 323
      src/core/ext/filters/client_channel/client_channel.cc
  30. 9
      src/core/ext/filters/client_channel/http_proxy.cc
  31. 33
      src/core/ext/filters/client_channel/lb_policy.cc
  32. 53
      src/core/ext/filters/client_channel/lb_policy.h
  33. 5
      src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc
  34. 365
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  35. 6
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc
  36. 5
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
  37. 70
      src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
  38. 2
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
  39. 9
      src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
  40. 53
      src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
  41. 20
      src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
  42. 16
      src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
  43. 12
      src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
  44. 834
      src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
  45. 6
      src/core/ext/filters/client_channel/lb_policy_registry.cc
  46. 3
      src/core/ext/filters/client_channel/local_subchannel_pool.h
  47. 43
      src/core/ext/filters/client_channel/parse_address.cc
  48. 9
      src/core/ext/filters/client_channel/resolver.cc
  49. 22
      src/core/ext/filters/client_channel/resolver.h
  50. 127
      src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
  51. 70
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc
  52. 15
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
  53. 36
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc
  54. 8
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
  55. 189
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc
  56. 129
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
  57. 3
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
  58. 5
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc
  59. 83
      src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
  60. 195
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
  61. 4
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h
  62. 4
      src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
  63. 6
      src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
  64. 4
      src/core/ext/filters/client_channel/resolver_factory.h
  65. 9
      src/core/ext/filters/client_channel/resolver_registry.cc
  66. 16
      src/core/ext/filters/client_channel/resolver_registry.h
  67. 8
      src/core/ext/filters/client_channel/resolver_result_parsing.cc
  68. 15
      src/core/ext/filters/client_channel/resolver_result_parsing.h
  69. 11
      src/core/ext/filters/client_channel/resolving_lb_policy.cc
  70. 5
      src/core/ext/filters/client_channel/resolving_lb_policy.h
  71. 5
      src/core/ext/filters/client_channel/server_address.h
  72. 10
      src/core/ext/filters/client_channel/service_config.cc
  73. 12
      src/core/ext/filters/client_channel/service_config.h
  74. 78
      src/core/ext/filters/client_channel/subchannel.cc
  75. 46
      src/core/ext/filters/client_channel/subchannel.h
  76. 190
      src/core/ext/filters/client_channel/xds/xds_api.cc
  77. 36
      src/core/ext/filters/client_channel/xds/xds_api.h
  78. 24
      src/core/ext/filters/client_channel/xds/xds_bootstrap.cc
  79. 7
      src/core/ext/filters/client_channel/xds/xds_bootstrap.h
  80. 6
      src/core/ext/filters/client_channel/xds/xds_channel_secure.cc
  81. 592
      src/core/ext/filters/client_channel/xds/xds_client.cc
  82. 41
      src/core/ext/filters/client_channel/xds/xds_client.h
  83. 10
      src/core/ext/filters/client_channel/xds/xds_client_stats.cc
  84. 27
      src/core/ext/filters/client_channel/xds/xds_client_stats.h
  85. 5
      src/core/ext/filters/http/client/http_client_filter.cc
  86. 35
      src/core/ext/filters/http/http_filters_plugin.cc
  87. 358
      src/core/ext/filters/http/message_compress/message_decompress_filter.cc
  88. 29
      src/core/ext/filters/http/message_compress/message_decompress_filter.h
  89. 40
      src/core/ext/transport/chttp2/transport/hpack_encoder.cc
  90. 1
      src/core/ext/transport/inproc/inproc_transport.cc
  91. 11
      src/core/lib/channel/channelz.cc
  92. 5
      src/core/lib/channel/channelz.h
  93. 8
      src/core/lib/channel/channelz_registry.cc
  94. 7
      src/core/lib/channel/connected_channel.cc
  95. 6
      src/core/lib/channel/handshaker.h
  96. 5
      src/core/lib/channel/handshaker_registry.cc
  97. 52
      src/core/lib/gprpp/host_port.cc
  98. 29
      src/core/lib/gprpp/host_port.h
  99. 37
      src/core/lib/gprpp/inlined_vector.h
  100. 16
      src/core/lib/gprpp/map.h
  101. Some files were not shown because too many files have changed in this diff Show More

@ -2,7 +2,7 @@
name: Report a bug
about: Create a report to help us improve
labels: kind/bug, priority/P2
assignees: nicolasnoble
assignees: veblush
---

@ -2,7 +2,7 @@
name: Request a cleanup
about: Suggest a cleanup in our repository
labels: kind/internal cleanup, priority/P2
assignees: nicolasnoble
assignees: veblush
---

@ -2,7 +2,7 @@
name: Request a feature
about: Suggest an idea for this project
labels: kind/enhancement, priority/P2
assignees: nicolasnoble
assignees: veblush
---

@ -8,4 +8,4 @@ If you know who should review your pull request, please remove the mentioning be
-->
@nicolasnoble
@veblush

1
.gitignore vendored

@ -150,4 +150,3 @@ BenchmarkDotNet.Artifacts/
# pyenv config
.python-version

66
BUILD

@ -322,6 +322,7 @@ grpc_cc_library(
"grpc_lb_policy_eds",
"grpc_lb_policy_grpclb",
"grpc_lb_policy_lrs",
"grpc_lb_policy_xds_routing",
"grpc_resolver_xds",
],
)
@ -341,6 +342,7 @@ grpc_cc_library(
"grpc_lb_policy_eds_secure",
"grpc_lb_policy_grpclb_secure",
"grpc_lb_policy_lrs_secure",
"grpc_lb_policy_xds_routing",
"grpc_resolver_xds_secure",
"grpc_secure",
"grpc_transport_chttp2_client_secure",
@ -552,7 +554,6 @@ grpc_cc_library(
"src/core/lib/gprpp/map.h",
"src/core/lib/gprpp/memory.h",
"src/core/lib/gprpp/mpscq.h",
"src/core/lib/gprpp/string_view.h",
"src/core/lib/gprpp/sync.h",
"src/core/lib/gprpp/thd.h",
"src/core/lib/profiling/timers.h",
@ -616,40 +617,12 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "inlined_vector",
external_deps = [
"absl/container:inlined_vector",
],
language = "c++",
public_hdrs = [
"src/core/lib/gprpp/inlined_vector.h",
],
deps = [
"gpr_base",
],
)
grpc_cc_library(
name = "debug_location",
language = "c++",
public_hdrs = ["src/core/lib/gprpp/debug_location.h"],
)
grpc_cc_library(
name = "optional",
external_deps = [
"absl/types:optional",
],
language = "c++",
public_hdrs = [
"src/core/lib/gprpp/optional.h",
],
deps = [
"gpr_base",
],
)
grpc_cc_library(
name = "orphanable",
language = "c++",
@ -724,6 +697,7 @@ grpc_cc_library(
"src/core/lib/iomgr/endpoint_pair_windows.cc",
"src/core/lib/iomgr/error.cc",
"src/core/lib/iomgr/error_cfstream.cc",
"src/core/lib/iomgr/ev_apple.cc",
"src/core/lib/iomgr/ev_epoll1_linux.cc",
"src/core/lib/iomgr/ev_epollex_linux.cc",
"src/core/lib/iomgr/ev_poll_posix.cc",
@ -885,6 +859,7 @@ grpc_cc_library(
"src/core/lib/iomgr/error.h",
"src/core/lib/iomgr/error_cfstream.h",
"src/core/lib/iomgr/error_internal.h",
"src/core/lib/iomgr/ev_apple.h",
"src/core/lib/iomgr/ev_epoll1_linux.h",
"src/core/lib/iomgr/ev_epollex_linux.h",
"src/core/lib/iomgr/ev_poll_posix.h",
@ -986,17 +961,16 @@ grpc_cc_library(
],
external_deps = [
"madler_zlib",
"absl/container:inlined_vector",
"absl/types:optional",
],
language = "c++",
public_hdrs = GRPC_PUBLIC_HDRS,
use_cfstream = True,
deps = [
"eventmanager_libuv",
"gpr_base",
"grpc_codegen",
"grpc_trace",
"inlined_vector",
"optional",
"orphanable",
"ref_counted",
"ref_counted_ptr",
@ -1104,6 +1078,9 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/subchannel_interface.h",
"src/core/ext/filters/client_channel/subchannel_pool_interface.h",
],
external_deps = [
"absl/container:inlined_vector",
],
language = "c++",
deps = [
"gpr_base",
@ -1111,7 +1088,6 @@ grpc_cc_library(
"grpc_client_authority_filter",
"grpc_deadline_filter",
"grpc_health_upb",
"inlined_vector",
"orphanable",
"ref_counted",
"ref_counted_ptr",
@ -1193,11 +1169,13 @@ grpc_cc_library(
"src/core/ext/filters/http/client/http_client_filter.cc",
"src/core/ext/filters/http/http_filters_plugin.cc",
"src/core/ext/filters/http/message_compress/message_compress_filter.cc",
"src/core/ext/filters/http/message_compress/message_decompress_filter.cc",
"src/core/ext/filters/http/server/http_server_filter.cc",
],
hdrs = [
"src/core/ext/filters/http/client/http_client_filter.h",
"src/core/ext/filters/http/message_compress/message_compress_filter.h",
"src/core/ext/filters/http/message_compress/message_decompress_filter.h",
"src/core/ext/filters/http/server/http_server_filter.h",
],
language = "c++",
@ -1452,6 +1430,18 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "grpc_lb_policy_xds_routing",
srcs = [
"src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc",
],
language = "c++",
deps = [
"grpc_base",
"grpc_client_channel",
],
)
grpc_cc_library(
name = "grpc_lb_address_filtering",
srcs = [
@ -1845,7 +1835,6 @@ grpc_cc_library(
deps = [
"alts_util",
"grpc_base",
"grpc_shadow_boringssl",
"grpc_transport_chttp2_alpn",
"tsi",
],
@ -2086,7 +2075,6 @@ grpc_cc_library(
deps = [
"gpr",
"grpc_base",
"grpc_shadow_boringssl",
"tsi_interface",
],
)
@ -2155,7 +2143,6 @@ grpc_cc_library(
"alts_util",
"gpr",
"grpc_base",
"grpc_shadow_boringssl",
"grpc_transport_chttp2_client_insecure",
"tsi_interface",
],
@ -2448,13 +2435,6 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "grpc_shadow_boringssl",
hdrs = [
"src/core/tsi/grpc_shadow_boringssl.h",
],
)
# Once upb code-gen issue is resolved, use the targets commented below to replace the ones using
# upb-generated files.

@ -160,7 +160,6 @@ config("grpc_config") {
"src/core/lib/gprpp/memory.h",
"src/core/lib/gprpp/mpscq.cc",
"src/core/lib/gprpp/mpscq.h",
"src/core/lib/gprpp/string_view.h",
"src/core/lib/gprpp/sync.h",
"src/core/lib/gprpp/thd.h",
"src/core/lib/gprpp/thd_posix.cc",
@ -248,6 +247,7 @@ config("grpc_config") {
"src/core/ext/filters/client_channel/lb_policy/xds/eds.cc",
"src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc",
"src/core/ext/filters/client_channel/lb_policy/xds/xds.h",
"src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc",
"src/core/ext/filters/client_channel/lb_policy_factory.h",
"src/core/ext/filters/client_channel/lb_policy_registry.cc",
"src/core/ext/filters/client_channel/lb_policy_registry.h",
@ -318,6 +318,8 @@ config("grpc_config") {
"src/core/ext/filters/http/http_filters_plugin.cc",
"src/core/ext/filters/http/message_compress/message_compress_filter.cc",
"src/core/ext/filters/http/message_compress/message_compress_filter.h",
"src/core/ext/filters/http/message_compress/message_decompress_filter.cc",
"src/core/ext/filters/http/message_compress/message_decompress_filter.h",
"src/core/ext/filters/http/server/http_server_filter.cc",
"src/core/ext/filters/http/server/http_server_filter.h",
"src/core/ext/filters/max_age/max_age_filter.cc",
@ -567,8 +569,6 @@ config("grpc_config") {
"src/core/lib/debug/trace.h",
"src/core/lib/gprpp/atomic.h",
"src/core/lib/gprpp/debug_location.h",
"src/core/lib/gprpp/inlined_vector.h",
"src/core/lib/gprpp/optional.h",
"src/core/lib/gprpp/orphanable.h",
"src/core/lib/gprpp/ref_counted.h",
"src/core/lib/gprpp/ref_counted_ptr.h",
@ -604,6 +604,8 @@ config("grpc_config") {
"src/core/lib/iomgr/error_cfstream.cc",
"src/core/lib/iomgr/error_cfstream.h",
"src/core/lib/iomgr/error_internal.h",
"src/core/lib/iomgr/ev_apple.cc",
"src/core/lib/iomgr/ev_apple.h",
"src/core/lib/iomgr/ev_epoll1_linux.cc",
"src/core/lib/iomgr/ev_epoll1_linux.h",
"src/core/lib/iomgr/ev_epollex_linux.cc",
@ -943,7 +945,6 @@ config("grpc_config") {
"src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h",
"src/core/tsi/fake_transport_security.cc",
"src/core/tsi/fake_transport_security.h",
"src/core/tsi/grpc_shadow_boringssl.h",
"src/core/tsi/local_transport_security.cc",
"src/core/tsi/local_transport_security.h",
"src/core/tsi/ssl/session_cache/ssl_session.h",

@ -756,7 +756,6 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx mock_test)
add_dependencies(buildtests_cxx nonblocking_test)
add_dependencies(buildtests_cxx noop-benchmark)
add_dependencies(buildtests_cxx optional_test)
add_dependencies(buildtests_cxx orphanable_test)
add_dependencies(buildtests_cxx out_of_bounds_bad_client_test)
add_dependencies(buildtests_cxx pid_controller_test)
@ -799,7 +798,6 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx streaming_throughput_test)
endif()
add_dependencies(buildtests_cxx string_ref_test)
add_dependencies(buildtests_cxx string_view_test)
add_dependencies(buildtests_cxx test_cpp_client_credentials_test)
add_dependencies(buildtests_cxx test_cpp_util_slice_test)
add_dependencies(buildtests_cxx test_cpp_util_time_test)
@ -919,6 +917,7 @@ add_library(end2end_nosec_tests
test/core/end2end/tests/cancel_in_a_vacuum.cc
test/core/end2end/tests/cancel_with_status.cc
test/core/end2end/tests/channelz.cc
test/core/end2end/tests/client_streaming.cc
test/core/end2end/tests/compressed_payload.cc
test/core/end2end/tests/connectivity.cc
test/core/end2end/tests/default_host.cc
@ -1050,6 +1049,7 @@ add_library(end2end_tests
test/core/end2end/tests/cancel_in_a_vacuum.cc
test/core/end2end/tests/cancel_with_status.cc
test/core/end2end/tests/channelz.cc
test/core/end2end/tests/client_streaming.cc
test/core/end2end/tests/compressed_payload.cc
test/core/end2end/tests/connectivity.cc
test/core/end2end/tests/default_host.cc
@ -1330,6 +1330,7 @@ add_library(grpc
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
src/core/ext/filters/client_channel/lb_policy_registry.cc
src/core/ext/filters/client_channel/local_subchannel_pool.cc
src/core/ext/filters/client_channel/parse_address.cc
@ -1369,6 +1370,7 @@ add_library(grpc
src/core/ext/filters/http/client_authority_filter.cc
src/core/ext/filters/http/http_filters_plugin.cc
src/core/ext/filters/http/message_compress/message_compress_filter.cc
src/core/ext/filters/http/message_compress/message_decompress_filter.cc
src/core/ext/filters/http/server/http_server_filter.cc
src/core/ext/filters/max_age/max_age_filter.cc
src/core/ext/filters/message_size/message_size_filter.cc
@ -1512,6 +1514,7 @@ add_library(grpc
src/core/lib/iomgr/endpoint_pair_windows.cc
src/core/lib/iomgr/error.cc
src/core/lib/iomgr/error_cfstream.cc
src/core/lib/iomgr/ev_apple.cc
src/core/lib/iomgr/ev_epoll1_linux.cc
src/core/lib/iomgr/ev_epollex_linux.cc
src/core/lib/iomgr/ev_poll_posix.cc
@ -1989,6 +1992,7 @@ add_library(grpc_unsecure
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
src/core/ext/filters/client_channel/lb_policy_registry.cc
src/core/ext/filters/client_channel/local_subchannel_pool.cc
src/core/ext/filters/client_channel/parse_address.cc
@ -2028,6 +2032,7 @@ add_library(grpc_unsecure
src/core/ext/filters/http/client_authority_filter.cc
src/core/ext/filters/http/http_filters_plugin.cc
src/core/ext/filters/http/message_compress/message_compress_filter.cc
src/core/ext/filters/http/message_compress/message_decompress_filter.cc
src/core/ext/filters/http/server/http_server_filter.cc
src/core/ext/filters/max_age/max_age_filter.cc
src/core/ext/filters/message_size/message_size_filter.cc
@ -2165,6 +2170,7 @@ add_library(grpc_unsecure
src/core/lib/iomgr/endpoint_pair_windows.cc
src/core/lib/iomgr/error.cc
src/core/lib/iomgr/error_cfstream.cc
src/core/lib/iomgr/ev_apple.cc
src/core/lib/iomgr/ev_epoll1_linux.cc
src/core/lib/iomgr/ev_epollex_linux.cc
src/core/lib/iomgr/ev_poll_posix.cc
@ -6344,10 +6350,6 @@ endif()
if(gRPC_BUILD_TESTS)
add_executable(num_external_connectivity_watchers_test
test/core/end2end/data/client_certs.cc
test/core/end2end/data/server1_cert.cc
test/core/end2end/data/server1_key.cc
test/core/end2end/data/test_root_cert.cc
test/core/surface/num_external_connectivity_watchers_test.cc
)
@ -12162,44 +12164,6 @@ target_link_libraries(noop-benchmark
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(optional_test
test/core/gprpp/optional_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(optional_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(optional_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr
address_sorting
upb
${_gRPC_GFLAGS_LIBRARIES}
)
endif()
if(gRPC_BUILD_TESTS)
@ -13801,44 +13765,6 @@ target_link_libraries(string_ref_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(string_view_test
test/core/gprpp/string_view_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(string_view_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(string_view_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr
address_sorting
upb
${_gRPC_GFLAGS_LIBRARIES}
)
endif()
if(gRPC_BUILD_TESTS)

@ -1251,7 +1251,6 @@ nanopb_fuzzer_response_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_response_test
nanopb_fuzzer_serverlist_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test
nonblocking_test: $(BINDIR)/$(CONFIG)/nonblocking_test
noop-benchmark: $(BINDIR)/$(CONFIG)/noop-benchmark
optional_test: $(BINDIR)/$(CONFIG)/optional_test
orphanable_test: $(BINDIR)/$(CONFIG)/orphanable_test
out_of_bounds_bad_client_test: $(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test
percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer
@ -1290,7 +1289,6 @@ status_metadata_test: $(BINDIR)/$(CONFIG)/status_metadata_test
status_util_test: $(BINDIR)/$(CONFIG)/status_util_test
streaming_throughput_test: $(BINDIR)/$(CONFIG)/streaming_throughput_test
string_ref_test: $(BINDIR)/$(CONFIG)/string_ref_test
string_view_test: $(BINDIR)/$(CONFIG)/string_view_test
test_cpp_client_credentials_test: $(BINDIR)/$(CONFIG)/test_cpp_client_credentials_test
test_cpp_util_slice_test: $(BINDIR)/$(CONFIG)/test_cpp_util_slice_test
test_cpp_util_time_test: $(BINDIR)/$(CONFIG)/test_cpp_util_time_test
@ -1616,7 +1614,6 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/mock_test \
$(BINDIR)/$(CONFIG)/nonblocking_test \
$(BINDIR)/$(CONFIG)/noop-benchmark \
$(BINDIR)/$(CONFIG)/optional_test \
$(BINDIR)/$(CONFIG)/orphanable_test \
$(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test \
$(BINDIR)/$(CONFIG)/pid_controller_test \
@ -1651,7 +1648,6 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/status_util_test \
$(BINDIR)/$(CONFIG)/streaming_throughput_test \
$(BINDIR)/$(CONFIG)/string_ref_test \
$(BINDIR)/$(CONFIG)/string_view_test \
$(BINDIR)/$(CONFIG)/test_cpp_client_credentials_test \
$(BINDIR)/$(CONFIG)/test_cpp_util_slice_test \
$(BINDIR)/$(CONFIG)/test_cpp_util_time_test \
@ -1774,7 +1770,6 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/mock_test \
$(BINDIR)/$(CONFIG)/nonblocking_test \
$(BINDIR)/$(CONFIG)/noop-benchmark \
$(BINDIR)/$(CONFIG)/optional_test \
$(BINDIR)/$(CONFIG)/orphanable_test \
$(BINDIR)/$(CONFIG)/out_of_bounds_bad_client_test \
$(BINDIR)/$(CONFIG)/pid_controller_test \
@ -1809,7 +1804,6 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/status_util_test \
$(BINDIR)/$(CONFIG)/streaming_throughput_test \
$(BINDIR)/$(CONFIG)/string_ref_test \
$(BINDIR)/$(CONFIG)/string_view_test \
$(BINDIR)/$(CONFIG)/test_cpp_client_credentials_test \
$(BINDIR)/$(CONFIG)/test_cpp_util_slice_test \
$(BINDIR)/$(CONFIG)/test_cpp_util_time_test \
@ -2276,8 +2270,6 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/nonblocking_test || ( echo test nonblocking_test failed ; exit 1 )
$(E) "[RUN] Testing noop-benchmark"
$(Q) $(BINDIR)/$(CONFIG)/noop-benchmark || ( echo test noop-benchmark failed ; exit 1 )
$(E) "[RUN] Testing optional_test"
$(Q) $(BINDIR)/$(CONFIG)/optional_test || ( echo test optional_test failed ; exit 1 )
$(E) "[RUN] Testing orphanable_test"
$(Q) $(BINDIR)/$(CONFIG)/orphanable_test || ( echo test orphanable_test failed ; exit 1 )
$(E) "[RUN] Testing out_of_bounds_bad_client_test"
@ -2340,8 +2332,6 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/streaming_throughput_test || ( echo test streaming_throughput_test failed ; exit 1 )
$(E) "[RUN] Testing string_ref_test"
$(Q) $(BINDIR)/$(CONFIG)/string_ref_test || ( echo test string_ref_test failed ; exit 1 )
$(E) "[RUN] Testing string_view_test"
$(Q) $(BINDIR)/$(CONFIG)/string_view_test || ( echo test string_view_test failed ; exit 1 )
$(E) "[RUN] Testing test_cpp_client_credentials_test"
$(Q) $(BINDIR)/$(CONFIG)/test_cpp_client_credentials_test || ( echo test test_cpp_client_credentials_test failed ; exit 1 )
$(E) "[RUN] Testing test_cpp_util_slice_test"
@ -3290,6 +3280,7 @@ LIBEND2END_NOSEC_TESTS_SRC = \
test/core/end2end/tests/cancel_in_a_vacuum.cc \
test/core/end2end/tests/cancel_with_status.cc \
test/core/end2end/tests/channelz.cc \
test/core/end2end/tests/client_streaming.cc \
test/core/end2end/tests/compressed_payload.cc \
test/core/end2end/tests/connectivity.cc \
test/core/end2end/tests/default_host.cc \
@ -3402,6 +3393,7 @@ LIBEND2END_TESTS_SRC = \
test/core/end2end/tests/cancel_in_a_vacuum.cc \
test/core/end2end/tests/cancel_with_status.cc \
test/core/end2end/tests/channelz.cc \
test/core/end2end/tests/client_streaming.cc \
test/core/end2end/tests/compressed_payload.cc \
test/core/end2end/tests/connectivity.cc \
test/core/end2end/tests/default_host.cc \
@ -3655,6 +3647,7 @@ LIBGRPC_SRC = \
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc \
src/core/ext/filters/client_channel/lb_policy/xds/eds.cc \
src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc \
src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc \
src/core/ext/filters/client_channel/lb_policy_registry.cc \
src/core/ext/filters/client_channel/local_subchannel_pool.cc \
src/core/ext/filters/client_channel/parse_address.cc \
@ -3694,6 +3687,7 @@ LIBGRPC_SRC = \
src/core/ext/filters/http/client_authority_filter.cc \
src/core/ext/filters/http/http_filters_plugin.cc \
src/core/ext/filters/http/message_compress/message_compress_filter.cc \
src/core/ext/filters/http/message_compress/message_decompress_filter.cc \
src/core/ext/filters/http/server/http_server_filter.cc \
src/core/ext/filters/max_age/max_age_filter.cc \
src/core/ext/filters/message_size/message_size_filter.cc \
@ -3837,6 +3831,7 @@ LIBGRPC_SRC = \
src/core/lib/iomgr/endpoint_pair_windows.cc \
src/core/lib/iomgr/error.cc \
src/core/lib/iomgr/error_cfstream.cc \
src/core/lib/iomgr/ev_apple.cc \
src/core/lib/iomgr/ev_epoll1_linux.cc \
src/core/lib/iomgr/ev_epollex_linux.cc \
src/core/lib/iomgr/ev_poll_posix.cc \
@ -4288,6 +4283,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc \
src/core/ext/filters/client_channel/lb_policy/xds/eds.cc \
src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc \
src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc \
src/core/ext/filters/client_channel/lb_policy_registry.cc \
src/core/ext/filters/client_channel/local_subchannel_pool.cc \
src/core/ext/filters/client_channel/parse_address.cc \
@ -4327,6 +4323,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/filters/http/client_authority_filter.cc \
src/core/ext/filters/http/http_filters_plugin.cc \
src/core/ext/filters/http/message_compress/message_compress_filter.cc \
src/core/ext/filters/http/message_compress/message_decompress_filter.cc \
src/core/ext/filters/http/server/http_server_filter.cc \
src/core/ext/filters/max_age/max_age_filter.cc \
src/core/ext/filters/message_size/message_size_filter.cc \
@ -4464,6 +4461,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/iomgr/endpoint_pair_windows.cc \
src/core/lib/iomgr/error.cc \
src/core/lib/iomgr/error_cfstream.cc \
src/core/lib/iomgr/ev_apple.cc \
src/core/lib/iomgr/ev_epoll1_linux.cc \
src/core/lib/iomgr/ev_epollex_linux.cc \
src/core/lib/iomgr/ev_poll_posix.cc \
@ -9538,10 +9536,6 @@ endif
NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_SRC = \
test/core/end2end/data/client_certs.cc \
test/core/end2end/data/server1_cert.cc \
test/core/end2end/data/server1_key.cc \
test/core/end2end/data/test_root_cert.cc \
test/core/surface/num_external_connectivity_watchers_test.cc \
NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_SRC))))
@ -9562,14 +9556,6 @@ $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test: $(NUM_EXTERNAL_CONN
endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/client_certs.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_cert.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/server1_key.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/end2end/data/test_root_cert.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(OBJDIR)/$(CONFIG)/test/core/surface/num_external_connectivity_watchers_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
deps_num_external_connectivity_watchers_test: $(NUM_EXTERNAL_CONNECTIVITY_WATCHERS_TEST_OBJS:.o=.dep)
@ -16217,49 +16203,6 @@ endif
endif
OPTIONAL_TEST_SRC = \
test/core/gprpp/optional_test.cc \
OPTIONAL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(OPTIONAL_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/optional_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
$(BINDIR)/$(CONFIG)/optional_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/optional_test: $(PROTOBUF_DEP) $(OPTIONAL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(OPTIONAL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/optional_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/core/gprpp/optional_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
deps_optional_test: $(OPTIONAL_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(OPTIONAL_TEST_OBJS:.o=.dep)
endif
endif
ORPHANABLE_TEST_SRC = \
test/core/gprpp/orphanable_test.cc \
@ -18249,49 +18192,6 @@ endif
endif
STRING_VIEW_TEST_SRC = \
test/core/gprpp/string_view_test.cc \
STRING_VIEW_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STRING_VIEW_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/string_view_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
$(BINDIR)/$(CONFIG)/string_view_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/string_view_test: $(PROTOBUF_DEP) $(STRING_VIEW_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(STRING_VIEW_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/string_view_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/core/gprpp/string_view_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
deps_string_view_test: $(STRING_VIEW_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(STRING_VIEW_TEST_OBJS:.o=.dep)
endif
endif
TEST_CPP_CLIENT_CREDENTIALS_TEST_SRC = \
test/cpp/client/credentials_test.cc \

@ -133,7 +133,10 @@ def grpc_deps():
# to obtain a boringssl archive with consistent sha256
sha256 = "a3d4de4f03cb321ef943678d72a045c9a19d26b23d6f4e313f97600c65201a27",
strip_prefix = "boringssl-1c2769383f027befac5b75b6cedd25daf3bf4dcf",
url = "https://github.com/google/boringssl/archive/1c2769383f027befac5b75b6cedd25daf3bf4dcf.tar.gz",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/boringssl/archive/1c2769383f027befac5b75b6cedd25daf3bf4dcf.tar.gz",
"https://github.com/google/boringssl/archive/1c2769383f027befac5b75b6cedd25daf3bf4dcf.tar.gz",
],
)
if "zlib" not in native.existing_rules():
@ -142,15 +145,21 @@ def grpc_deps():
build_file = "@com_github_grpc_grpc//third_party:zlib.BUILD",
sha256 = "6d4d6640ca3121620995ee255945161821218752b551a1a180f4215f7d124d45",
strip_prefix = "zlib-cacf7f1d4e3d44d871b605da3b647f07d718623f",
url = "https://github.com/madler/zlib/archive/cacf7f1d4e3d44d871b605da3b647f07d718623f.tar.gz",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/madler/zlib/archive/cacf7f1d4e3d44d871b605da3b647f07d718623f.tar.gz",
"https://github.com/madler/zlib/archive/cacf7f1d4e3d44d871b605da3b647f07d718623f.tar.gz",
],
)
if "com_google_protobuf" not in native.existing_rules():
http_archive(
name = "com_google_protobuf",
sha256 = "51398b0b97b353c1c226d0ade0bae80c80380e691cba7c1a108918986784a1c7",
strip_prefix = "protobuf-29cd005ce1fe1a8fabf11e325cb13006a6646d59",
url = "https://github.com/google/protobuf/archive/29cd005ce1fe1a8fabf11e325cb13006a6646d59.tar.gz",
sha256 = "2435b7fb83b8a608c24ca677907aa9a35e482a7f018e65ca69481b3c8c9f7caf",
strip_prefix = "protobuf-d0bfd5221182da1a7cc280f3337b5e41a89539cf",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/protobuf/archive/d0bfd5221182da1a7cc280f3337b5e41a89539cf.tar.gz",
"https://github.com/google/protobuf/archive/d0bfd5221182da1a7cc280f3337b5e41a89539cf.tar.gz",
],
)
if "com_github_google_googletest" not in native.existing_rules():
@ -158,7 +167,11 @@ def grpc_deps():
name = "com_github_google_googletest",
sha256 = "443d383db648ebb8e391382c0ab63263b7091d03197f304390baac10f178a468",
strip_prefix = "googletest-c9ccac7cb7345901884aabf5d1a786cfa6e2f397",
url = "https://github.com/google/googletest/archive/c9ccac7cb7345901884aabf5d1a786cfa6e2f397.tar.gz", # 2019-08-19
urls = [
# 2019-08-19
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/googletest/archive/c9ccac7cb7345901884aabf5d1a786cfa6e2f397.tar.gz",
"https://github.com/google/googletest/archive/c9ccac7cb7345901884aabf5d1a786cfa6e2f397.tar.gz",
],
)
if "rules_cc" not in native.existing_rules():
@ -166,7 +179,11 @@ def grpc_deps():
name = "rules_cc",
sha256 = "35f2fb4ea0b3e61ad64a369de284e4fbbdcdba71836a5555abb5e194cf119509",
strip_prefix = "rules_cc-624b5d59dfb45672d4239422fa1e3de1822ee110",
url = "https://github.com/bazelbuild/rules_cc/archive/624b5d59dfb45672d4239422fa1e3de1822ee110.tar.gz", #2019-08-15
urls = [
#2019-08-15
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/rules_cc/archive/624b5d59dfb45672d4239422fa1e3de1822ee110.tar.gz",
"https://github.com/bazelbuild/rules_cc/archive/624b5d59dfb45672d4239422fa1e3de1822ee110.tar.gz",
],
)
if "com_github_gflags_gflags" not in native.existing_rules():
@ -174,7 +191,10 @@ def grpc_deps():
name = "com_github_gflags_gflags",
sha256 = "63ae70ea3e05780f7547d03503a53de3a7d2d83ad1caaa443a31cb20aea28654",
strip_prefix = "gflags-28f50e0fed19872e0fd50dd23ce2ee8cd759338e",
url = "https://github.com/gflags/gflags/archive/28f50e0fed19872e0fd50dd23ce2ee8cd759338e.tar.gz",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/gflags/gflags/archive/28f50e0fed19872e0fd50dd23ce2ee8cd759338e.tar.gz",
"https://github.com/gflags/gflags/archive/28f50e0fed19872e0fd50dd23ce2ee8cd759338e.tar.gz",
],
)
if "com_github_google_benchmark" not in native.existing_rules():
@ -182,7 +202,10 @@ def grpc_deps():
name = "com_github_google_benchmark",
sha256 = "f68aec93154d010324c05bcd8c5cc53468b87af88d87acb5ddcfaa1bba044837",
strip_prefix = "benchmark-090faecb454fbd6e6e17a75ef8146acb037118d4",
url = "https://github.com/google/benchmark/archive/090faecb454fbd6e6e17a75ef8146acb037118d4.tar.gz",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/benchmark/archive/090faecb454fbd6e6e17a75ef8146acb037118d4.tar.gz",
"https://github.com/google/benchmark/archive/090faecb454fbd6e6e17a75ef8146acb037118d4.tar.gz",
],
)
if "com_github_cares_cares" not in native.existing_rules():
@ -191,7 +214,10 @@ def grpc_deps():
build_file = "@com_github_grpc_grpc//third_party:cares/cares.BUILD",
sha256 = "e8c2751ddc70fed9dc6f999acd92e232d5846f009ee1674f8aee81f19b2b915a",
strip_prefix = "c-ares-e982924acee7f7313b4baa4ee5ec000c5e373c30",
url = "https://github.com/c-ares/c-ares/archive/e982924acee7f7313b4baa4ee5ec000c5e373c30.tar.gz",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/c-ares/c-ares/archive/e982924acee7f7313b4baa4ee5ec000c5e373c30.tar.gz",
"https://github.com/c-ares/c-ares/archive/e982924acee7f7313b4baa4ee5ec000c5e373c30.tar.gz",
],
)
if "com_google_absl" not in native.existing_rules():
@ -199,7 +225,10 @@ def grpc_deps():
name = "com_google_absl",
sha256 = "f368a8476f4e2e0eccf8a7318b98dafbe30b2600f4e3cf52636e5eb145aba06a",
strip_prefix = "abseil-cpp-df3ea785d8c30a9503321a3d35ee7d35808f190d",
url = "https://github.com/abseil/abseil-cpp/archive/df3ea785d8c30a9503321a3d35ee7d35808f190d.tar.gz",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/abseil/abseil-cpp/archive/df3ea785d8c30a9503321a3d35ee7d35808f190d.tar.gz",
"https://github.com/abseil/abseil-cpp/archive/df3ea785d8c30a9503321a3d35ee7d35808f190d.tar.gz",
],
)
if "bazel_toolchains" not in native.existing_rules():
@ -209,8 +238,8 @@ def grpc_deps():
sha256 = "0b36eef8a66f39c8dbae88e522d5bbbef49d5e66e834a982402c79962281be10",
strip_prefix = "bazel-toolchains-1.0.1",
urls = [
"https://github.com/bazelbuild/bazel-toolchains/releases/download/1.0.1/bazel-toolchains-1.0.1.tar.gz",
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/1.0.1.tar.gz",
"https://github.com/bazelbuild/bazel-toolchains/releases/download/1.0.1/bazel-toolchains-1.0.1.tar.gz",
],
)
@ -229,14 +258,20 @@ def grpc_deps():
name = "io_opencensus_cpp",
sha256 = "90d6fafa8b1a2ea613bf662731d3086e1c2ed286f458a95c81744df2dbae41b1",
strip_prefix = "opencensus-cpp-c9a4da319bc669a772928ffc55af4a61be1a1176",
url = "https://github.com/census-instrumentation/opencensus-cpp/archive/c9a4da319bc669a772928ffc55af4a61be1a1176.tar.gz",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/census-instrumentation/opencensus-cpp/archive/c9a4da319bc669a772928ffc55af4a61be1a1176.tar.gz",
"https://github.com/census-instrumentation/opencensus-cpp/archive/c9a4da319bc669a772928ffc55af4a61be1a1176.tar.gz",
],
)
if "upb" not in native.existing_rules():
http_archive(
name = "upb",
sha256 = "e9c136e56b98c8eb48ad1c9f8df4a6348e99f9f336ee6199c4259a312c2e3598",
strip_prefix = "upb-d8f3d6f9d415b31f3ce56d46791706c38fa311bc",
url = "https://github.com/protocolbuffers/upb/archive/d8f3d6f9d415b31f3ce56d46791706c38fa311bc.tar.gz",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/protocolbuffers/upb/archive/d8f3d6f9d415b31f3ce56d46791706c38fa311bc.tar.gz",
"https://github.com/protocolbuffers/upb/archive/d8f3d6f9d415b31f3ce56d46791706c38fa311bc.tar.gz",
],
)
if "envoy_api" not in native.existing_rules():
@ -244,28 +279,38 @@ def grpc_deps():
name = "envoy_api",
sha256 = "4ba23e0370ec358d1050c020e00cd020f03644a733aaf8fd85cc43d17b92236a",
strip_prefix = "data-plane-api-0487bbb43c3e8b54c7332f74ba7344d8265774f7",
url = "https://github.com/envoyproxy/data-plane-api/archive/0487bbb43c3e8b54c7332f74ba7344d8265774f7.tar.gz",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/envoyproxy/data-plane-api/archive/0487bbb43c3e8b54c7332f74ba7344d8265774f7.tar.gz",
"https://github.com/envoyproxy/data-plane-api/archive/0487bbb43c3e8b54c7332f74ba7344d8265774f7.tar.gz",
],
)
if "io_bazel_rules_go" not in native.existing_rules():
http_archive(
name = "io_bazel_rules_go",
urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.18.5/rules_go-0.18.5.tar.gz"],
sha256 = "a82a352bffae6bee4e95f68a8d80a70e87f42c4741e6a448bec11998fcc82329",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/rules_go/releases/download/0.18.5/rules_go-0.18.5.tar.gz",
"https://github.com/bazelbuild/rules_go/releases/download/0.18.5/rules_go-0.18.5.tar.gz",
],
)
if "build_bazel_rules_apple" not in native.existing_rules():
http_archive(
name = "build_bazel_rules_apple",
url = "https://github.com/bazelbuild/rules_apple/archive/b869b0d3868d78a1d4ffd866ccb304fb68aa12c3.tar.gz",
strip_prefix = "rules_apple-b869b0d3868d78a1d4ffd866ccb304fb68aa12c3",
sha256 = "bdc8e66e70b8a75da23b79f1f8c6207356df07d041d96d2189add7ee0780cf4e",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/rules_apple/archive/b869b0d3868d78a1d4ffd866ccb304fb68aa12c3.tar.gz",
"https://github.com/bazelbuild/rules_apple/archive/b869b0d3868d78a1d4ffd866ccb304fb68aa12c3.tar.gz",
],
)
if "build_bazel_apple_support" not in native.existing_rules():
http_archive(
name = "build_bazel_apple_support",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/apple_support/releases/download/0.7.1/apple_support.0.7.1.tar.gz",
"https://github.com/bazelbuild/apple_support/releases/download/0.7.1/apple_support.0.7.1.tar.gz",
],
sha256 = "122ebf7fe7d1c8e938af6aeaee0efe788a3a2449ece5a8d6a428cb18d6f88033",
@ -277,7 +322,10 @@ def grpc_deps():
build_file = "@com_github_grpc_grpc//third_party:libuv.BUILD",
sha256 = "dfb4fe1ff0b47340978490a14bf253475159ecfcbad46ab2a350c78f9ce3360f",
strip_prefix = "libuv-15ae750151ac9341e5945eb38f8982d59fb99201",
url = "https://github.com/libuv/libuv/archive/15ae750151ac9341e5945eb38f8982d59fb99201.tar.gz",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/libuv/libuv/archive/15ae750151ac9341e5945eb38f8982d59fb99201.tar.gz",
"https://github.com/libuv/libuv/archive/15ae750151ac9341e5945eb38f8982d59fb99201.tar.gz",
],
)
grpc_python_deps()
@ -301,7 +349,10 @@ def grpc_test_only_deps():
name = "com_github_twisted_twisted",
sha256 = "ca17699d0d62eafc5c28daf2c7d0a18e62ae77b4137300b6c7d7868b39b06139",
strip_prefix = "twisted-twisted-17.5.0",
url = "https://github.com/twisted/twisted/archive/twisted-17.5.0.zip",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/twisted/twisted/archive/twisted-17.5.0.zip",
"https://github.com/twisted/twisted/archive/twisted-17.5.0.zip",
],
build_file = "@com_github_grpc_grpc//third_party:twisted.BUILD",
)
@ -310,7 +361,10 @@ def grpc_test_only_deps():
name = "com_github_yaml_pyyaml",
sha256 = "6b4314b1b2051ddb9d4fcd1634e1fa9c1bb4012954273c9ff3ef689f6ec6c93e",
strip_prefix = "pyyaml-3.12",
url = "https://github.com/yaml/pyyaml/archive/3.12.zip",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/yaml/pyyaml/archive/3.12.zip",
"https://github.com/yaml/pyyaml/archive/3.12.zip",
],
build_file = "@com_github_grpc_grpc//third_party:yaml.BUILD",
)
@ -319,7 +373,10 @@ def grpc_test_only_deps():
name = "com_github_twisted_incremental",
sha256 = "f0ca93359ee70243ff7fbf2d904a6291810bd88cb80ed4aca6fa77f318a41a36",
strip_prefix = "incremental-incremental-17.5.0",
url = "https://github.com/twisted/incremental/archive/incremental-17.5.0.zip",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/twisted/incremental/archive/incremental-17.5.0.zip",
"https://github.com/twisted/incremental/archive/incremental-17.5.0.zip",
],
build_file = "@com_github_grpc_grpc//third_party:incremental.BUILD",
)
@ -328,7 +385,10 @@ def grpc_test_only_deps():
name = "com_github_zopefoundation_zope_interface",
sha256 = "e9579fc6149294339897be3aa9ecd8a29217c0b013fe6f44fcdae00e3204198a",
strip_prefix = "zope.interface-4.4.3",
url = "https://github.com/zopefoundation/zope.interface/archive/4.4.3.zip",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/zopefoundation/zope.interface/archive/4.4.3.zip",
"https://github.com/zopefoundation/zope.interface/archive/4.4.3.zip",
],
build_file = "@com_github_grpc_grpc//third_party:zope_interface.BUILD",
)
@ -337,6 +397,9 @@ def grpc_test_only_deps():
name = "com_github_twisted_constantly",
sha256 = "2702cd322161a579d2c0dbf94af4e57712eedc7bd7bbbdc554a230544f7d346c",
strip_prefix = "constantly-15.1.0",
url = "https://github.com/twisted/constantly/archive/15.1.0.zip",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/twisted/constantly/archive/15.1.0.zip",
"https://github.com/twisted/constantly/archive/15.1.0.zip",
],
build_file = "@com_github_grpc_grpc//third_party:constantly.BUILD",
)

@ -0,0 +1,63 @@
#!/bin/bash
# Copyright 2020 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.
# Script to upload github archives for bazel dependencies to GCS, creating a reliable mirror link.
# Archives are copied to "grpc-bazel-mirror" GCS bucket (https://console.cloud.google.com/storage/browser/grpc-bazel-mirror?project=grpc-testing)
# and will by downloadable with the https://storage.googleapis.com/grpc-bazel-mirror/ prefix.
#
# This script should be run each time bazel dependencies are updated.
set -e
cd $(dirname $0)/..
# Create a temp directory to hold the versioned tarball,
# and clean it up when the script exits.
tmpdir="$(mktemp -d)"
function cleanup {
rm -rf "$tmpdir"
}
trap cleanup EXIT
function upload {
local file="$1"
echo "Downloading https://${file}"
curl -L --fail --output "${tmpdir}/archive" "https://${file}"
echo "Uploading https://${file} to https://storage.googleapis.com/grpc-bazel-mirror/${file}"
gsutil cp -n "${tmpdir}/archive" "gs://grpc-bazel-mirror/${file}" # "-n" will skip existing files
rm -rf "${tmpdir}/archive"
}
# How to check that all mirror URLs work:
# 1. clean $HOME/.cache/bazel
# 2. bazel clean --expunge
# 3. bazel sync (failed downloads will print warnings)
# A specific link can be upload manually by running e.g.
# upload "github.com/google/boringssl/archive/1c2769383f027befac5b75b6cedd25daf3bf4dcf.tar.gz"
# bazel binaries used by the tools/bazel wrapper script
upload github.com/bazelbuild/bazel/releases/download/1.0.0/bazel-1.0.0-linux-x86_64
upload github.com/bazelbuild/bazel/releases/download/1.0.0/bazel-1.0.0-darwin-x86_64
upload github.com/bazelbuild/bazel/releases/download/1.0.0/bazel-1.0.0-windows-x86_64.exe
# Collect the github archives to mirror from grpc_deps.bzl
grep -o '"https://github.com/[^"]*"' bazel/grpc_deps.bzl | sed 's/^"https:\/\///' | sed 's/"$//' | while read -r line ; do
echo "Updating mirror for ${line}"
upload "${line}"
done

@ -49,6 +49,7 @@ libs:
- test/core/end2end/tests/cancel_in_a_vacuum.cc
- test/core/end2end/tests/cancel_with_status.cc
- test/core/end2end/tests/channelz.cc
- test/core/end2end/tests/client_streaming.cc
- test/core/end2end/tests/compressed_payload.cc
- test/core/end2end/tests/connectivity.cc
- test/core/end2end/tests/default_host.cc
@ -157,6 +158,7 @@ libs:
- test/core/end2end/tests/cancel_in_a_vacuum.cc
- test/core/end2end/tests/cancel_with_status.cc
- test/core/end2end/tests/channelz.cc
- test/core/end2end/tests/client_streaming.cc
- test/core/end2end/tests/compressed_payload.cc
- test/core/end2end/tests/connectivity.cc
- test/core/end2end/tests/default_host.cc
@ -300,7 +302,6 @@ libs:
- src/core/lib/gprpp/map.h
- src/core/lib/gprpp/memory.h
- src/core/lib/gprpp/mpscq.h
- src/core/lib/gprpp/string_view.h
- src/core/lib/gprpp/sync.h
- src/core/lib/gprpp/thd.h
- src/core/lib/profiling/timers.h
@ -423,6 +424,7 @@ libs:
- src/core/ext/filters/http/client/http_client_filter.h
- src/core/ext/filters/http/client_authority_filter.h
- src/core/ext/filters/http/message_compress/message_compress_filter.h
- src/core/ext/filters/http/message_compress/message_decompress_filter.h
- src/core/ext/filters/http/server/http_server_filter.h
- src/core/ext/filters/max_age/max_age_filter.h
- src/core/ext/filters/message_size/message_size_filter.h
@ -545,8 +547,6 @@ libs:
- src/core/lib/debug/trace.h
- src/core/lib/gprpp/atomic.h
- src/core/lib/gprpp/debug_location.h
- src/core/lib/gprpp/inlined_vector.h
- src/core/lib/gprpp/optional.h
- src/core/lib/gprpp/orphanable.h
- src/core/lib/gprpp/ref_counted.h
- src/core/lib/gprpp/ref_counted_ptr.h
@ -566,6 +566,7 @@ libs:
- src/core/lib/iomgr/error.h
- src/core/lib/iomgr/error_cfstream.h
- src/core/lib/iomgr/error_internal.h
- src/core/lib/iomgr/ev_apple.h
- src/core/lib/iomgr/ev_epoll1_linux.h
- src/core/lib/iomgr/ev_epollex_linux.h
- src/core/lib/iomgr/ev_poll_posix.h
@ -718,7 +719,6 @@ libs:
- src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h
- src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h
- src/core/tsi/fake_transport_security.h
- src/core/tsi/grpc_shadow_boringssl.h
- src/core/tsi/local_transport_security.h
- src/core/tsi/ssl/session_cache/ssl_session.h
- src/core/tsi/ssl/session_cache/ssl_session_cache.h
@ -756,6 +756,7 @@ libs:
- src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
- src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
- src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
- src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
- src/core/ext/filters/client_channel/lb_policy_registry.cc
- src/core/ext/filters/client_channel/local_subchannel_pool.cc
- src/core/ext/filters/client_channel/parse_address.cc
@ -795,6 +796,7 @@ libs:
- src/core/ext/filters/http/client_authority_filter.cc
- src/core/ext/filters/http/http_filters_plugin.cc
- src/core/ext/filters/http/message_compress/message_compress_filter.cc
- src/core/ext/filters/http/message_compress/message_decompress_filter.cc
- src/core/ext/filters/http/server/http_server_filter.cc
- src/core/ext/filters/max_age/max_age_filter.cc
- src/core/ext/filters/message_size/message_size_filter.cc
@ -938,6 +940,7 @@ libs:
- src/core/lib/iomgr/endpoint_pair_windows.cc
- src/core/lib/iomgr/error.cc
- src/core/lib/iomgr/error_cfstream.cc
- src/core/lib/iomgr/ev_apple.cc
- src/core/lib/iomgr/ev_epoll1_linux.cc
- src/core/lib/iomgr/ev_epollex_linux.cc
- src/core/lib/iomgr/ev_poll_posix.cc
@ -1325,6 +1328,7 @@ libs:
- src/core/ext/filters/http/client/http_client_filter.h
- src/core/ext/filters/http/client_authority_filter.h
- src/core/ext/filters/http/message_compress/message_compress_filter.h
- src/core/ext/filters/http/message_compress/message_decompress_filter.h
- src/core/ext/filters/http/server/http_server_filter.h
- src/core/ext/filters/max_age/max_age_filter.h
- src/core/ext/filters/message_size/message_size_filter.h
@ -1444,8 +1448,6 @@ libs:
- src/core/lib/debug/trace.h
- src/core/lib/gprpp/atomic.h
- src/core/lib/gprpp/debug_location.h
- src/core/lib/gprpp/inlined_vector.h
- src/core/lib/gprpp/optional.h
- src/core/lib/gprpp/orphanable.h
- src/core/lib/gprpp/ref_counted.h
- src/core/lib/gprpp/ref_counted_ptr.h
@ -1465,6 +1467,7 @@ libs:
- src/core/lib/iomgr/error.h
- src/core/lib/iomgr/error_cfstream.h
- src/core/lib/iomgr/error_internal.h
- src/core/lib/iomgr/ev_apple.h
- src/core/lib/iomgr/ev_epoll1_linux.h
- src/core/lib/iomgr/ev_epollex_linux.h
- src/core/lib/iomgr/ev_poll_posix.h
@ -1593,6 +1596,7 @@ libs:
- src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
- src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
- src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
- src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
- src/core/ext/filters/client_channel/lb_policy_registry.cc
- src/core/ext/filters/client_channel/local_subchannel_pool.cc
- src/core/ext/filters/client_channel/parse_address.cc
@ -1632,6 +1636,7 @@ libs:
- src/core/ext/filters/http/client_authority_filter.cc
- src/core/ext/filters/http/http_filters_plugin.cc
- src/core/ext/filters/http/message_compress/message_compress_filter.cc
- src/core/ext/filters/http/message_compress/message_decompress_filter.cc
- src/core/ext/filters/http/server/http_server_filter.cc
- src/core/ext/filters/max_age/max_age_filter.cc
- src/core/ext/filters/message_size/message_size_filter.cc
@ -1769,6 +1774,7 @@ libs:
- src/core/lib/iomgr/endpoint_pair_windows.cc
- src/core/lib/iomgr/error.cc
- src/core/lib/iomgr/error_cfstream.cc
- src/core/lib/iomgr/ev_apple.cc
- src/core/lib/iomgr/ev_epoll1_linux.cc
- src/core/lib/iomgr/ev_epollex_linux.cc
- src/core/lib/iomgr/ev_poll_posix.cc
@ -3881,13 +3887,8 @@ targets:
- name: num_external_connectivity_watchers_test
build: test
language: c
headers:
- test/core/end2end/data/ssl_test_data.h
headers: []
src:
- test/core/end2end/data/client_certs.cc
- test/core/end2end/data/server1_cert.cc
- test/core/end2end/data/server1_key.cc
- test/core/end2end/data/test_root_cert.cc
- test/core/surface/num_external_connectivity_watchers_test.cc
deps:
- grpc_test_util
@ -6532,19 +6533,6 @@ targets:
- benchmark
benchmark: true
defaults: benchmark
- name: optional_test
gtest: true
build: test
language: c++
headers: []
src:
- test/core/gprpp/optional_test.cc
deps:
- grpc_test_util
- grpc
- gpr
- address_sorting
- upb
- name: orphanable_test
gtest: true
build: test
@ -7252,19 +7240,6 @@ targets:
- address_sorting
- upb
uses_polling: false
- name: string_view_test
gtest: true
build: test
language: c++
headers: []
src:
- test/core/gprpp/string_view_test.cc
deps:
- grpc_test_util
- grpc
- gpr
- address_sorting
- upb
- name: test_cpp_client_credentials_test
gtest: true
build: test

@ -65,6 +65,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/lb_policy/xds/cds.cc \
src/core/ext/filters/client_channel/lb_policy/xds/eds.cc \
src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc \
src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc \
src/core/ext/filters/client_channel/lb_policy_registry.cc \
src/core/ext/filters/client_channel/local_subchannel_pool.cc \
src/core/ext/filters/client_channel/parse_address.cc \
@ -104,6 +105,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/http/client_authority_filter.cc \
src/core/ext/filters/http/http_filters_plugin.cc \
src/core/ext/filters/http/message_compress/message_compress_filter.cc \
src/core/ext/filters/http/message_compress/message_decompress_filter.cc \
src/core/ext/filters/http/server/http_server_filter.cc \
src/core/ext/filters/max_age/max_age_filter.cc \
src/core/ext/filters/message_size/message_size_filter.cc \
@ -286,6 +288,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/iomgr/endpoint_pair_windows.cc \
src/core/lib/iomgr/error.cc \
src/core/lib/iomgr/error_cfstream.cc \
src/core/lib/iomgr/ev_apple.cc \
src/core/lib/iomgr/ev_epoll1_linux.cc \
src/core/lib/iomgr/ev_epollex_linux.cc \
src/core/lib/iomgr/ev_poll_posix.cc \

@ -34,6 +34,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\lb_policy\\xds\\cds.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\xds\\eds.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\xds\\lrs.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\xds\\xds_routing.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy_registry.cc " +
"src\\core\\ext\\filters\\client_channel\\local_subchannel_pool.cc " +
"src\\core\\ext\\filters\\client_channel\\parse_address.cc " +
@ -73,6 +74,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\http\\client_authority_filter.cc " +
"src\\core\\ext\\filters\\http\\http_filters_plugin.cc " +
"src\\core\\ext\\filters\\http\\message_compress\\message_compress_filter.cc " +
"src\\core\\ext\\filters\\http\\message_compress\\message_decompress_filter.cc " +
"src\\core\\ext\\filters\\http\\server\\http_server_filter.cc " +
"src\\core\\ext\\filters\\max_age\\max_age_filter.cc " +
"src\\core\\ext\\filters\\message_size\\message_size_filter.cc " +
@ -255,6 +257,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\iomgr\\endpoint_pair_windows.cc " +
"src\\core\\lib\\iomgr\\error.cc " +
"src\\core\\lib\\iomgr\\error_cfstream.cc " +
"src\\core\\lib\\iomgr\\ev_apple.cc " +
"src\\core\\lib\\iomgr\\ev_epoll1_linux.cc " +
"src\\core\\lib\\iomgr\\ev_epollex_linux.cc " +
"src\\core\\lib\\iomgr\\ev_poll_posix.cc " +

@ -28,13 +28,17 @@ sys.path.insert(0, os.path.join(PYTHON_FOLDER, 'grpcio_testing'))
# -- Project information -----------------------------------------------------
project = 'gRPC Python'
copyright = '2018, The gRPC Authors'
copyright = '2020, The gRPC Authors'
author = 'The gRPC Authors'
# Import generated grpc_version after the path been modified
import grpc_version
version = ".".join(grpc_version.VERSION.split(".")[:3])
version = '.'.join(grpc_version.VERSION.split('.')[:3])
release = grpc_version.VERSION
if 'dev' in grpc_version.VERSION:
branch = 'master'
else:
branch = 'v%s.%s.x' % tuple(grpc_version.VERSION.split('.')[:2])
# -- General configuration ---------------------------------------------------
@ -100,3 +104,7 @@ epub_exclude_files = ['search.html']
# -- Options for todo extension ----------------------------------------------
todo_include_todos = True
# -- Options for substitutions -----------------------------------------------
rst_epilog = '.. |grpc_types_link| replace:: https://github.com/grpc/grpc/blob/%s/include/grpc/impl/codegen/grpc_types.h' % branch

@ -14,3 +14,37 @@ Glossary
metadata
A sequence of metadatum.
serializer
A callable function that encodes an object into bytes. Applications are
allowed to provide any customized serializer, so there isn't a restriction
for the input object (i.e. even ``None``). On the server-side, the
serializer is invoked with server handler's return value; on the
client-side, the serializer is invoked with outbound message objects.
deserializer
A callable function that decodes bytes into an object. Same as serializer,
the returned object doesn't have restrictions (i.e. ``None`` allowed). The
deserializer is invoked with inbound message bytes on both the server side
and the client-side.
wait_for_ready
If an RPC is issued but the channel is in the TRANSIENT_FAILURE or SHUTDOWN
states, the library cannot transmit the RPC at the moment. By default, the
gRPC library will fail such RPCs immediately. This is known as "fail fast."
RPCs will not fail as a result of the channel being in other states
(CONNECTING, READY, or IDLE).
When the wait_for_ready option is specified, the library will queue RPCs
until the channel is READY. Any submitted RPCs may still fail before the
READY state is reached for other reasons, e.g., the client channel has been
shut down or the RPC's deadline has been reached.
channel_arguments
A list of key-value pairs to configure the underlying gRPC Core channel or
server object. Channel arguments are meant for advanced usages and contain
experimental API (some may not labeled as experimental). Full list of
available channel arguments and documentation can be found under the
"grpc_arg_keys" section of "grpc_types.h" header file (|grpc_types_link|).
For example, if you want to disable TCP port reuse, you may construct
channel arguments like: ``options = (('grpc.so_reuseport', 0),)``.

@ -25,6 +25,9 @@ The code for the xDS test client can be at:
Clients should accept these arguments:
* --fail_on_failed_rpcs=BOOL
* If true, the client should exit with a non-zero return code if any RPCs
fail. Default is false.
* --num_channels=CHANNELS
* The number of channels to create to the server.
* --qps=QPS
@ -88,6 +91,7 @@ Client parameters:
1. --num_channels=1
1. --qps=10
1. --fail_on_failed_rpc=true
Load balancer configuration:
@ -106,6 +110,7 @@ Client parameters:
1. --num_channels=1
1. --qps=10
1. --fail_on_failed_rpc=true
Load balancer configuration:
@ -220,6 +225,7 @@ Client parameters:
1. --num_channels=1
1. --qps=10
1. --fail_on_failed_rpc=true
Load balancer configuration:
@ -268,6 +274,7 @@ Client parameters:
1. --num_channels=1
1. --qps=10
1. --fail_on_failed_rpc=true
Load balancer configuration:

@ -274,6 +274,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/http/client/http_client_filter.h',
'src/core/ext/filters/http/client_authority_filter.h',
'src/core/ext/filters/http/message_compress/message_compress_filter.h',
'src/core/ext/filters/http/message_compress/message_decompress_filter.h',
'src/core/ext/filters/http/server/http_server_filter.h',
'src/core/ext/filters/max_age/max_age_filter.h',
'src/core/ext/filters/message_size/message_size_filter.h',
@ -417,16 +418,13 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/global_config_env.h',
'src/core/lib/gprpp/global_config_generic.h',
'src/core/lib/gprpp/host_port.h',
'src/core/lib/gprpp/inlined_vector.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/map.h',
'src/core/lib/gprpp/memory.h',
'src/core/lib/gprpp/mpscq.h',
'src/core/lib/gprpp/optional.h',
'src/core/lib/gprpp/orphanable.h',
'src/core/lib/gprpp/ref_counted.h',
'src/core/lib/gprpp/ref_counted_ptr.h',
'src/core/lib/gprpp/string_view.h',
'src/core/lib/gprpp/sync.h',
'src/core/lib/gprpp/thd.h',
'src/core/lib/http/format_request.h',
@ -445,6 +443,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/error.h',
'src/core/lib/iomgr/error_cfstream.h',
'src/core/lib/iomgr/error_internal.h',
'src/core/lib/iomgr/ev_apple.h',
'src/core/lib/iomgr/ev_epoll1_linux.h',
'src/core/lib/iomgr/ev_epollex_linux.h',
'src/core/lib/iomgr/ev_poll_posix.h',
@ -598,7 +597,6 @@ Pod::Spec.new do |s|
'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
'src/core/tsi/fake_transport_security.h',
'src/core/tsi/grpc_shadow_boringssl.h',
'src/core/tsi/local_transport_security.h',
'src/core/tsi/ssl/session_cache/ssl_session.h',
'src/core/tsi/ssl/session_cache/ssl_session_cache.h',
@ -725,6 +723,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/http/client/http_client_filter.h',
'src/core/ext/filters/http/client_authority_filter.h',
'src/core/ext/filters/http/message_compress/message_compress_filter.h',
'src/core/ext/filters/http/message_compress/message_decompress_filter.h',
'src/core/ext/filters/http/server/http_server_filter.h',
'src/core/ext/filters/max_age/max_age_filter.h',
'src/core/ext/filters/message_size/message_size_filter.h',
@ -868,16 +867,13 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/global_config_env.h',
'src/core/lib/gprpp/global_config_generic.h',
'src/core/lib/gprpp/host_port.h',
'src/core/lib/gprpp/inlined_vector.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/map.h',
'src/core/lib/gprpp/memory.h',
'src/core/lib/gprpp/mpscq.h',
'src/core/lib/gprpp/optional.h',
'src/core/lib/gprpp/orphanable.h',
'src/core/lib/gprpp/ref_counted.h',
'src/core/lib/gprpp/ref_counted_ptr.h',
'src/core/lib/gprpp/string_view.h',
'src/core/lib/gprpp/sync.h',
'src/core/lib/gprpp/thd.h',
'src/core/lib/http/format_request.h',
@ -896,6 +892,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/error.h',
'src/core/lib/iomgr/error_cfstream.h',
'src/core/lib/iomgr/error_internal.h',
'src/core/lib/iomgr/ev_apple.h',
'src/core/lib/iomgr/ev_epoll1_linux.h',
'src/core/lib/iomgr/ev_epollex_linux.h',
'src/core/lib/iomgr/ev_poll_posix.h',
@ -1049,7 +1046,6 @@ Pod::Spec.new do |s|
'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
'src/core/tsi/fake_transport_security.h',
'src/core/tsi/grpc_shadow_boringssl.h',
'src/core/tsi/local_transport_security.h',
'src/core/tsi/ssl/session_cache/ssl_session.h',
'src/core/tsi/ssl/session_cache/ssl_session_cache.h',

@ -172,7 +172,7 @@ Pod::Spec.new do |s|
ss.header_mappings_dir = '.'
ss.libraries = 'z'
ss.dependency "#{s.name}/Interface", version
ss.dependency 'BoringSSL-GRPC', '0.0.7'
ss.dependency 'BoringSSL-GRPC', '0.0.8'
abseil_version = '1.20200225.0'
ss.dependency 'abseil/container/inlined_vector', abseil_version
ss.dependency 'abseil/memory/memory', abseil_version
@ -180,7 +180,7 @@ Pod::Spec.new do |s|
ss.dependency 'abseil/strings/strings', abseil_version
ss.dependency 'abseil/time/time', abseil_version
ss.dependency 'abseil/types/optional', abseil_version
ss.compiler_flags = '-DGRPC_SHADOW_BORINGSSL_SYMBOLS'
ss.compiler_flags = '-DBORINGSSL_PREFIX=GRPC'
ss.source_files = 'src/core/ext/filters/census/grpc_context.cc',
'src/core/ext/filters/client_channel/backend_metric.cc',
@ -231,6 +231,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/lb_policy/xds/eds.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/xds.h',
'src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc',
'src/core/ext/filters/client_channel/lb_policy_factory.h',
'src/core/ext/filters/client_channel/lb_policy_registry.cc',
'src/core/ext/filters/client_channel/lb_policy_registry.h',
@ -301,6 +302,8 @@ Pod::Spec.new do |s|
'src/core/ext/filters/http/http_filters_plugin.cc',
'src/core/ext/filters/http/message_compress/message_compress_filter.cc',
'src/core/ext/filters/http/message_compress/message_compress_filter.h',
'src/core/ext/filters/http/message_compress/message_decompress_filter.cc',
'src/core/ext/filters/http/message_compress/message_decompress_filter.h',
'src/core/ext/filters/http/server/http_server_filter.cc',
'src/core/ext/filters/http/server/http_server_filter.h',
'src/core/ext/filters/max_age/max_age_filter.cc',
@ -607,17 +610,14 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/global_config_generic.h',
'src/core/lib/gprpp/host_port.cc',
'src/core/lib/gprpp/host_port.h',
'src/core/lib/gprpp/inlined_vector.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/map.h',
'src/core/lib/gprpp/memory.h',
'src/core/lib/gprpp/mpscq.cc',
'src/core/lib/gprpp/mpscq.h',
'src/core/lib/gprpp/optional.h',
'src/core/lib/gprpp/orphanable.h',
'src/core/lib/gprpp/ref_counted.h',
'src/core/lib/gprpp/ref_counted_ptr.h',
'src/core/lib/gprpp/string_view.h',
'src/core/lib/gprpp/sync.h',
'src/core/lib/gprpp/thd.h',
'src/core/lib/gprpp/thd_posix.cc',
@ -654,6 +654,8 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/error_cfstream.cc',
'src/core/lib/iomgr/error_cfstream.h',
'src/core/lib/iomgr/error_internal.h',
'src/core/lib/iomgr/ev_apple.cc',
'src/core/lib/iomgr/ev_apple.h',
'src/core/lib/iomgr/ev_epoll1_linux.cc',
'src/core/lib/iomgr/ev_epoll1_linux.h',
'src/core/lib/iomgr/ev_epollex_linux.cc',
@ -996,7 +998,6 @@ Pod::Spec.new do |s|
'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
'src/core/tsi/fake_transport_security.cc',
'src/core/tsi/fake_transport_security.h',
'src/core/tsi/grpc_shadow_boringssl.h',
'src/core/tsi/local_transport_security.cc',
'src/core/tsi/local_transport_security.h',
'src/core/tsi/ssl/session_cache/ssl_session.h',
@ -1078,6 +1079,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/http/client/http_client_filter.h',
'src/core/ext/filters/http/client_authority_filter.h',
'src/core/ext/filters/http/message_compress/message_compress_filter.h',
'src/core/ext/filters/http/message_compress/message_decompress_filter.h',
'src/core/ext/filters/http/server/http_server_filter.h',
'src/core/ext/filters/max_age/max_age_filter.h',
'src/core/ext/filters/message_size/message_size_filter.h',
@ -1221,16 +1223,13 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/global_config_env.h',
'src/core/lib/gprpp/global_config_generic.h',
'src/core/lib/gprpp/host_port.h',
'src/core/lib/gprpp/inlined_vector.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/map.h',
'src/core/lib/gprpp/memory.h',
'src/core/lib/gprpp/mpscq.h',
'src/core/lib/gprpp/optional.h',
'src/core/lib/gprpp/orphanable.h',
'src/core/lib/gprpp/ref_counted.h',
'src/core/lib/gprpp/ref_counted_ptr.h',
'src/core/lib/gprpp/string_view.h',
'src/core/lib/gprpp/sync.h',
'src/core/lib/gprpp/thd.h',
'src/core/lib/http/format_request.h',
@ -1249,6 +1248,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/error.h',
'src/core/lib/iomgr/error_cfstream.h',
'src/core/lib/iomgr/error_internal.h',
'src/core/lib/iomgr/ev_apple.h',
'src/core/lib/iomgr/ev_epoll1_linux.h',
'src/core/lib/iomgr/ev_epollex_linux.h',
'src/core/lib/iomgr/ev_poll_posix.h',
@ -1402,7 +1402,6 @@ Pod::Spec.new do |s|
'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
'src/core/tsi/fake_transport_security.h',
'src/core/tsi/grpc_shadow_boringssl.h',
'src/core/tsi/local_transport_security.h',
'src/core/tsi/ssl/session_cache/ssl_session.h',
'src/core/tsi/ssl/session_cache/ssl_session_cache.h',
@ -1482,6 +1481,7 @@ Pod::Spec.new do |s|
'test/core/end2end/tests/cancel_test_helpers.h',
'test/core/end2end/tests/cancel_with_status.cc',
'test/core/end2end/tests/channelz.cc',
'test/core/end2end/tests/client_streaming.cc',
'test/core/end2end/tests/compressed_payload.cc',
'test/core/end2end/tests/connectivity.cc',
'test/core/end2end/tests/default_host.cc',

@ -153,6 +153,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/lb_policy/xds/eds.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/xds/xds.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy_factory.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy_registry.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy_registry.h )
@ -223,6 +224,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/http/http_filters_plugin.cc )
s.files += %w( src/core/ext/filters/http/message_compress/message_compress_filter.cc )
s.files += %w( src/core/ext/filters/http/message_compress/message_compress_filter.h )
s.files += %w( src/core/ext/filters/http/message_compress/message_decompress_filter.cc )
s.files += %w( src/core/ext/filters/http/message_compress/message_decompress_filter.h )
s.files += %w( src/core/ext/filters/http/server/http_server_filter.cc )
s.files += %w( src/core/ext/filters/http/server/http_server_filter.h )
s.files += %w( src/core/ext/filters/max_age/max_age_filter.cc )
@ -529,17 +532,14 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/gprpp/global_config_generic.h )
s.files += %w( src/core/lib/gprpp/host_port.cc )
s.files += %w( src/core/lib/gprpp/host_port.h )
s.files += %w( src/core/lib/gprpp/inlined_vector.h )
s.files += %w( src/core/lib/gprpp/manual_constructor.h )
s.files += %w( src/core/lib/gprpp/map.h )
s.files += %w( src/core/lib/gprpp/memory.h )
s.files += %w( src/core/lib/gprpp/mpscq.cc )
s.files += %w( src/core/lib/gprpp/mpscq.h )
s.files += %w( src/core/lib/gprpp/optional.h )
s.files += %w( src/core/lib/gprpp/orphanable.h )
s.files += %w( src/core/lib/gprpp/ref_counted.h )
s.files += %w( src/core/lib/gprpp/ref_counted_ptr.h )
s.files += %w( src/core/lib/gprpp/string_view.h )
s.files += %w( src/core/lib/gprpp/sync.h )
s.files += %w( src/core/lib/gprpp/thd.h )
s.files += %w( src/core/lib/gprpp/thd_posix.cc )
@ -576,6 +576,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/error_cfstream.cc )
s.files += %w( src/core/lib/iomgr/error_cfstream.h )
s.files += %w( src/core/lib/iomgr/error_internal.h )
s.files += %w( src/core/lib/iomgr/ev_apple.cc )
s.files += %w( src/core/lib/iomgr/ev_apple.h )
s.files += %w( src/core/lib/iomgr/ev_epoll1_linux.cc )
s.files += %w( src/core/lib/iomgr/ev_epoll1_linux.h )
s.files += %w( src/core/lib/iomgr/ev_epollex_linux.cc )
@ -918,7 +920,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h )
s.files += %w( src/core/tsi/fake_transport_security.cc )
s.files += %w( src/core/tsi/fake_transport_security.h )
s.files += %w( src/core/tsi/grpc_shadow_boringssl.h )
s.files += %w( src/core/tsi/local_transport_security.cc )
s.files += %w( src/core/tsi/local_transport_security.h )
s.files += %w( src/core/tsi/ssl/session_cache/ssl_session.h )

@ -198,6 +198,7 @@
'test/core/end2end/tests/cancel_in_a_vacuum.cc',
'test/core/end2end/tests/cancel_with_status.cc',
'test/core/end2end/tests/channelz.cc',
'test/core/end2end/tests/client_streaming.cc',
'test/core/end2end/tests/compressed_payload.cc',
'test/core/end2end/tests/connectivity.cc',
'test/core/end2end/tests/default_host.cc',
@ -299,6 +300,7 @@
'test/core/end2end/tests/cancel_in_a_vacuum.cc',
'test/core/end2end/tests/cancel_with_status.cc',
'test/core/end2end/tests/channelz.cc',
'test/core/end2end/tests/client_streaming.cc',
'test/core/end2end/tests/compressed_payload.cc',
'test/core/end2end/tests/connectivity.cc',
'test/core/end2end/tests/default_host.cc',
@ -458,6 +460,7 @@
'src/core/ext/filters/client_channel/lb_policy/xds/cds.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/eds.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc',
'src/core/ext/filters/client_channel/lb_policy_registry.cc',
'src/core/ext/filters/client_channel/local_subchannel_pool.cc',
'src/core/ext/filters/client_channel/parse_address.cc',
@ -497,6 +500,7 @@
'src/core/ext/filters/http/client_authority_filter.cc',
'src/core/ext/filters/http/http_filters_plugin.cc',
'src/core/ext/filters/http/message_compress/message_compress_filter.cc',
'src/core/ext/filters/http/message_compress/message_decompress_filter.cc',
'src/core/ext/filters/http/server/http_server_filter.cc',
'src/core/ext/filters/max_age/max_age_filter.cc',
'src/core/ext/filters/message_size/message_size_filter.cc',
@ -640,6 +644,7 @@
'src/core/lib/iomgr/endpoint_pair_windows.cc',
'src/core/lib/iomgr/error.cc',
'src/core/lib/iomgr/error_cfstream.cc',
'src/core/lib/iomgr/ev_apple.cc',
'src/core/lib/iomgr/ev_epoll1_linux.cc',
'src/core/lib/iomgr/ev_epollex_linux.cc',
'src/core/lib/iomgr/ev_poll_posix.cc',
@ -953,6 +958,7 @@
'src/core/ext/filters/client_channel/lb_policy/xds/cds.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/eds.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc',
'src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc',
'src/core/ext/filters/client_channel/lb_policy_registry.cc',
'src/core/ext/filters/client_channel/local_subchannel_pool.cc',
'src/core/ext/filters/client_channel/parse_address.cc',
@ -992,6 +998,7 @@
'src/core/ext/filters/http/client_authority_filter.cc',
'src/core/ext/filters/http/http_filters_plugin.cc',
'src/core/ext/filters/http/message_compress/message_compress_filter.cc',
'src/core/ext/filters/http/message_compress/message_decompress_filter.cc',
'src/core/ext/filters/http/server/http_server_filter.cc',
'src/core/ext/filters/max_age/max_age_filter.cc',
'src/core/ext/filters/message_size/message_size_filter.cc',
@ -1129,6 +1136,7 @@
'src/core/lib/iomgr/endpoint_pair_windows.cc',
'src/core/lib/iomgr/error.cc',
'src/core/lib/iomgr/error_cfstream.cc',
'src/core/lib/iomgr/ev_apple.cc',
'src/core/lib/iomgr/ev_epoll1_linux.cc',
'src/core/lib/iomgr/ev_epollex_linux.cc',
'src/core/lib/iomgr/ev_poll_posix.cc',

@ -174,6 +174,11 @@ typedef struct {
/** Enable/disable support for per-message compression. Defaults to 1, unless
GRPC_ARG_MINIMAL_STACK is enabled, in which case it defaults to 0. */
#define GRPC_ARG_ENABLE_PER_MESSAGE_COMPRESSION "grpc.per_message_compression"
/** Experimental Arg. Enable/disable support for per-message decompression.
Defaults to 1. If disabled, decompression will not be performed and the
application will see the compressed message in the byte buffer. */
#define GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION \
"grpc.per_message_decompression"
/** Enable/disable support for deadline checking. Defaults to 1, unless
GRPC_ARG_MINIMAL_STACK is enabled, in which case it defaults to 0 */
#define GRPC_ARG_ENABLE_DEADLINE_CHECKS "grpc.enable_deadline_checking"
@ -354,6 +359,11 @@ typedef struct {
* The default is 15 seconds. */
#define GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS \
"grpc.xds_resource_does_not_exist_timeout_ms"
/* If set, enable xds routing policy. This boolean argument is currently
* disabled by default; however, it will be changed to enabled by default
* once the functionality proves stable. This arg will eventually
* be removed completely. */
#define GRPC_ARG_XDS_ROUTING_ENABLED "grpc.xds_routing_enabled"
/** If non-zero, grpc server's cronet compression workaround will be enabled */
#define GRPC_ARG_WORKAROUND_CRONET_COMPRESSION \
"grpc.workaround.cronet_compression"

@ -291,6 +291,13 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
grpc_impl::ServerInitializer* initializer();
// Functions to manage the server shutdown ref count. Things that increase
// the ref count are the running state of the server (take a ref at start and
// drop it at shutdown) and each running callback RPC.
void Ref();
void UnrefWithPossibleNotify() /* LOCKS_EXCLUDED(mu_) */;
void UnrefAndWaitLocked() /* EXCLUSIVE_LOCKS_REQUIRED(mu_) */;
std::vector<std::shared_ptr<grpc::internal::ExternalConnectionAcceptorImpl>>
acceptors_;
@ -315,16 +322,6 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
/// the \a sync_server_cqs)
std::vector<std::unique_ptr<SyncRequestThreadManager>> sync_req_mgrs_;
// Outstanding unmatched callback requests, indexed by method.
// NOTE: Using a gpr_atm rather than atomic_int because atomic_int isn't
// copyable or movable and thus will cause compilation errors. We
// actually only want to extend the vector before the threaded use
// starts, but this is still a limitation.
std::vector<gpr_atm> callback_unmatched_reqs_count_;
// List of callback requests to start when server actually starts.
std::list<CallbackRequestBase*> callback_reqs_to_start_;
#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL
// For registering experimental callback generic service; remove when that
// method longer experimental
@ -336,25 +333,18 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
bool started_;
bool shutdown_;
bool shutdown_notified_; // Was notify called on the shutdown_cv_
grpc::internal::CondVar shutdown_done_cv_;
bool shutdown_done_ = false;
std::atomic_int shutdown_refs_outstanding_{1};
grpc::internal::CondVar shutdown_cv_;
// It is ok (but not required) to nest callback_reqs_mu_ under mu_ .
// Incrementing callback_reqs_outstanding_ is ok without a lock but it must be
// decremented under the lock in case it is the last request and enables the
// server shutdown. The increment is performance-critical since it happens
// during periods of increasing load; the decrement happens only when memory
// is maxed out, during server shutdown, or (possibly in a future version)
// during decreasing load, so it is less performance-critical.
grpc::internal::Mutex callback_reqs_mu_;
grpc::internal::CondVar callback_reqs_done_cv_;
std::atomic<intptr_t> callback_reqs_outstanding_{0};
std::shared_ptr<GlobalCallbacks> global_callbacks_;
std::vector<grpc::string> services_;
bool has_async_generic_service_{false};
bool has_callback_generic_service_{false};
bool has_async_generic_service_ = false;
bool has_callback_generic_service_ = false;
bool has_callback_methods_ = false;
// Pointer to the wrapped grpc_server.
grpc_server* server_;
@ -383,8 +373,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
// with this server (if any). It is set on the first call to CallbackCQ().
// It is _not owned_ by the server; ownership belongs with its internal
// shutdown callback tag (invoked when the CQ is fully shutdown).
// It is protected by mu_
CompletionQueue* callback_cq_ = nullptr;
CompletionQueue* callback_cq_ /* GUARDED_BY(mu_) */ = nullptr;
// List of CQs passed in by user that must be Shutdown only after Server is
// Shutdown. Even though this is only used with NDEBUG, instantiate it in all

@ -133,6 +133,7 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/xds/eds.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/xds/xds.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_registry.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_registry.h" role="src" />
@ -203,6 +204,8 @@
<file baseinstalldir="/" name="src/core/ext/filters/http/http_filters_plugin.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/message_compress/message_compress_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/message_compress/message_compress_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/message_compress/message_decompress_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/message_compress/message_decompress_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/server/http_server_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/server/http_server_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/max_age/max_age_filter.cc" role="src" />
@ -509,17 +512,14 @@
<file baseinstalldir="/" name="src/core/lib/gprpp/global_config_generic.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/host_port.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/host_port.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/inlined_vector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/manual_constructor.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/map.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/memory.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/mpscq.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/mpscq.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/optional.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/orphanable.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/ref_counted.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/ref_counted_ptr.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/string_view.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/sync.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/thd.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/thd_posix.cc" role="src" />
@ -556,6 +556,8 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/error_cfstream.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/error_cfstream.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/error_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_apple.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_apple.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll1_linux.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll1_linux.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollex_linux.cc" role="src" />
@ -898,7 +900,6 @@
<file baseinstalldir="/" name="src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/fake_transport_security.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/fake_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/grpc_shadow_boringssl.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/local_transport_security.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/local_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/ssl/session_cache/ssl_session.h" role="src" />

@ -11,7 +11,6 @@
# 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.
"""A setup module for the GRPC Python package."""
from distutils import cygwinccompiler
from distutils import extension as _extension
@ -37,23 +36,30 @@ egg_info.manifest_maker.template = 'PYTHON-MANIFEST.in'
PY3 = sys.version_info.major == 3
PYTHON_STEM = os.path.join('src', 'python', 'grpcio')
CORE_INCLUDE = ('include', '.',)
CORE_INCLUDE = (
'include',
'.',
)
ABSL_INCLUDE = (os.path.join('third_party', 'abseil-cpp'),)
ADDRESS_SORTING_INCLUDE = (os.path.join('third_party', 'address_sorting', 'include'),)
ADDRESS_SORTING_INCLUDE = (os.path.join('third_party', 'address_sorting',
'include'),)
CARES_INCLUDE = (
os.path.join('third_party', 'cares'),
os.path.join('third_party', 'cares', 'cares'),)
os.path.join('third_party', 'cares', 'cares'),
)
if 'darwin' in sys.platform:
CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_darwin'),)
CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_darwin'),)
if 'freebsd' in sys.platform:
CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_freebsd'),)
CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_freebsd'),)
if 'linux' in sys.platform:
CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_linux'),)
CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_linux'),)
if 'openbsd' in sys.platform:
CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_openbsd'),)
SSL_INCLUDE = (os.path.join('third_party', 'boringssl-with-bazel', 'src', 'include'),)
CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_openbsd'),)
SSL_INCLUDE = (os.path.join('third_party', 'boringssl-with-bazel', 'src',
'include'),)
UPB_INCLUDE = (os.path.join('third_party', 'upb'),)
UPB_GRPC_GENERATED_INCLUDE = (os.path.join('src', 'core', 'ext', 'upb-generated'),)
UPB_GRPC_GENERATED_INCLUDE = (os.path.join('src', 'core', 'ext',
'upb-generated'),)
ZLIB_INCLUDE = (os.path.join('third_party', 'zlib'),)
README = os.path.join(PYTHON_STEM, 'README.rst')
@ -79,7 +85,6 @@ CLASSIFIERS = [
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
@ -94,7 +99,6 @@ CLASSIFIERS = [
# present, then it will still attempt to use Cython.
BUILD_WITH_CYTHON = os.environ.get('GRPC_PYTHON_BUILD_WITH_CYTHON', False)
# Export this variable to use the system installation of openssl. You need to
# have the header files installed (in /usr/include/openssl) and during
# runtime, the shared library must be installed
@ -104,8 +108,7 @@ BUILD_WITH_SYSTEM_OPENSSL = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_OPENSSL',
# Export this variable to use the system installation of zlib. You need to
# have the header files installed (in /usr/include/) and during
# runtime, the shared library must be installed
BUILD_WITH_SYSTEM_ZLIB = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_ZLIB',
False)
BUILD_WITH_SYSTEM_ZLIB = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_ZLIB', False)
# Export this variable to use the system installation of cares. You need to
# have the header files installed (in /usr/include/) and during
@ -124,34 +127,36 @@ BUILD_WITH_SYSTEM_CARES = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_CARES',
# make HAS_SYSTEM_OPENSSL_ALPN=0
#
# TODO(ericgribkoff) Respect the BUILD_WITH_SYSTEM_* flags alongside this option
USE_PREBUILT_GRPC_CORE = os.environ.get(
'GRPC_PYTHON_USE_PREBUILT_GRPC_CORE', False)
USE_PREBUILT_GRPC_CORE = os.environ.get('GRPC_PYTHON_USE_PREBUILT_GRPC_CORE',
False)
# If this environmental variable is set, GRPC will not try to be compatible with
# libc versions old than the one it was compiled against.
DISABLE_LIBC_COMPATIBILITY = os.environ.get('GRPC_PYTHON_DISABLE_LIBC_COMPATIBILITY', False)
DISABLE_LIBC_COMPATIBILITY = os.environ.get(
'GRPC_PYTHON_DISABLE_LIBC_COMPATIBILITY', False)
# Environment variable to determine whether or not to enable coverage analysis
# in Cython modules.
ENABLE_CYTHON_TRACING = os.environ.get(
'GRPC_PYTHON_ENABLE_CYTHON_TRACING', False)
ENABLE_CYTHON_TRACING = os.environ.get('GRPC_PYTHON_ENABLE_CYTHON_TRACING',
False)
# Environment variable specifying whether or not there's interest in setting up
# documentation building.
ENABLE_DOCUMENTATION_BUILD = os.environ.get(
'GRPC_PYTHON_ENABLE_DOCUMENTATION_BUILD', False)
def check_linker_need_libatomic():
"""Test if linker on system needs libatomic."""
code_test = (b'#include <atomic>\n' +
b'int main() { return std::atomic<int64_t>{}; }')
cc_test = subprocess.Popen(['cc', '-x', 'c++', '-std=c++11', '-'],
stdin=PIPE,
stdout=PIPE,
stderr=PIPE)
cc_test.communicate(input=code_test)
return cc_test.returncode != 0
"""Test if linker on system needs libatomic."""
code_test = (b'#include <atomic>\n' +
b'int main() { return std::atomic<int64_t>{}; }')
cc_test = subprocess.Popen(['cc', '-x', 'c++', '-std=c++11', '-'],
stdin=PIPE,
stdout=PIPE,
stderr=PIPE)
cc_test.communicate(input=code_test)
return cc_test.returncode != 0
# There are some situations (like on Windows) where CC, CFLAGS, and LDFLAGS are
# entirely ignored/dropped/forgotten by distutils and its Cygwin/MinGW support.
@ -163,40 +168,40 @@ def check_linker_need_libatomic():
EXTRA_ENV_COMPILE_ARGS = os.environ.get('GRPC_PYTHON_CFLAGS', None)
EXTRA_ENV_LINK_ARGS = os.environ.get('GRPC_PYTHON_LDFLAGS', None)
if EXTRA_ENV_COMPILE_ARGS is None:
EXTRA_ENV_COMPILE_ARGS = ' -std=c++11'
if 'win32' in sys.platform:
if sys.version_info < (3, 5):
EXTRA_ENV_COMPILE_ARGS += ' -D_hypot=hypot'
# We use define flags here and don't directly add to DEFINE_MACROS below to
# ensure that the expert user/builder has a way of turning it off (via the
# envvars) without adding yet more GRPC-specific envvars.
# See https://sourceforge.net/p/mingw-w64/bugs/363/
if '32' in platform.architecture()[0]:
EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s'
else:
EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64'
else:
# We need to statically link the C++ Runtime, only the C runtime is
# available dynamically
EXTRA_ENV_COMPILE_ARGS += ' /MT'
elif "linux" in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
elif "darwin" in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -stdlib=libc++ -fvisibility=hidden -fno-wrapv -fno-exceptions'
EXTRA_ENV_COMPILE_ARGS = ' -std=c++11'
if 'win32' in sys.platform:
if sys.version_info < (3, 5):
EXTRA_ENV_COMPILE_ARGS += ' -D_hypot=hypot'
# We use define flags here and don't directly add to DEFINE_MACROS below to
# ensure that the expert user/builder has a way of turning it off (via the
# envvars) without adding yet more GRPC-specific envvars.
# See https://sourceforge.net/p/mingw-w64/bugs/363/
if '32' in platform.architecture()[0]:
EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s'
else:
EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64'
else:
# We need to statically link the C++ Runtime, only the C runtime is
# available dynamically
EXTRA_ENV_COMPILE_ARGS += ' /MT'
elif "linux" in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
elif "darwin" in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -stdlib=libc++ -fvisibility=hidden -fno-wrapv -fno-exceptions'
if EXTRA_ENV_LINK_ARGS is None:
EXTRA_ENV_LINK_ARGS = ''
if "linux" in sys.platform or "darwin" in sys.platform:
EXTRA_ENV_LINK_ARGS += ' -lpthread'
if check_linker_need_libatomic():
EXTRA_ENV_LINK_ARGS += ' -latomic'
elif "win32" in sys.platform and sys.version_info < (3, 5):
msvcr = cygwinccompiler.get_msvcr()[0]
EXTRA_ENV_LINK_ARGS += (
' -static-libgcc -static-libstdc++ -mcrtdll={msvcr}'
' -static -lshlwapi'.format(msvcr=msvcr))
if "linux" in sys.platform:
EXTRA_ENV_LINK_ARGS += ' -Wl,-wrap,memcpy -static-libgcc'
EXTRA_ENV_LINK_ARGS = ''
if "linux" in sys.platform or "darwin" in sys.platform:
EXTRA_ENV_LINK_ARGS += ' -lpthread'
if check_linker_need_libatomic():
EXTRA_ENV_LINK_ARGS += ' -latomic'
elif "win32" in sys.platform and sys.version_info < (3, 5):
msvcr = cygwinccompiler.get_msvcr()[0]
EXTRA_ENV_LINK_ARGS += (
' -static-libgcc -static-libstdc++ -mcrtdll={msvcr}'
' -static -lshlwapi'.format(msvcr=msvcr))
if "linux" in sys.platform:
EXTRA_ENV_LINK_ARGS += ' -Wl,-wrap,memcpy -static-libgcc'
EXTRA_COMPILE_ARGS = shlex.split(EXTRA_ENV_COMPILE_ARGS)
EXTRA_LINK_ARGS = shlex.split(EXTRA_ENV_LINK_ARGS)
@ -209,119 +214,135 @@ CYTHON_HELPER_C_FILES = ()
CORE_C_FILES = tuple(grpc_core_dependencies.CORE_SOURCE_FILES)
if "win32" in sys.platform:
CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES)
CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES)
if BUILD_WITH_SYSTEM_OPENSSL:
CORE_C_FILES = filter(lambda x: 'third_party/boringssl' not in x, CORE_C_FILES)
CORE_C_FILES = filter(lambda x: 'src/boringssl' not in x, CORE_C_FILES)
SSL_INCLUDE = (os.path.join('/usr', 'include', 'openssl'),)
CORE_C_FILES = filter(lambda x: 'third_party/boringssl' not in x,
CORE_C_FILES)
CORE_C_FILES = filter(lambda x: 'src/boringssl' not in x, CORE_C_FILES)
SSL_INCLUDE = (os.path.join('/usr', 'include', 'openssl'),)
if BUILD_WITH_SYSTEM_ZLIB:
CORE_C_FILES = filter(lambda x: 'third_party/zlib' not in x, CORE_C_FILES)
ZLIB_INCLUDE = (os.path.join('/usr', 'include'),)
CORE_C_FILES = filter(lambda x: 'third_party/zlib' not in x, CORE_C_FILES)
ZLIB_INCLUDE = (os.path.join('/usr', 'include'),)
if BUILD_WITH_SYSTEM_CARES:
CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES)
CARES_INCLUDE = (os.path.join('/usr', 'include'),)
EXTENSION_INCLUDE_DIRECTORIES = (
(PYTHON_STEM,) +
CORE_INCLUDE +
ABSL_INCLUDE +
ADDRESS_SORTING_INCLUDE +
CARES_INCLUDE +
SSL_INCLUDE +
UPB_INCLUDE +
UPB_GRPC_GENERATED_INCLUDE +
ZLIB_INCLUDE)
CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES)
CARES_INCLUDE = (os.path.join('/usr', 'include'),)
EXTENSION_INCLUDE_DIRECTORIES = ((PYTHON_STEM,) + CORE_INCLUDE + ABSL_INCLUDE +
ADDRESS_SORTING_INCLUDE + CARES_INCLUDE +
SSL_INCLUDE + UPB_INCLUDE +
UPB_GRPC_GENERATED_INCLUDE + ZLIB_INCLUDE)
EXTENSION_LIBRARIES = ()
if "linux" in sys.platform:
EXTENSION_LIBRARIES += ('rt',)
EXTENSION_LIBRARIES += ('rt',)
if not "win32" in sys.platform:
EXTENSION_LIBRARIES += ('m',)
EXTENSION_LIBRARIES += ('m',)
if "win32" in sys.platform:
EXTENSION_LIBRARIES += ('advapi32', 'ws2_32', 'dbghelp',)
EXTENSION_LIBRARIES += (
'advapi32',
'ws2_32',
'dbghelp',
)
if BUILD_WITH_SYSTEM_OPENSSL:
EXTENSION_LIBRARIES += ('ssl', 'crypto',)
EXTENSION_LIBRARIES += (
'ssl',
'crypto',
)
if BUILD_WITH_SYSTEM_ZLIB:
EXTENSION_LIBRARIES += ('z',)
EXTENSION_LIBRARIES += ('z',)
if BUILD_WITH_SYSTEM_CARES:
EXTENSION_LIBRARIES += ('cares',)
EXTENSION_LIBRARIES += ('cares',)
DEFINE_MACROS = (('OPENSSL_NO_ASM', 1), ('_WIN32_WINNT', 0x600))
if not DISABLE_LIBC_COMPATIBILITY:
DEFINE_MACROS += (('GPR_BACKWARDS_COMPATIBILITY_MODE', 1),)
DEFINE_MACROS += (('GPR_BACKWARDS_COMPATIBILITY_MODE', 1),)
if "win32" in sys.platform:
# TODO(zyc): Re-enable c-ares on x64 and x86 windows after fixing the
# ares_library_init compilation issue
DEFINE_MACROS += (('WIN32_LEAN_AND_MEAN', 1), ('CARES_STATICLIB', 1),
('GRPC_ARES', 0), ('NTDDI_VERSION', 0x06000000),
('NOMINMAX', 1),)
if '64bit' in platform.architecture()[0]:
DEFINE_MACROS += (('MS_WIN64', 1),)
elif sys.version_info >= (3, 5):
# For some reason, this is needed to get access to inet_pton/inet_ntop
# on msvc, but only for 32 bits
DEFINE_MACROS += (('NTDDI_VERSION', 0x06000000),)
# TODO(zyc): Re-enable c-ares on x64 and x86 windows after fixing the
# ares_library_init compilation issue
DEFINE_MACROS += (
('WIN32_LEAN_AND_MEAN', 1),
('CARES_STATICLIB', 1),
('GRPC_ARES', 0),
('NTDDI_VERSION', 0x06000000),
('NOMINMAX', 1),
)
if '64bit' in platform.architecture()[0]:
DEFINE_MACROS += (('MS_WIN64', 1),)
elif sys.version_info >= (3, 5):
# For some reason, this is needed to get access to inet_pton/inet_ntop
# on msvc, but only for 32 bits
DEFINE_MACROS += (('NTDDI_VERSION', 0x06000000),)
else:
DEFINE_MACROS += (('HAVE_CONFIG_H', 1), ('GRPC_ENABLE_FORK_SUPPORT', 1),)
DEFINE_MACROS += (
('HAVE_CONFIG_H', 1),
('GRPC_ENABLE_FORK_SUPPORT', 1),
)
LDFLAGS = tuple(EXTRA_LINK_ARGS)
CFLAGS = tuple(EXTRA_COMPILE_ARGS)
if "linux" in sys.platform or "darwin" in sys.platform:
pymodinit_type = 'PyObject*' if PY3 else 'void'
pymodinit = 'extern "C" __attribute__((visibility ("default"))) {}'.format(pymodinit_type)
DEFINE_MACROS += (('PyMODINIT_FUNC', pymodinit),)
DEFINE_MACROS += (('GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK', 1),)
pymodinit_type = 'PyObject*' if PY3 else 'void'
pymodinit = 'extern "C" __attribute__((visibility ("default"))) {}'.format(
pymodinit_type)
DEFINE_MACROS += (('PyMODINIT_FUNC', pymodinit),)
DEFINE_MACROS += (('GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK', 1),)
# By default, Python3 distutils enforces compatibility of
# c plugins (.so files) with the OSX version Python3 was built with.
# For Python3.4, this is OSX 10.6, but we need Thread Local Support (__thread)
if 'darwin' in sys.platform and PY3:
mac_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
if mac_target and (pkg_resources.parse_version(mac_target) <
pkg_resources.parse_version('10.7.0')):
os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7'
os.environ['_PYTHON_HOST_PLATFORM'] = re.sub(
r'macosx-[0-9]+\.[0-9]+-(.+)',
r'macosx-10.7-\1',
util.get_platform())
mac_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
if mac_target and (pkg_resources.parse_version(mac_target) <
pkg_resources.parse_version('10.7.0')):
os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7'
os.environ['_PYTHON_HOST_PLATFORM'] = re.sub(
r'macosx-[0-9]+\.[0-9]+-(.+)', r'macosx-10.7-\1',
util.get_platform())
def cython_extensions_and_necessity():
cython_module_files = [os.path.join(PYTHON_STEM,
name.replace('.', '/') + '.pyx')
for name in CYTHON_EXTENSION_MODULE_NAMES]
config = os.environ.get('CONFIG', 'opt')
prefix = 'libs/' + config + '/'
if USE_PREBUILT_GRPC_CORE:
extra_objects = [prefix + 'libares.a',
prefix + 'libboringssl.a',
prefix + 'libgpr.a',
prefix + 'libgrpc.a']
core_c_files = []
else:
core_c_files = list(CORE_C_FILES)
extra_objects = []
extensions = [
_extension.Extension(
name=module_name,
sources=[module_file] + list(CYTHON_HELPER_C_FILES) + core_c_files,
include_dirs=list(EXTENSION_INCLUDE_DIRECTORIES),
libraries=list(EXTENSION_LIBRARIES),
define_macros=list(DEFINE_MACROS),
extra_objects=extra_objects,
extra_compile_args=list(CFLAGS),
extra_link_args=list(LDFLAGS),
) for (module_name, module_file) in zip(list(CYTHON_EXTENSION_MODULE_NAMES), cython_module_files)
]
need_cython = BUILD_WITH_CYTHON
if not BUILD_WITH_CYTHON:
need_cython = need_cython or not commands.check_and_update_cythonization(extensions)
# TODO: the strategy for conditional compiling and exposing the aio Cython
# dependencies will be revisited by https://github.com/grpc/grpc/issues/19728
return commands.try_cythonize(extensions, linetracing=ENABLE_CYTHON_TRACING, mandatory=BUILD_WITH_CYTHON), need_cython
cython_module_files = [
os.path.join(PYTHON_STEM,
name.replace('.', '/') + '.pyx')
for name in CYTHON_EXTENSION_MODULE_NAMES
]
config = os.environ.get('CONFIG', 'opt')
prefix = 'libs/' + config + '/'
if USE_PREBUILT_GRPC_CORE:
extra_objects = [
prefix + 'libares.a', prefix + 'libboringssl.a',
prefix + 'libgpr.a', prefix + 'libgrpc.a'
]
core_c_files = []
else:
core_c_files = list(CORE_C_FILES)
extra_objects = []
extensions = [
_extension.Extension(
name=module_name,
sources=[module_file] + list(CYTHON_HELPER_C_FILES) + core_c_files,
include_dirs=list(EXTENSION_INCLUDE_DIRECTORIES),
libraries=list(EXTENSION_LIBRARIES),
define_macros=list(DEFINE_MACROS),
extra_objects=extra_objects,
extra_compile_args=list(CFLAGS),
extra_link_args=list(LDFLAGS),
) for (module_name, module_file
) in zip(list(CYTHON_EXTENSION_MODULE_NAMES), cython_module_files)
]
need_cython = BUILD_WITH_CYTHON
if not BUILD_WITH_CYTHON:
need_cython = need_cython or not commands.check_and_update_cythonization(
extensions)
# TODO: the strategy for conditional compiling and exposing the aio Cython
# dependencies will be revisited by https://github.com/grpc/grpc/issues/19728
return commands.try_cythonize(extensions,
linetracing=ENABLE_CYTHON_TRACING,
mandatory=BUILD_WITH_CYTHON), need_cython
CYTHON_EXTENSION_MODULES, need_cython = cython_extensions_and_necessity()
@ -338,20 +359,20 @@ INSTALL_REQUIRES = (
SETUP_REQUIRES = INSTALL_REQUIRES + (
'Sphinx~=1.8.1',
'six>=1.10',
) if ENABLE_DOCUMENTATION_BUILD else ()
) if ENABLE_DOCUMENTATION_BUILD else ()
try:
import Cython
import Cython
except ImportError:
if BUILD_WITH_CYTHON:
sys.stderr.write(
"You requested a Cython build via GRPC_PYTHON_BUILD_WITH_CYTHON, "
"but do not have Cython installed. We won't stop you from using "
"other commands, but the extension files will fail to build.\n")
elif need_cython:
sys.stderr.write(
'We could not find Cython. Setup may take 10-20 minutes.\n')
SETUP_REQUIRES += ('cython>=0.23',)
if BUILD_WITH_CYTHON:
sys.stderr.write(
"You requested a Cython build via GRPC_PYTHON_BUILD_WITH_CYTHON, "
"but do not have Cython installed. We won't stop you from using "
"other commands, but the extension files will fail to build.\n")
elif need_cython:
sys.stderr.write(
'We could not find Cython. Setup may take 10-20 minutes.\n')
SETUP_REQUIRES += ('cython>=0.23',)
COMMAND_CLASS = {
'doc': commands.SphinxDocumentation,
@ -364,9 +385,9 @@ COMMAND_CLASS = {
# Ensure that package data is copied over before any commands have been run:
credentials_dir = os.path.join(PYTHON_STEM, 'grpc', '_cython', '_credentials')
try:
os.mkdir(credentials_dir)
os.mkdir(credentials_dir)
except OSError:
pass
pass
shutil.copyfile(os.path.join('etc', 'roots.pem'),
os.path.join(credentials_dir, 'roots.pem'))
@ -382,20 +403,20 @@ PACKAGE_DATA = {
PACKAGES = setuptools.find_packages(PYTHON_STEM)
setuptools.setup(
name='grpcio',
version=grpc_version.VERSION,
description='HTTP/2-based RPC framework',
author='The gRPC Authors',
author_email='grpc-io@googlegroups.com',
url='https://grpc.io',
license=LICENSE,
classifiers=CLASSIFIERS,
long_description=open(README).read(),
ext_modules=CYTHON_EXTENSION_MODULES,
packages=list(PACKAGES),
package_dir=PACKAGE_DIRECTORIES,
package_data=PACKAGE_DATA,
install_requires=INSTALL_REQUIRES,
setup_requires=SETUP_REQUIRES,
cmdclass=COMMAND_CLASS,
name='grpcio',
version=grpc_version.VERSION,
description='HTTP/2-based RPC framework',
author='The gRPC Authors',
author_email='grpc-io@googlegroups.com',
url='https://grpc.io',
license=LICENSE,
classifiers=CLASSIFIERS,
long_description=open(README).read(),
ext_modules=CYTHON_EXTENSION_MODULES,
packages=list(PACKAGES),
package_dir=PACKAGE_DIRECTORIES,
package_data=PACKAGE_DATA,
install_requires=INSTALL_REQUIRES,
setup_requires=SETUP_REQUIRES,
cmdclass=COMMAND_CLASS,
)

File diff suppressed because it is too large Load Diff

@ -80,7 +80,8 @@ void PrintMethod(const MethodDescriptor* method, Printer* out) {
if (method->client_streaming()) {
out->Print(vars,
" * @param array $$metadata metadata\n"
" * @param array $$options call options\n */\n"
" * @param array $$options call options\n"
" * @return \\$output_type_id$\n */\n"
"public function $name$($$metadata = [], "
"$$options = []) {\n");
out->Indent();
@ -98,7 +99,8 @@ void PrintMethod(const MethodDescriptor* method, Printer* out) {
out->Print(vars,
" * @param \\$input_type_id$ $$argument input argument\n"
" * @param array $$metadata metadata\n"
" * @param array $$options call options\n */\n"
" * @param array $$options call options\n"
" * @return \\$output_type_id$\n */\n"
"public function $name$(\\$input_type_id$ $$argument,\n"
" $$metadata = [], $$options = []) {\n");
out->Indent();

@ -18,27 +18,30 @@
#include "src/core/ext/filters/client_channel/backend_metric.h"
#include "src/core/lib/gprpp/string_view.h"
#include "absl/strings/string_view.h"
#include "udpa/data/orca/v1/orca_load_report.upb.h"
#include "src/core/lib/gprpp/map.h"
namespace grpc_core {
namespace {
template <typename EntryType>
std::map<StringView, double, StringLess> ParseMap(
std::map<absl::string_view, double, StringLess> ParseMap(
udpa_data_orca_v1_OrcaLoadReport* msg,
EntryType** (*entry_func)(udpa_data_orca_v1_OrcaLoadReport*, size_t*),
upb_strview (*key_func)(const EntryType*),
double (*value_func)(const EntryType*), Arena* arena) {
std::map<StringView, double, StringLess> result;
std::map<absl::string_view, double, StringLess> result;
size_t size;
const auto* const* entries = entry_func(msg, &size);
for (size_t i = 0; i < size; ++i) {
upb_strview key_view = key_func(entries[i]);
char* key = static_cast<char*>(arena->Alloc(key_view.size + 1));
memcpy(key, key_view.data, key_view.size);
result[StringView(key, key_view.size)] = value_func(entries[i]);
result[absl::string_view(key, key_view.size)] = value_func(entries[i]);
}
return result;
}

@ -28,11 +28,16 @@
#include <set>
#include "absl/strings/string_view.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include "absl/container/inlined_vector.h"
#include "absl/types/optional.h"
#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/global_subchannel_pool.h"
@ -52,13 +57,12 @@
#include "src/core/lib/channel/connected_channel.h"
#include "src/core/lib/channel/status_util.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/manual_constructor.h"
#include "src/core/lib/gprpp/map.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/iomgr/work_serializer.h"
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
@ -126,6 +130,7 @@ class ChannelData {
size_t per_rpc_retry_buffer_size() const {
return per_rpc_retry_buffer_size_;
}
grpc_channel_stack* owning_stack() const { return owning_stack_; }
// Note: Does NOT return a new ref.
grpc_error* disconnect_error() const {
@ -149,6 +154,7 @@ class ChannelData {
RefCountedPtr<ServiceConfig> service_config() const {
return service_config_;
}
WorkSerializer* work_serializer() const { return work_serializer_.get(); }
RefCountedPtr<ConnectedSubchannel> GetConnectedSubchannelInDataPlane(
SubchannelInterface* subchannel) const;
@ -159,11 +165,15 @@ class ChannelData {
grpc_connectivity_state* state,
grpc_closure* on_complete,
grpc_closure* watcher_timer_init) {
MutexLock lock(&external_watchers_mu_);
// Will be deleted when the watch is complete.
GPR_ASSERT(external_watchers_[on_complete] == nullptr);
external_watchers_[on_complete] = new ExternalConnectivityWatcher(
auto* watcher = new ExternalConnectivityWatcher(
this, pollent, state, on_complete, watcher_timer_init);
{
MutexLock lock(&external_watchers_mu_);
// Will be deleted when the watch is complete.
GPR_ASSERT(external_watchers_[on_complete] == nullptr);
external_watchers_[on_complete] = watcher;
}
watcher->Start();
}
void RemoveExternalConnectivityWatcher(grpc_closure* on_complete,
@ -204,13 +214,15 @@ class ChannelData {
~ExternalConnectivityWatcher();
void Start();
void Notify(grpc_connectivity_state state) override;
void Cancel();
private:
static void AddWatcherLocked(void* arg, grpc_error* ignored);
static void RemoveWatcherLocked(void* arg, grpc_error* ignored);
void AddWatcherLocked();
void RemoveWatcherLocked();
ChannelData* chand_;
grpc_polling_entity pollent_;
@ -218,8 +230,6 @@ class ChannelData {
grpc_connectivity_state* state_;
grpc_closure* on_complete_;
grpc_closure* watcher_timer_init_;
grpc_closure add_closure_;
grpc_closure remove_closure_;
Atomic<bool> done_{false};
};
@ -245,9 +255,9 @@ class ChannelData {
grpc_error* DoPingLocked(grpc_transport_op* op);
static void StartTransportOpLocked(void* arg, grpc_error* ignored);
void StartTransportOpLocked(grpc_transport_op* op);
static void TryToConnectLocked(void* arg, grpc_error* error_ignored);
void TryToConnectLocked();
void ProcessLbPolicy(
const Resolver::Result& resolver_result,
@ -280,9 +290,9 @@ class ChannelData {
RefCountedPtr<ServiceConfig> service_config_;
//
// Fields used in the control plane. Guarded by combiner.
// Fields used in the control plane. Guarded by work_serializer.
//
Combiner* combiner_;
std::shared_ptr<WorkSerializer> work_serializer_;
grpc_pollset_set* interested_parties_;
RefCountedPtr<SubchannelPoolInterface> subchannel_pool_;
OrphanablePtr<ResolvingLoadBalancingPolicy> resolving_lb_policy_;
@ -294,17 +304,17 @@ class ChannelData {
std::map<Subchannel*, int> subchannel_refcount_map_;
// The set of SubchannelWrappers that currently exist.
// No need to hold a ref, since the map is updated in the control-plane
// combiner when the SubchannelWrappers are created and destroyed.
// work_serializer when the SubchannelWrappers are created and destroyed.
std::set<SubchannelWrapper*> subchannel_wrappers_;
// Pending ConnectedSubchannel updates for each SubchannelWrapper.
// Updates are queued here in the control plane combiner and then applied
// in the data plane mutex when the picker is updated.
std::map<RefCountedPtr<SubchannelWrapper>, RefCountedPtr<ConnectedSubchannel>,
RefCountedPtrLess<SubchannelWrapper>>
// Updates are queued here in the control plane work_serializer and then
// applied in the data plane mutex when the picker is updated.
std::map<RefCountedPtr<SubchannelWrapper>, RefCountedPtr<ConnectedSubchannel>>
pending_subchannel_updates_;
//
// Fields accessed from both data plane mutex and control plane combiner.
// Fields accessed from both data plane mutex and control plane
// work_serializer.
//
Atomic<grpc_error*> disconnect_error_;
@ -364,7 +374,7 @@ class CallData {
Metadata(CallData* calld, grpc_metadata_batch* batch)
: calld_(calld), batch_(batch) {}
void Add(StringView key, StringView value) override {
void Add(absl::string_view key, absl::string_view value) override {
grpc_linked_mdelem* linked_mdelem = static_cast<grpc_linked_mdelem*>(
calld_->arena_->Alloc(sizeof(grpc_linked_mdelem)));
linked_mdelem->md = grpc_mdelem_from_slices(
@ -399,7 +409,7 @@ class CallData {
reinterpret_cast<grpc_linked_mdelem*>(handle);
return reinterpret_cast<intptr_t>(linked_mdelem->next);
}
std::pair<StringView, StringView> IteratorHandleGet(
std::pair<absl::string_view, absl::string_view> IteratorHandleGet(
intptr_t handle) const override {
grpc_linked_mdelem* linked_mdelem =
reinterpret_cast<grpc_linked_mdelem*>(handle);
@ -820,7 +830,7 @@ class CallData {
// Note: We inline the cache for the first 3 send_message ops and use
// dynamic allocation after that. This number was essentially picked
// at random; it could be changed in the future to tune performance.
InlinedVector<ByteStreamCache*, 3> send_messages_;
absl::InlinedVector<ByteStreamCache*, 3> send_messages_;
// send_trailing_metadata
bool seen_send_trailing_metadata_ = false;
grpc_linked_mdelem* send_trailing_metadata_storage_ = nullptr;
@ -838,7 +848,7 @@ class CallData {
// Note that no synchronization is needed here, because even if the
// underlying subchannel is shared between channels, this wrapper will only
// be used within one channel, so it will always be synchronized by the
// control plane combiner.
// control plane work_serializer.
class ChannelData::SubchannelWrapper : public SubchannelInterface {
public:
SubchannelWrapper(ChannelData* chand, Subchannel* subchannel,
@ -907,7 +917,7 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
initial_state,
grpc_core::UniquePtr<char>(
gpr_strdup(health_check_service_name_.get())),
OrphanablePtr<Subchannel::ConnectivityStateWatcherInterface>(
RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface>(
watcher_wrapper));
}
@ -957,14 +967,14 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
replacement->last_seen_state(),
grpc_core::UniquePtr<char>(
gpr_strdup(health_check_service_name.get())),
OrphanablePtr<Subchannel::ConnectivityStateWatcherInterface>(
RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface>(
replacement));
}
// Save the new health check service name.
health_check_service_name_ = std::move(health_check_service_name);
}
// Caller must be holding the control-plane combiner.
// Caller must be holding the control-plane work_serializer.
ConnectedSubchannel* connected_subchannel() const {
return connected_subchannel_.get();
}
@ -1004,23 +1014,27 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
parent_(std::move(parent)),
last_seen_state_(initial_state) {}
~WatcherWrapper() { parent_.reset(DEBUG_LOCATION, "WatcherWrapper"); }
void Orphan() override { Unref(); }
~WatcherWrapper() {
auto* parent = parent_.release(); // ref owned by lambda
parent->chand_->work_serializer_->Run(
[parent]() { parent->Unref(DEBUG_LOCATION, "WatcherWrapper"); },
DEBUG_LOCATION);
}
void OnConnectivityStateChange(
grpc_connectivity_state new_state,
RefCountedPtr<ConnectedSubchannel> connected_subchannel) override {
void OnConnectivityStateChange() override {
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
gpr_log(GPR_INFO,
"chand=%p: connectivity change for subchannel wrapper %p "
"subchannel %p (connected_subchannel=%p state=%s); "
"hopping into combiner",
parent_->chand_, parent_.get(), parent_->subchannel_,
connected_subchannel.get(), ConnectivityStateName(new_state));
"subchannel %p; hopping into work_serializer",
parent_->chand_, parent_.get(), parent_->subchannel_);
}
// Will delete itself.
new Updater(Ref(), new_state, std::move(connected_subchannel));
Ref().release(); // ref owned by lambda
parent_->chand_->work_serializer_->Run(
[this]() {
ApplyUpdateInControlPlaneWorkSerializer();
Unref();
},
DEBUG_LOCATION);
}
grpc_pollset_set* interested_parties() override {
@ -1040,50 +1054,25 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
grpc_connectivity_state last_seen_state() const { return last_seen_state_; }
private:
class Updater {
public:
Updater(RefCountedPtr<WatcherWrapper> parent,
grpc_connectivity_state new_state,
RefCountedPtr<ConnectedSubchannel> connected_subchannel)
: parent_(std::move(parent)),
state_(new_state),
connected_subchannel_(std::move(connected_subchannel)) {
parent_->parent_->chand_->combiner_->Run(
GRPC_CLOSURE_INIT(&closure_, ApplyUpdateInControlPlaneCombiner,
this, nullptr),
GRPC_ERROR_NONE);
void ApplyUpdateInControlPlaneWorkSerializer() {
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
gpr_log(GPR_INFO,
"chand=%p: processing connectivity change in work serializer "
"for subchannel wrapper %p subchannel %p "
"watcher=%p",
parent_->chand_, parent_.get(), parent_->subchannel_,
watcher_.get());
}
private:
static void ApplyUpdateInControlPlaneCombiner(void* arg,
grpc_error* /*error*/) {
Updater* self = static_cast<Updater*>(arg);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
gpr_log(GPR_INFO,
"chand=%p: processing connectivity change in combiner "
"for subchannel wrapper %p subchannel %p "
"(connected_subchannel=%p state=%s): watcher=%p",
self->parent_->parent_->chand_, self->parent_->parent_.get(),
self->parent_->parent_->subchannel_,
self->connected_subchannel_.get(),
ConnectivityStateName(self->state_),
self->parent_->watcher_.get());
}
// Ignore update if the parent WatcherWrapper has been replaced
// since this callback was scheduled.
if (self->parent_->watcher_ == nullptr) return;
self->parent_->last_seen_state_ = self->state_;
self->parent_->parent_->MaybeUpdateConnectedSubchannel(
std::move(self->connected_subchannel_));
self->parent_->watcher_->OnConnectivityStateChange(self->state_);
delete self;
ConnectivityStateChange state_change = PopConnectivityStateChange();
// Ignore update if the parent WatcherWrapper has been replaced
// since this callback was scheduled.
if (watcher_ != nullptr) {
last_seen_state_ = state_change.state;
parent_->MaybeUpdateConnectedSubchannel(
std::move(state_change.connected_subchannel));
watcher_->OnConnectivityStateChange(state_change.state);
}
RefCountedPtr<WatcherWrapper> parent_;
grpc_connectivity_state state_;
RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
grpc_closure closure_;
};
}
std::unique_ptr<SubchannelInterface::ConnectivityStateWatcherInterface>
watcher_;
@ -1122,7 +1111,7 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
// CancelConnectivityStateWatch() with its watcher, we know the
// corresponding WrapperWatcher to cancel on the underlying subchannel.
std::map<ConnectivityStateWatcherInterface*, WatcherWrapper*> watcher_map_;
// To be accessed only in the control plane combiner.
// To be accessed only in the control plane work_serializer.
RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
// To be accessed only in the data plane mutex.
RefCountedPtr<ConnectedSubchannel> connected_subchannel_in_data_plane_;
@ -1145,9 +1134,6 @@ ChannelData::ExternalConnectivityWatcher::ExternalConnectivityWatcher(
grpc_polling_entity_add_to_pollset_set(&pollent_,
chand_->interested_parties_);
GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "ExternalConnectivityWatcher");
chand_->combiner_->Run(
GRPC_CLOSURE_INIT(&add_closure_, AddWatcherLocked, this, nullptr),
GRPC_ERROR_NONE);
}
ChannelData::ExternalConnectivityWatcher::~ExternalConnectivityWatcher() {
@ -1157,6 +1143,11 @@ ChannelData::ExternalConnectivityWatcher::~ExternalConnectivityWatcher() {
"ExternalConnectivityWatcher");
}
void ChannelData::ExternalConnectivityWatcher::Start() {
chand_->work_serializer_->Run([this]() { AddWatcherLocked(); },
DEBUG_LOCATION);
}
void ChannelData::ExternalConnectivityWatcher::Notify(
grpc_connectivity_state state) {
bool done = false;
@ -1169,13 +1160,12 @@ void ChannelData::ExternalConnectivityWatcher::Notify(
// Report new state to the user.
*state_ = state;
ExecCtx::Run(DEBUG_LOCATION, on_complete_, GRPC_ERROR_NONE);
// Hop back into the combiner to clean up.
// Hop back into the work_serializer to clean up.
// Not needed in state SHUTDOWN, because the tracker will
// automatically remove all watchers in that case.
if (state != GRPC_CHANNEL_SHUTDOWN) {
chand_->combiner_->Run(
GRPC_CLOSURE_INIT(&remove_closure_, RemoveWatcherLocked, this, nullptr),
GRPC_ERROR_NONE);
chand_->work_serializer_->Run([this]() { RemoveWatcherLocked(); },
DEBUG_LOCATION);
}
}
@ -1186,28 +1176,20 @@ void ChannelData::ExternalConnectivityWatcher::Cancel() {
return; // Already done.
}
ExecCtx::Run(DEBUG_LOCATION, on_complete_, GRPC_ERROR_CANCELLED);
// Hop back into the combiner to clean up.
chand_->combiner_->Run(
GRPC_CLOSURE_INIT(&remove_closure_, RemoveWatcherLocked, this, nullptr),
GRPC_ERROR_NONE);
// Hop back into the work_serializer to clean up.
chand_->work_serializer_->Run([this]() { RemoveWatcherLocked(); },
DEBUG_LOCATION);
}
void ChannelData::ExternalConnectivityWatcher::AddWatcherLocked(
void* arg, grpc_error* /*ignored*/) {
ExternalConnectivityWatcher* self =
static_cast<ExternalConnectivityWatcher*>(arg);
Closure::Run(DEBUG_LOCATION, self->watcher_timer_init_, GRPC_ERROR_NONE);
void ChannelData::ExternalConnectivityWatcher::AddWatcherLocked() {
Closure::Run(DEBUG_LOCATION, watcher_timer_init_, GRPC_ERROR_NONE);
// Add new watcher.
self->chand_->state_tracker_.AddWatcher(
self->initial_state_,
OrphanablePtr<ConnectivityStateWatcherInterface>(self));
chand_->state_tracker_.AddWatcher(
initial_state_, OrphanablePtr<ConnectivityStateWatcherInterface>(this));
}
void ChannelData::ExternalConnectivityWatcher::RemoveWatcherLocked(
void* arg, grpc_error* /*ignored*/) {
ExternalConnectivityWatcher* self =
static_cast<ExternalConnectivityWatcher*>(arg);
self->chand_->state_tracker_.RemoveWatcher(self);
void ChannelData::ExternalConnectivityWatcher::RemoveWatcherLocked() {
chand_->state_tracker_.RemoveWatcher(this);
}
//
@ -1223,28 +1205,20 @@ class ChannelData::ConnectivityWatcherAdder {
initial_state_(initial_state),
watcher_(std::move(watcher)) {
GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "ConnectivityWatcherAdder");
chand_->combiner_->Run(
GRPC_CLOSURE_INIT(&closure_,
&ConnectivityWatcherAdder::AddWatcherLocked, this,
nullptr),
GRPC_ERROR_NONE);
chand_->work_serializer_->Run([this]() { AddWatcherLocked(); },
DEBUG_LOCATION);
}
private:
static void AddWatcherLocked(void* arg, grpc_error* /*error*/) {
ConnectivityWatcherAdder* self =
static_cast<ConnectivityWatcherAdder*>(arg);
self->chand_->state_tracker_.AddWatcher(self->initial_state_,
std::move(self->watcher_));
GRPC_CHANNEL_STACK_UNREF(self->chand_->owning_stack_,
"ConnectivityWatcherAdder");
delete self;
void AddWatcherLocked() {
chand_->state_tracker_.AddWatcher(initial_state_, std::move(watcher_));
GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "ConnectivityWatcherAdder");
delete this;
}
ChannelData* chand_;
grpc_connectivity_state initial_state_;
OrphanablePtr<AsyncConnectivityStateWatcherInterface> watcher_;
grpc_closure closure_;
};
//
@ -1257,26 +1231,20 @@ class ChannelData::ConnectivityWatcherRemover {
AsyncConnectivityStateWatcherInterface* watcher)
: chand_(chand), watcher_(watcher) {
GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "ConnectivityWatcherRemover");
chand_->combiner_->Run(
GRPC_CLOSURE_INIT(&closure_,
&ConnectivityWatcherRemover::RemoveWatcherLocked,
this, nullptr),
GRPC_ERROR_NONE);
chand_->work_serializer_->Run([this]() { RemoveWatcherLocked(); },
DEBUG_LOCATION);
}
private:
static void RemoveWatcherLocked(void* arg, grpc_error* /*error*/) {
ConnectivityWatcherRemover* self =
static_cast<ConnectivityWatcherRemover*>(arg);
self->chand_->state_tracker_.RemoveWatcher(self->watcher_);
GRPC_CHANNEL_STACK_UNREF(self->chand_->owning_stack_,
void RemoveWatcherLocked() {
chand_->state_tracker_.RemoveWatcher(watcher_);
GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_,
"ConnectivityWatcherRemover");
delete self;
delete this;
}
ChannelData* chand_;
AsyncConnectivityStateWatcherInterface* watcher_;
grpc_closure closure_;
};
//
@ -1340,7 +1308,8 @@ class ChannelData::ClientChannelControlHelper
// No-op -- we should never get this from ResolvingLoadBalancingPolicy.
void RequestReresolution() override {}
void AddTraceEvent(TraceSeverity severity, StringView message) override {
void AddTraceEvent(TraceSeverity severity,
absl::string_view message) override {
if (chand_->channelz_node_ != nullptr) {
chand_->channelz_node_->AddTraceEvent(
ConvertSeverityEnum(severity),
@ -1417,7 +1386,7 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error)
client_channel_factory_(
ClientChannelFactory::GetFromChannelArgs(args->channel_args)),
channelz_node_(GetChannelzNode(args->channel_args)),
combiner_(grpc_combiner_create()),
work_serializer_(std::make_shared<WorkSerializer>()),
interested_parties_(grpc_pollset_set_create()),
subchannel_pool_(GetSubchannelPool(args->channel_args)),
state_tracker_("client_channel", GRPC_CHANNEL_IDLE),
@ -1488,7 +1457,6 @@ ChannelData::~ChannelData() {
// Stop backup polling.
grpc_client_channel_stop_backup_polling(interested_parties_);
grpc_pollset_set_destroy(interested_parties_);
GRPC_COMBINER_UNREF(combiner_, "client_channel");
GRPC_ERROR_UNREF(disconnect_error_.Load(MemoryOrder::RELAXED));
gpr_mu_destroy(&info_mu_);
}
@ -1592,7 +1560,7 @@ void ChannelData::UpdateServiceConfigLocked(
void ChannelData::CreateResolvingLoadBalancingPolicyLocked() {
// Instantiate resolving LB policy.
LoadBalancingPolicy::Args lb_args;
lb_args.combiner = combiner_;
lb_args.work_serializer = work_serializer_;
lb_args.channel_control_helper =
absl::make_unique<ClientChannelControlHelper>(this);
lb_args.args = channel_args_;
@ -1762,7 +1730,7 @@ bool ChannelData::ProcessResolverResultLocked(
chand->received_first_resolver_result_ = true;
RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
if (parsed_service_config != nullptr) {
Optional<internal::ClientChannelGlobalParsedConfig::RetryThrottling>
absl::optional<internal::ClientChannelGlobalParsedConfig::RetryThrottling>
retry_throttle_config = parsed_service_config->retry_throttling();
if (retry_throttle_config.has_value()) {
retry_throttle_data =
@ -1813,22 +1781,18 @@ grpc_error* ChannelData::DoPingLocked(grpc_transport_op* op) {
return result.error;
}
void ChannelData::StartTransportOpLocked(void* arg, grpc_error* /*ignored*/) {
grpc_transport_op* op = static_cast<grpc_transport_op*>(arg);
grpc_channel_element* elem =
static_cast<grpc_channel_element*>(op->handler_private.extra_arg);
ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
void ChannelData::StartTransportOpLocked(grpc_transport_op* op) {
// Connectivity watch.
if (op->start_connectivity_watch != nullptr) {
chand->state_tracker_.AddWatcher(op->start_connectivity_watch_state,
std::move(op->start_connectivity_watch));
state_tracker_.AddWatcher(op->start_connectivity_watch_state,
std::move(op->start_connectivity_watch));
}
if (op->stop_connectivity_watch != nullptr) {
chand->state_tracker_.RemoveWatcher(op->stop_connectivity_watch);
state_tracker_.RemoveWatcher(op->stop_connectivity_watch);
}
// Ping.
if (op->send_ping.on_initiate != nullptr || op->send_ping.on_ack != nullptr) {
grpc_error* error = chand->DoPingLocked(op);
grpc_error* error = DoPingLocked(op);
if (error != GRPC_ERROR_NONE) {
ExecCtx::Run(DEBUG_LOCATION, op->send_ping.on_initiate,
GRPC_ERROR_REF(error));
@ -1840,40 +1804,39 @@ void ChannelData::StartTransportOpLocked(void* arg, grpc_error* /*ignored*/) {
}
// Reset backoff.
if (op->reset_connect_backoff) {
if (chand->resolving_lb_policy_ != nullptr) {
chand->resolving_lb_policy_->ResetBackoffLocked();
if (resolving_lb_policy_ != nullptr) {
resolving_lb_policy_->ResetBackoffLocked();
}
}
// Disconnect or enter IDLE.
if (op->disconnect_with_error != GRPC_ERROR_NONE) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
gpr_log(GPR_INFO, "chand=%p: disconnect_with_error: %s", chand,
gpr_log(GPR_INFO, "chand=%p: disconnect_with_error: %s", this,
grpc_error_string(op->disconnect_with_error));
}
chand->DestroyResolvingLoadBalancingPolicyLocked();
DestroyResolvingLoadBalancingPolicyLocked();
intptr_t value;
if (grpc_error_get_int(op->disconnect_with_error,
GRPC_ERROR_INT_CHANNEL_CONNECTIVITY_STATE, &value) &&
static_cast<grpc_connectivity_state>(value) == GRPC_CHANNEL_IDLE) {
if (chand->disconnect_error() == GRPC_ERROR_NONE) {
if (disconnect_error() == GRPC_ERROR_NONE) {
// Enter IDLE state.
chand->UpdateStateAndPickerLocked(GRPC_CHANNEL_IDLE,
"channel entering IDLE", nullptr);
UpdateStateAndPickerLocked(GRPC_CHANNEL_IDLE, "channel entering IDLE",
nullptr);
}
GRPC_ERROR_UNREF(op->disconnect_with_error);
} else {
// Disconnect.
GPR_ASSERT(chand->disconnect_error_.Load(MemoryOrder::RELAXED) ==
GPR_ASSERT(disconnect_error_.Load(MemoryOrder::RELAXED) ==
GRPC_ERROR_NONE);
chand->disconnect_error_.Store(op->disconnect_with_error,
MemoryOrder::RELEASE);
chand->UpdateStateAndPickerLocked(
disconnect_error_.Store(op->disconnect_with_error, MemoryOrder::RELEASE);
UpdateStateAndPickerLocked(
GRPC_CHANNEL_SHUTDOWN, "shutdown from API",
absl::make_unique<LoadBalancingPolicy::TransientFailurePicker>(
GRPC_ERROR_REF(op->disconnect_with_error)));
}
}
GRPC_CHANNEL_STACK_UNREF(chand->owning_stack_, "start_transport_op");
GRPC_CHANNEL_STACK_UNREF(owning_stack_, "start_transport_op");
ExecCtx::Run(DEBUG_LOCATION, op->on_consumed, GRPC_ERROR_NONE);
}
@ -1885,13 +1848,10 @@ void ChannelData::StartTransportOp(grpc_channel_element* elem,
if (op->bind_pollset != nullptr) {
grpc_pollset_set_add_pollset(chand->interested_parties_, op->bind_pollset);
}
// Pop into control plane combiner for remaining ops.
op->handler_private.extra_arg = elem;
// Pop into control plane work_serializer for remaining ops.
GRPC_CHANNEL_STACK_REF(chand->owning_stack_, "start_transport_op");
chand->combiner_->Run(
GRPC_CLOSURE_INIT(&op->handler_private.closure,
ChannelData::StartTransportOpLocked, op, nullptr),
GRPC_ERROR_NONE);
chand->work_serializer_->Run(
[chand, op]() { chand->StartTransportOpLocked(op); }, DEBUG_LOCATION);
}
void ChannelData::GetChannelInfo(grpc_channel_element* elem,
@ -1942,14 +1902,13 @@ ChannelData::GetConnectedSubchannelInDataPlane(
return connected_subchannel->Ref();
}
void ChannelData::TryToConnectLocked(void* arg, grpc_error* /*error_ignored*/) {
auto* chand = static_cast<ChannelData*>(arg);
if (chand->resolving_lb_policy_ != nullptr) {
chand->resolving_lb_policy_->ExitIdleLocked();
void ChannelData::TryToConnectLocked() {
if (resolving_lb_policy_ != nullptr) {
resolving_lb_policy_->ExitIdleLocked();
} else {
chand->CreateResolvingLoadBalancingPolicyLocked();
CreateResolvingLoadBalancingPolicyLocked();
}
GRPC_CHANNEL_STACK_UNREF(chand->owning_stack_, "TryToConnect");
GRPC_CHANNEL_STACK_UNREF(owning_stack_, "TryToConnect");
}
grpc_connectivity_state ChannelData::CheckConnectivityState(
@ -1957,8 +1916,7 @@ grpc_connectivity_state ChannelData::CheckConnectivityState(
grpc_connectivity_state out = state_tracker_.state();
if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
GRPC_CHANNEL_STACK_REF(owning_stack_, "TryToConnect");
combiner_->Run(GRPC_CLOSURE_CREATE(TryToConnectLocked, this, nullptr),
GRPC_ERROR_NONE);
work_serializer_->Run([this]() { TryToConnectLocked(); }, DEBUG_LOCATION);
}
return out;
}
@ -3892,8 +3850,25 @@ bool CallData::PickSubchannelLocked(grpc_call_element* elem,
// The picker being null means that the channel is currently in IDLE state.
// The incoming call will make the channel exit IDLE.
if (chand->picker() == nullptr) {
// Bounce into the control plane combiner to exit IDLE.
chand->CheckConnectivityState(/*try_to_connect=*/true);
GRPC_CHANNEL_STACK_REF(chand->owning_stack(), "PickSubchannelLocked");
// Bounce into the control plane work serializer to exit IDLE. Since we are
// holding on to the data plane mutex here, we offload it on the ExecCtx so
// that we don't deadlock with ourselves.
ExecCtx::Run(
DEBUG_LOCATION,
GRPC_CLOSURE_CREATE(
[](void* arg, grpc_error* /*error*/) {
auto* chand = static_cast<ChannelData*>(arg);
chand->work_serializer()->Run(
[chand]() {
chand->CheckConnectivityState(/*try_to_connect=*/true);
GRPC_CHANNEL_STACK_UNREF(chand->owning_stack(),
"PickSubchannelLocked");
},
DEBUG_LOCATION);
},
chand, nullptr),
GRPC_ERROR_NONE);
// Queue the pick, so that it will be attempted once the channel
// becomes connected.
AddCallToQueuedPicksLocked(elem);

@ -125,8 +125,8 @@ class HttpProxyMapper : public ProxyMapperInterface {
if (no_proxy_str != nullptr) {
static const char* NO_PROXY_SEPARATOR = ",";
bool use_proxy = true;
grpc_core::UniquePtr<char> server_host;
grpc_core::UniquePtr<char> server_port;
std::string server_host;
std::string server_port;
if (!grpc_core::SplitHostPort(
uri->path[0] == '/' ? uri->path + 1 : uri->path, &server_host,
&server_port)) {
@ -136,7 +136,7 @@ class HttpProxyMapper : public ProxyMapperInterface {
server_uri);
gpr_free(no_proxy_str);
} else {
size_t uri_len = strlen(server_host.get());
size_t uri_len = server_host.size();
char** no_proxy_hosts;
size_t num_no_proxy_hosts;
gpr_string_split(no_proxy_str, NO_PROXY_SEPARATOR, &no_proxy_hosts,
@ -146,7 +146,8 @@ class HttpProxyMapper : public ProxyMapperInterface {
size_t no_proxy_len = strlen(no_proxy_entry);
if (no_proxy_len <= uri_len &&
gpr_stricmp(no_proxy_entry,
&(server_host.get()[uri_len - no_proxy_len])) == 0) {
&(server_host.c_str()[uri_len - no_proxy_len])) ==
0) {
gpr_log(GPR_INFO, "not using proxy for host in no_proxy list '%s'",
server_uri);
use_proxy = false;

@ -33,13 +33,12 @@ DebugOnlyTraceFlag grpc_trace_lb_policy_refcount(false, "lb_policy_refcount");
LoadBalancingPolicy::LoadBalancingPolicy(Args args, intptr_t initial_refcount)
: InternallyRefCounted(&grpc_trace_lb_policy_refcount, initial_refcount),
combiner_(GRPC_COMBINER_REF(args.combiner, "lb_policy")),
work_serializer_(std::move(args.work_serializer)),
interested_parties_(grpc_pollset_set_create()),
channel_control_helper_(std::move(args.channel_control_helper)) {}
LoadBalancingPolicy::~LoadBalancingPolicy() {
grpc_pollset_set_destroy(interested_parties_);
GRPC_COMBINER_UNREF(combiner_, "lb_policy");
}
void LoadBalancingPolicy::Orphan() {
@ -99,29 +98,31 @@ LoadBalancingPolicy::PickResult LoadBalancingPolicy::QueuePicker::Pick(
// 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 combiner, but we
// need to bounce into the control plane combiner to call
// 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_) {
exit_idle_called_ = true;
// Ref held by closure.
parent_->Ref(DEBUG_LOCATION, "QueuePicker::CallExitIdle").release();
parent_->combiner()->Run(
GRPC_CLOSURE_CREATE(&CallExitIdle, parent_.get(), nullptr),
GRPC_ERROR_NONE);
auto* parent = parent_->Ref().release(); // ref held by lambda.
ExecCtx::Run(DEBUG_LOCATION,
GRPC_CLOSURE_CREATE(
[](void* arg, grpc_error* /*error*/) {
auto* parent = static_cast<LoadBalancingPolicy*>(arg);
parent->work_serializer()->Run(
[parent]() {
parent->ExitIdleLocked();
parent->Unref();
},
DEBUG_LOCATION);
},
parent, nullptr),
GRPC_ERROR_NONE);
}
PickResult result;
result.type = PickResult::PICK_QUEUE;
return result;
}
void LoadBalancingPolicy::QueuePicker::CallExitIdle(void* arg,
grpc_error* /*error*/) {
LoadBalancingPolicy* parent = static_cast<LoadBalancingPolicy*>(arg);
parent->ExitIdleLocked();
parent->Unref(DEBUG_LOCATION, "QueuePicker::CallExitIdle");
}
//
// LoadBalancingPolicy::TransientFailurePicker
//

@ -24,15 +24,16 @@
#include <functional>
#include <iterator>
#include "absl/strings/string_view.h"
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/ext/filters/client_channel/subchannel_interface.h"
#include "src/core/lib/gprpp/map.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/string_view.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/iomgr/work_serializer.h"
#include "src/core/lib/transport/connectivity_state.h"
namespace grpc_core {
@ -72,7 +73,7 @@ extern DebugOnlyTraceFlag grpc_trace_lb_policy_refcount;
/// LoadBalacingPolicy API.
///
/// Note: All methods with a "Locked" suffix must be called from the
/// combiner passed to the constructor.
/// work_serializer passed to the constructor.
///
/// Any I/O done by the LB policy should be done under the pollset_set
/// returned by \a interested_parties().
@ -93,11 +94,11 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
/// 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.
std::map<StringView, double, StringLess> request_cost;
std::map<absl::string_view, double, StringLess> request_cost;
/// Application-specific resource utilization metrics. Metric names
/// are determined by the application. Each value is expressed as a
/// fraction of total resources available.
std::map<StringView, double, StringLess> utilization;
std::map<absl::string_view, double, StringLess> utilization;
};
/// Interface for accessing per-call state.
@ -123,12 +124,13 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
class MetadataInterface {
public:
class iterator
: public std::iterator<std::input_iterator_tag,
std::pair<StringView, StringView>, // value_type
std::ptrdiff_t, // difference_type
std::pair<StringView, StringView>*, // pointer
std::pair<StringView, StringView>& // reference
> {
: public std::iterator<
std::input_iterator_tag,
std::pair<absl::string_view, absl::string_view>, // value_type
std::ptrdiff_t, // difference_type
std::pair<absl::string_view, absl::string_view>*, // pointer
std::pair<absl::string_view, absl::string_view>& // reference
> {
public:
iterator(const MetadataInterface* md, intptr_t handle)
: md_(md), handle_(handle) {}
@ -155,7 +157,7 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
/// Implementations must ensure that the key and value remain alive
/// until the call ends. If desired, they may be allocated via
/// CallState::Alloc().
virtual void Add(StringView key, StringView value) = 0;
virtual void Add(absl::string_view key, absl::string_view value) = 0;
/// Iteration interface.
virtual iterator begin() const = 0;
@ -172,7 +174,7 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
friend class iterator;
virtual intptr_t IteratorHandleNext(intptr_t handle) const = 0;
virtual std::pair<StringView /*key*/, StringView /*value */>
virtual std::pair<absl::string_view /*key*/, absl::string_view /*value */>
IteratorHandleGet(intptr_t handle) const = 0;
};
@ -242,7 +244,7 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
/// live in the LB policy object itself.
///
/// Currently, pickers are always accessed from within the
/// client_channel data plane combiner, so they do not have to be
/// client_channel data plane mutex, so they do not have to be
/// thread-safe.
class SubchannelPicker {
public:
@ -276,7 +278,8 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
/// Adds a trace message associated with the channel.
enum TraceSeverity { TRACE_INFO, TRACE_WARNING, TRACE_ERROR };
virtual void AddTraceEvent(TraceSeverity severity, StringView message) = 0;
virtual void AddTraceEvent(TraceSeverity severity,
absl::string_view message) = 0;
};
/// Interface for configuration data used by an LB policy implementation.
@ -309,12 +312,8 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
/// Args used to instantiate an LB policy.
struct Args {
/// The combiner under which all LB policy calls will be run.
/// Policy does NOT take ownership of the reference to the combiner.
// TODO(roth): Once we have a C++-like interface for combiners, this
// API should change to take a smart pointer that does pass ownership
// of a reference.
Combiner* combiner = nullptr;
/// The work_serializer under which all LB policy calls will be run.
std::shared_ptr<WorkSerializer> work_serializer;
/// Channel control helper.
/// Note: LB policies MUST NOT call any method on the helper from
/// their constructor.
@ -352,7 +351,7 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
grpc_pollset_set* interested_parties() const { return interested_parties_; }
// Note: This must be invoked while holding the combiner.
// Note: This must be invoked while holding the work_serializer.
void Orphan() override;
// A picker that returns PICK_QUEUE for all picks.
@ -368,8 +367,6 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
PickResult Pick(PickArgs args) override;
private:
static void CallExitIdle(void* arg, grpc_error* error);
RefCountedPtr<LoadBalancingPolicy> parent_;
bool exit_idle_called_ = false;
};
@ -387,7 +384,9 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
};
protected:
Combiner* combiner() const { return combiner_; }
std::shared_ptr<WorkSerializer> work_serializer() const {
return work_serializer_;
}
// Note: LB policies MUST NOT call any method on the helper from their
// constructor.
@ -399,8 +398,8 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
virtual void ShutdownLocked() = 0;
private:
/// Combiner under which LB policy actions take place.
Combiner* combiner_;
/// Work Serializer under which LB policy actions take place.
std::shared_ptr<WorkSerializer> work_serializer_;
/// Owned pointer to interested parties in load balancing decisions.
grpc_pollset_set* interested_parties_;
/// Channel control helper.

@ -86,7 +86,8 @@ class ChildPolicyHandler::Helper
parent_->channel_control_helper()->RequestReresolution();
}
void AddTraceEvent(TraceSeverity severity, StringView message) override {
void AddTraceEvent(TraceSeverity severity,
absl::string_view message) override {
if (parent_->shutting_down_) return;
if (!CalledByPendingChild() && !CalledByCurrentChild()) return;
parent_->channel_control_helper()->AddTraceEvent(severity, message);
@ -251,7 +252,7 @@ OrphanablePtr<LoadBalancingPolicy> ChildPolicyHandler::CreateChildPolicy(
const char* child_policy_name, const grpc_channel_args& args) {
Helper* helper = new Helper(Ref(DEBUG_LOCATION, "Helper"));
LoadBalancingPolicy::Args lb_policy_args;
lb_policy_args.combiner = combiner();
lb_policy_args.work_serializer = work_serializer();
lb_policy_args.channel_control_helper =
std::unique_ptr<ChannelControlHelper>(helper);
lb_policy_args.args = &args;

@ -64,6 +64,8 @@
#include <limits.h>
#include <string.h>
#include "absl/container/inlined_vector.h"
#include <grpc/byte_buffer_reader.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
@ -91,7 +93,6 @@
#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/iomgr/combiner.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/timer.h"
@ -179,11 +180,11 @@ class GrpcLb : public LoadBalancingPolicy {
static void OnBalancerMessageReceived(void* arg, grpc_error* error);
static void OnBalancerStatusReceived(void* arg, grpc_error* error);
static void MaybeSendClientLoadReportLocked(void* arg, grpc_error* error);
static void ClientLoadReportDoneLocked(void* arg, grpc_error* error);
static void OnInitialRequestSentLocked(void* arg, grpc_error* error);
static void OnBalancerMessageReceivedLocked(void* arg, grpc_error* error);
static void OnBalancerStatusReceivedLocked(void* arg, grpc_error* error);
void MaybeSendClientLoadReportLocked(grpc_error* error);
void ClientLoadReportDoneLocked(grpc_error* error);
void OnInitialRequestSentLocked();
void OnBalancerMessageReceivedLocked();
void OnBalancerStatusReceivedLocked(grpc_error* error);
// The owning LB policy.
RefCountedPtr<LoadBalancingPolicy> grpclb_policy_;
@ -248,16 +249,16 @@ class GrpcLb : public LoadBalancingPolicy {
// should not be dropped.
//
// Note: This is called from the picker, so it will be invoked in
// the channel's data plane combiner, NOT the control plane
// combiner. It should not be accessed by any other part of the LB
// 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.
const char* ShouldDrop();
private:
std::vector<GrpcLbServer> serverlist_;
// Guarded by the channel's data plane combiner, NOT the control
// plane combiner. It should not be accessed by anything but the
// 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;
};
@ -296,7 +297,8 @@ class GrpcLb : public LoadBalancingPolicy {
void UpdateState(grpc_connectivity_state state,
std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity, StringView message) override;
void AddTraceEvent(TraceSeverity severity,
absl::string_view message) override;
private:
RefCountedPtr<GrpcLb> parent_;
@ -305,7 +307,7 @@ class GrpcLb : public LoadBalancingPolicy {
class StateWatcher : public AsyncConnectivityStateWatcherInterface {
public:
explicit StateWatcher(RefCountedPtr<GrpcLb> parent)
: AsyncConnectivityStateWatcherInterface(parent->combiner()),
: AsyncConnectivityStateWatcherInterface(parent->work_serializer()),
parent_(std::move(parent)) {}
~StateWatcher() { parent_.reset(DEBUG_LOCATION, "StateWatcher"); }
@ -340,18 +342,19 @@ class GrpcLb : public LoadBalancingPolicy {
// Helper functions used in UpdateLocked().
void ProcessAddressesAndChannelArgsLocked(const ServerAddressList& addresses,
const grpc_channel_args& args);
void CancelBalancerChannelConnectivityWatchLocked();
// Methods for dealing with fallback state.
void MaybeEnterFallbackModeAfterStartup();
static void OnFallbackTimer(void* arg, grpc_error* error);
static void OnFallbackTimerLocked(void* arg, grpc_error* error);
void OnFallbackTimerLocked(grpc_error* error);
// Methods for dealing with the balancer call.
void StartBalancerCallLocked();
void StartBalancerCallRetryTimerLocked();
static void OnBalancerCallRetryTimer(void* arg, grpc_error* error);
static void OnBalancerCallRetryTimerLocked(void* arg, grpc_error* error);
void OnBalancerCallRetryTimerLocked(grpc_error* error);
// Methods for dealing with the child policy.
grpc_channel_args* CreateChildPolicyArgsLocked(
@ -555,7 +558,7 @@ ServerAddressList GrpcLb::Serverlist::GetServerAddressList(
lb_token[0] = '\0';
}
// Add address.
InlinedVector<grpc_arg, 2> args_to_add;
absl::InlinedVector<grpc_arg, 2> args_to_add;
args_to_add.emplace_back(grpc_channel_arg_pointer_create(
const_cast<char*>(GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN), lb_token,
&lb_token_arg_vtable));
@ -626,7 +629,7 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) {
// how to interpret it.
args.initial_metadata->Add(
kGrpcLbClientStatsMetadataKey,
StringView(reinterpret_cast<const char*>(client_stats), 0));
absl::string_view(reinterpret_cast<const char*>(client_stats), 0));
// Update calls-started.
client_stats->AddCallStarted();
}
@ -719,7 +722,8 @@ void GrpcLb::Helper::RequestReresolution() {
}
}
void GrpcLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
void GrpcLb::Helper::AddTraceEvent(TraceSeverity severity,
absl::string_view message) {
if (parent_->shutting_down_) return;
parent_->channel_control_helper()->AddTraceEvent(severity, message);
}
@ -739,6 +743,15 @@ GrpcLb::BalancerCallState::BalancerCallState(
// the polling entities from client_channel.
GPR_ASSERT(grpclb_policy()->server_name_ != nullptr);
GPR_ASSERT(grpclb_policy()->server_name_[0] != '\0');
// Closure Initialization
GRPC_CLOSURE_INIT(&lb_on_initial_request_sent_, OnInitialRequestSent, this,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&lb_on_balancer_message_received_,
OnBalancerMessageReceived, this, grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&lb_on_balancer_status_received_, OnBalancerStatusReceived,
this, grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&client_load_report_closure_, MaybeSendClientLoadReport,
this, grpc_schedule_on_exec_ctx);
const grpc_millis deadline =
grpclb_policy()->lb_call_timeout_ms_ == 0
? GRPC_MILLIS_INF_FUTURE
@ -815,8 +828,6 @@ void GrpcLb::BalancerCallState::StartQuery() {
// with the callback.
auto self = Ref(DEBUG_LOCATION, "on_initial_request_sent");
self.release();
GRPC_CLOSURE_INIT(&lb_on_initial_request_sent_, OnInitialRequestSent, this,
grpc_schedule_on_exec_ctx);
call_error = grpc_call_start_batch_and_execute(
lb_call_, ops, (size_t)(op - ops), &lb_on_initial_request_sent_);
GPR_ASSERT(GRPC_CALL_OK == call_error);
@ -839,8 +850,6 @@ void GrpcLb::BalancerCallState::StartQuery() {
// with the callback.
self = Ref(DEBUG_LOCATION, "on_message_received");
self.release();
GRPC_CLOSURE_INIT(&lb_on_balancer_message_received_,
OnBalancerMessageReceived, this, grpc_schedule_on_exec_ctx);
call_error = grpc_call_start_batch_and_execute(
lb_call_, ops, (size_t)(op - ops), &lb_on_balancer_message_received_);
GPR_ASSERT(GRPC_CALL_OK == call_error);
@ -857,8 +866,6 @@ void GrpcLb::BalancerCallState::StartQuery() {
// This callback signals the end of the LB call, so it relies on the initial
// ref instead of a new ref. When it's invoked, it's the initial ref that is
// unreffed.
GRPC_CLOSURE_INIT(&lb_on_balancer_status_received_, OnBalancerStatusReceived,
this, grpc_schedule_on_exec_ctx);
call_error = grpc_call_start_batch_and_execute(
lb_call_, ops, (size_t)(op - ops), &lb_on_balancer_status_received_);
GPR_ASSERT(GRPC_CALL_OK == call_error);
@ -877,28 +884,27 @@ void GrpcLb::BalancerCallState::ScheduleNextClientLoadReportLocked() {
void GrpcLb::BalancerCallState::MaybeSendClientLoadReport(void* arg,
grpc_error* error) {
BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
lb_calld->grpclb_policy()->combiner()->Run(
GRPC_CLOSURE_INIT(&lb_calld->client_load_report_closure_,
MaybeSendClientLoadReportLocked, lb_calld, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // ref owned by lambda
lb_calld->grpclb_policy()->work_serializer()->Run(
[lb_calld, error]() { lb_calld->MaybeSendClientLoadReportLocked(error); },
DEBUG_LOCATION);
}
void GrpcLb::BalancerCallState::MaybeSendClientLoadReportLocked(
void* arg, grpc_error* error) {
BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
GrpcLb* grpclb_policy = lb_calld->grpclb_policy();
lb_calld->client_load_report_timer_callback_pending_ = false;
if (error != GRPC_ERROR_NONE || lb_calld != grpclb_policy->lb_calld_.get()) {
lb_calld->Unref(DEBUG_LOCATION, "client_load_report");
grpc_error* error) {
client_load_report_timer_callback_pending_ = false;
if (error != GRPC_ERROR_NONE || this != grpclb_policy()->lb_calld_.get()) {
Unref(DEBUG_LOCATION, "client_load_report");
GRPC_ERROR_UNREF(error);
return;
}
// If we've already sent the initial request, then we can go ahead and send
// the load report. Otherwise, we need to wait until the initial request has
// been sent to send this (see OnInitialRequestSentLocked()).
if (lb_calld->send_message_payload_ == nullptr) {
lb_calld->SendClientLoadReportLocked();
if (send_message_payload_ == nullptr) {
SendClientLoadReportLocked();
} else {
lb_calld->client_load_report_is_due_ = true;
client_load_report_is_due_ = true;
}
}
@ -957,110 +963,98 @@ void GrpcLb::BalancerCallState::SendClientLoadReportLocked() {
void GrpcLb::BalancerCallState::ClientLoadReportDone(void* arg,
grpc_error* error) {
BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
lb_calld->grpclb_policy()->combiner()->Run(
GRPC_CLOSURE_INIT(&lb_calld->client_load_report_closure_,
ClientLoadReportDoneLocked, lb_calld, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // ref owned by lambda
lb_calld->grpclb_policy()->work_serializer()->Run(
[lb_calld, error]() { lb_calld->ClientLoadReportDoneLocked(error); },
DEBUG_LOCATION);
}
void GrpcLb::BalancerCallState::ClientLoadReportDoneLocked(void* arg,
grpc_error* error) {
BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
GrpcLb* grpclb_policy = lb_calld->grpclb_policy();
grpc_byte_buffer_destroy(lb_calld->send_message_payload_);
lb_calld->send_message_payload_ = nullptr;
if (error != GRPC_ERROR_NONE || lb_calld != grpclb_policy->lb_calld_.get()) {
lb_calld->Unref(DEBUG_LOCATION, "client_load_report");
void GrpcLb::BalancerCallState::ClientLoadReportDoneLocked(grpc_error* error) {
grpc_byte_buffer_destroy(send_message_payload_);
send_message_payload_ = nullptr;
if (error != GRPC_ERROR_NONE || this != grpclb_policy()->lb_calld_.get()) {
Unref(DEBUG_LOCATION, "client_load_report");
GRPC_ERROR_UNREF(error);
return;
}
lb_calld->ScheduleNextClientLoadReportLocked();
ScheduleNextClientLoadReportLocked();
}
void GrpcLb::BalancerCallState::OnInitialRequestSent(void* arg,
grpc_error* error) {
grpc_error* /*error*/) {
BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
lb_calld->grpclb_policy()->combiner()->Run(
GRPC_CLOSURE_INIT(&lb_calld->lb_on_initial_request_sent_,
OnInitialRequestSentLocked, lb_calld, nullptr),
GRPC_ERROR_REF(error));
lb_calld->grpclb_policy()->work_serializer()->Run(
[lb_calld]() { lb_calld->OnInitialRequestSentLocked(); }, DEBUG_LOCATION);
}
void GrpcLb::BalancerCallState::OnInitialRequestSentLocked(
void* arg, grpc_error* /*error*/) {
BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
grpc_byte_buffer_destroy(lb_calld->send_message_payload_);
lb_calld->send_message_payload_ = nullptr;
void GrpcLb::BalancerCallState::OnInitialRequestSentLocked() {
grpc_byte_buffer_destroy(send_message_payload_);
send_message_payload_ = nullptr;
// If we attempted to send a client load report before the initial request was
// sent (and this lb_calld is still in use), send the load report now.
if (lb_calld->client_load_report_is_due_ &&
lb_calld == lb_calld->grpclb_policy()->lb_calld_.get()) {
lb_calld->SendClientLoadReportLocked();
lb_calld->client_load_report_is_due_ = false;
if (client_load_report_is_due_ && this == grpclb_policy()->lb_calld_.get()) {
SendClientLoadReportLocked();
client_load_report_is_due_ = false;
}
lb_calld->Unref(DEBUG_LOCATION, "on_initial_request_sent");
Unref(DEBUG_LOCATION, "on_initial_request_sent");
}
void GrpcLb::BalancerCallState::OnBalancerMessageReceived(void* arg,
grpc_error* error) {
void GrpcLb::BalancerCallState::OnBalancerMessageReceived(
void* arg, grpc_error* /*error*/) {
BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
lb_calld->grpclb_policy()->combiner()->Run(
GRPC_CLOSURE_INIT(&lb_calld->lb_on_balancer_message_received_,
OnBalancerMessageReceivedLocked, lb_calld, nullptr),
GRPC_ERROR_REF(error));
lb_calld->grpclb_policy()->work_serializer()->Run(
[lb_calld]() { lb_calld->OnBalancerMessageReceivedLocked(); },
DEBUG_LOCATION);
}
void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
void* arg, grpc_error* /*error*/) {
BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
GrpcLb* grpclb_policy = lb_calld->grpclb_policy();
void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked() {
// Null payload means the LB call was cancelled.
if (lb_calld != grpclb_policy->lb_calld_.get() ||
lb_calld->recv_message_payload_ == nullptr) {
lb_calld->Unref(DEBUG_LOCATION, "on_message_received");
if (this != grpclb_policy()->lb_calld_.get() ||
recv_message_payload_ == nullptr) {
Unref(DEBUG_LOCATION, "on_message_received");
return;
}
grpc_byte_buffer_reader bbr;
grpc_byte_buffer_reader_init(&bbr, lb_calld->recv_message_payload_);
grpc_byte_buffer_reader_init(&bbr, recv_message_payload_);
grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
grpc_byte_buffer_reader_destroy(&bbr);
grpc_byte_buffer_destroy(lb_calld->recv_message_payload_);
lb_calld->recv_message_payload_ = nullptr;
grpc_byte_buffer_destroy(recv_message_payload_);
recv_message_payload_ = nullptr;
GrpcLbResponse response;
upb::Arena arena;
if (!GrpcLbResponseParse(response_slice, arena.ptr(), &response) ||
(response.type == response.INITIAL && lb_calld->seen_initial_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, lb_calld, response_slice_str);
grpclb_policy(), this, response_slice_str);
gpr_free(response_slice_str);
} else {
switch (response.type) {
case response.INITIAL: {
if (response.client_stats_report_interval != 0) {
lb_calld->client_stats_report_interval_ =
client_stats_report_interval_ =
GPR_MAX(GPR_MS_PER_SEC, response.client_stats_report_interval);
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
gpr_log(GPR_INFO,
"[grpclb %p] lb_calld=%p: Received initial LB response "
"message; client load reporting interval = %" PRId64
" milliseconds",
grpclb_policy, lb_calld,
lb_calld->client_stats_report_interval_);
grpclb_policy(), this, client_stats_report_interval_);
}
} else if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
gpr_log(GPR_INFO,
"[grpclb %p] lb_calld=%p: Received initial LB response "
"message; client load reporting NOT enabled",
grpclb_policy, lb_calld);
grpclb_policy(), this);
}
lb_calld->seen_initial_response_ = true;
seen_initial_response_ = true;
break;
}
case response.SERVERLIST: {
GPR_ASSERT(lb_calld->lb_call_ != nullptr);
GPR_ASSERT(lb_call_ != nullptr);
auto serverlist_wrapper =
MakeRefCounted<Serverlist>(std::move(response.serverlist));
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
@ -1069,28 +1063,27 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
gpr_log(GPR_INFO,
"[grpclb %p] lb_calld=%p: Serverlist with %" PRIuPTR
" servers received:\n%s",
grpclb_policy, lb_calld,
grpclb_policy(), this,
serverlist_wrapper->serverlist().size(),
serverlist_text.get());
}
lb_calld->seen_serverlist_ = true;
seen_serverlist_ = true;
// Start sending client load report only after we start using the
// serverlist returned from the current LB call.
if (lb_calld->client_stats_report_interval_ > 0 &&
lb_calld->client_stats_ == nullptr) {
lb_calld->client_stats_ = MakeRefCounted<GrpcLbClientStats>();
if (client_stats_report_interval_ > 0 && client_stats_ == nullptr) {
client_stats_ = MakeRefCounted<GrpcLbClientStats>();
// Ref held by callback.
lb_calld->Ref(DEBUG_LOCATION, "client_load_report").release();
lb_calld->ScheduleNextClientLoadReportLocked();
Ref(DEBUG_LOCATION, "client_load_report").release();
ScheduleNextClientLoadReportLocked();
}
// Check if the serverlist differs from the previous one.
if (grpclb_policy->serverlist_ != nullptr &&
*grpclb_policy->serverlist_ == *serverlist_wrapper) {
if (grpclb_policy()->serverlist_ != nullptr &&
*grpclb_policy()->serverlist_ == *serverlist_wrapper) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
gpr_log(GPR_INFO,
"[grpclb %p] lb_calld=%p: Incoming server list identical "
"to current, ignoring.",
grpclb_policy, lb_calld);
grpclb_policy(), this);
}
} else { // New serverlist.
// Dispose of the fallback.
@ -1112,130 +1105,124 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
// the grpclb implementation at this point, since we're deprecating
// it in favor of the xds policy. We will implement this the
// right way in the xds policy instead.
if (grpclb_policy->fallback_mode_) {
if (grpclb_policy()->fallback_mode_) {
gpr_log(GPR_INFO,
"[grpclb %p] Received response from balancer; exiting "
"fallback mode",
grpclb_policy);
grpclb_policy->fallback_mode_ = false;
grpclb_policy());
grpclb_policy()->fallback_mode_ = false;
}
if (grpclb_policy->fallback_at_startup_checks_pending_) {
grpclb_policy->fallback_at_startup_checks_pending_ = false;
grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_);
grpclb_policy->CancelBalancerChannelConnectivityWatchLocked();
if (grpclb_policy()->fallback_at_startup_checks_pending_) {
grpclb_policy()->fallback_at_startup_checks_pending_ = false;
grpc_timer_cancel(&grpclb_policy()->lb_fallback_timer_);
grpclb_policy()->CancelBalancerChannelConnectivityWatchLocked();
}
// Update the serverlist in the GrpcLb instance. This serverlist
// instance will be destroyed either upon the next update or when the
// GrpcLb instance is destroyed.
grpclb_policy->serverlist_ = std::move(serverlist_wrapper);
grpclb_policy->CreateOrUpdateChildPolicyLocked();
grpclb_policy()->serverlist_ = std::move(serverlist_wrapper);
grpclb_policy()->CreateOrUpdateChildPolicyLocked();
}
break;
}
case response.FALLBACK: {
if (!grpclb_policy->fallback_mode_) {
if (!grpclb_policy()->fallback_mode_) {
gpr_log(GPR_INFO,
"[grpclb %p] Entering fallback mode as requested by balancer",
grpclb_policy);
if (grpclb_policy->fallback_at_startup_checks_pending_) {
grpclb_policy->fallback_at_startup_checks_pending_ = false;
grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_);
grpclb_policy->CancelBalancerChannelConnectivityWatchLocked();
grpclb_policy());
if (grpclb_policy()->fallback_at_startup_checks_pending_) {
grpclb_policy()->fallback_at_startup_checks_pending_ = false;
grpc_timer_cancel(&grpclb_policy()->lb_fallback_timer_);
grpclb_policy()->CancelBalancerChannelConnectivityWatchLocked();
}
grpclb_policy->fallback_mode_ = true;
grpclb_policy->CreateOrUpdateChildPolicyLocked();
grpclb_policy()->fallback_mode_ = true;
grpclb_policy()->CreateOrUpdateChildPolicyLocked();
// Reset serverlist, so that if the balancer exits fallback
// mode by sending the same serverlist we were previously
// using, we don't incorrectly ignore it as a duplicate.
grpclb_policy->serverlist_.reset();
grpclb_policy()->serverlist_.reset();
}
break;
}
}
}
grpc_slice_unref_internal(response_slice);
if (!grpclb_policy->shutting_down_) {
if (!grpclb_policy()->shutting_down_) {
// Keep listening for serverlist updates.
grpc_op op;
memset(&op, 0, sizeof(op));
op.op = GRPC_OP_RECV_MESSAGE;
op.data.recv_message.recv_message = &lb_calld->recv_message_payload_;
op.data.recv_message.recv_message = &recv_message_payload_;
op.flags = 0;
op.reserved = nullptr;
// Reuse the "OnBalancerMessageReceivedLocked" ref taken in StartQuery().
GRPC_CLOSURE_INIT(&lb_calld->lb_on_balancer_message_received_,
GrpcLb::BalancerCallState::OnBalancerMessageReceived,
lb_calld, grpc_schedule_on_exec_ctx);
const grpc_call_error call_error = grpc_call_start_batch_and_execute(
lb_calld->lb_call_, &op, 1,
&lb_calld->lb_on_balancer_message_received_);
lb_call_, &op, 1, &lb_on_balancer_message_received_);
GPR_ASSERT(GRPC_CALL_OK == call_error);
} else {
lb_calld->Unref(DEBUG_LOCATION, "on_message_received+grpclb_shutdown");
Unref(DEBUG_LOCATION, "on_message_received+grpclb_shutdown");
}
}
void GrpcLb::BalancerCallState::OnBalancerStatusReceived(void* arg,
grpc_error* error) {
BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
lb_calld->grpclb_policy()->combiner()->Run(
GRPC_CLOSURE_INIT(&lb_calld->lb_on_balancer_status_received_,
OnBalancerStatusReceivedLocked, lb_calld, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // owned by lambda
lb_calld->grpclb_policy()->work_serializer()->Run(
[lb_calld, error]() { lb_calld->OnBalancerStatusReceivedLocked(error); },
DEBUG_LOCATION);
}
void GrpcLb::BalancerCallState::OnBalancerStatusReceivedLocked(
void* arg, grpc_error* error) {
BalancerCallState* lb_calld = static_cast<BalancerCallState*>(arg);
GrpcLb* grpclb_policy = lb_calld->grpclb_policy();
GPR_ASSERT(lb_calld->lb_call_ != nullptr);
grpc_error* error) {
GPR_ASSERT(lb_call_ != nullptr);
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
char* status_details =
grpc_slice_to_c_string(lb_calld->lb_call_status_details_);
char* status_details = grpc_slice_to_c_string(lb_call_status_details_);
gpr_log(GPR_INFO,
"[grpclb %p] lb_calld=%p: Status from LB server received. "
"Status = %d, details = '%s', (lb_call: %p), error '%s'",
grpclb_policy, lb_calld, lb_calld->lb_call_status_, status_details,
lb_calld->lb_call_, grpc_error_string(error));
grpclb_policy(), this, lb_call_status_, status_details, lb_call_,
grpc_error_string(error));
gpr_free(status_details);
}
GRPC_ERROR_UNREF(error);
// If this lb_calld is still in use, this call ended because of a failure so
// we want to retry connecting. Otherwise, we have deliberately ended this
// call and no further action is required.
if (lb_calld == grpclb_policy->lb_calld_.get()) {
if (this == grpclb_policy()->lb_calld_.get()) {
// If the fallback-at-startup checks are pending, go into fallback mode
// immediately. This short-circuits the timeout for the fallback-at-startup
// case.
if (grpclb_policy->fallback_at_startup_checks_pending_) {
GPR_ASSERT(!lb_calld->seen_serverlist_);
if (grpclb_policy()->fallback_at_startup_checks_pending_) {
GPR_ASSERT(!seen_serverlist_);
gpr_log(GPR_INFO,
"[grpclb %p] Balancer call finished without receiving "
"serverlist; entering fallback mode",
grpclb_policy);
grpclb_policy->fallback_at_startup_checks_pending_ = false;
grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_);
grpclb_policy->CancelBalancerChannelConnectivityWatchLocked();
grpclb_policy->fallback_mode_ = true;
grpclb_policy->CreateOrUpdateChildPolicyLocked();
grpclb_policy());
grpclb_policy()->fallback_at_startup_checks_pending_ = false;
grpc_timer_cancel(&grpclb_policy()->lb_fallback_timer_);
grpclb_policy()->CancelBalancerChannelConnectivityWatchLocked();
grpclb_policy()->fallback_mode_ = true;
grpclb_policy()->CreateOrUpdateChildPolicyLocked();
} else {
// This handles the fallback-after-startup case.
grpclb_policy->MaybeEnterFallbackModeAfterStartup();
grpclb_policy()->MaybeEnterFallbackModeAfterStartup();
}
grpclb_policy->lb_calld_.reset();
GPR_ASSERT(!grpclb_policy->shutting_down_);
grpclb_policy->channel_control_helper()->RequestReresolution();
if (lb_calld->seen_initial_response_) {
grpclb_policy()->lb_calld_.reset();
GPR_ASSERT(!grpclb_policy()->shutting_down_);
grpclb_policy()->channel_control_helper()->RequestReresolution();
if (seen_initial_response_) {
// If we lose connection to the LB server, reset the backoff and restart
// the LB call immediately.
grpclb_policy->lb_call_backoff_.Reset();
grpclb_policy->StartBalancerCallLocked();
grpclb_policy()->lb_call_backoff_.Reset();
grpclb_policy()->StartBalancerCallLocked();
} else {
// If this LB call fails establishing any connection to the LB server,
// retry later.
grpclb_policy->StartBalancerCallRetryTimerLocked();
grpclb_policy()->StartBalancerCallRetryTimerLocked();
}
}
lb_calld->Unref(DEBUG_LOCATION, "lb_call_ended");
Unref(DEBUG_LOCATION, "lb_call_ended");
}
//
@ -1290,7 +1277,7 @@ grpc_channel_args* BuildBalancerChannelArgs(
GRPC_ARG_CHANNELZ_CHANNEL_NODE,
};
// Channel args to add.
InlinedVector<grpc_arg, 3> args_to_add;
absl::InlinedVector<grpc_arg, 3> args_to_add;
// The fake resolver response generator, which we use to inject
// address updates into the LB channel.
args_to_add.emplace_back(
@ -1332,6 +1319,11 @@ GrpcLb::GrpcLb(Args args)
.set_jitter(GRPC_GRPCLB_RECONNECT_JITTER)
.set_max_backoff(GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS *
1000)) {
// Closure Initialization
GRPC_CLOSURE_INIT(&lb_on_fallback_, &GrpcLb::OnFallbackTimer, this,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&lb_on_call_retry_, &GrpcLb::OnBalancerCallRetryTimer, this,
grpc_schedule_on_exec_ctx);
// Record server name.
const grpc_arg* arg = grpc_channel_args_find(args.args, GRPC_ARG_SERVER_URI);
const char* server_uri = grpc_channel_arg_get_string(arg);
@ -1416,8 +1408,6 @@ void GrpcLb::UpdateLocked(UpdateArgs args) {
// Start timer.
grpc_millis deadline = ExecCtx::Get()->Now() + fallback_at_startup_timeout_;
Ref(DEBUG_LOCATION, "on_fallback_timer").release(); // Ref for callback
GRPC_CLOSURE_INIT(&lb_on_fallback_, &GrpcLb::OnFallbackTimer, this,
grpc_schedule_on_exec_ctx);
grpc_timer_init(&lb_fallback_timer_, deadline, &lb_on_fallback_);
// Start watching the channel's connectivity state. If the channel
// goes into state TRANSIENT_FAILURE before the timer fires, we go into
@ -1529,33 +1519,30 @@ void GrpcLb::StartBalancerCallRetryTimerLocked() {
// with the callback.
auto self = Ref(DEBUG_LOCATION, "on_balancer_call_retry_timer");
self.release();
GRPC_CLOSURE_INIT(&lb_on_call_retry_, &GrpcLb::OnBalancerCallRetryTimer, this,
grpc_schedule_on_exec_ctx);
retry_timer_callback_pending_ = true;
grpc_timer_init(&lb_call_retry_timer_, next_try, &lb_on_call_retry_);
}
void GrpcLb::OnBalancerCallRetryTimer(void* arg, grpc_error* error) {
GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
grpclb_policy->combiner()->Run(
GRPC_CLOSURE_INIT(&grpclb_policy->lb_on_call_retry_,
&GrpcLb::OnBalancerCallRetryTimerLocked, grpclb_policy,
nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // ref owned by lambda
grpclb_policy->work_serializer()->Run(
[grpclb_policy, error]() {
grpclb_policy->OnBalancerCallRetryTimerLocked(error);
},
DEBUG_LOCATION);
}
void GrpcLb::OnBalancerCallRetryTimerLocked(void* arg, grpc_error* error) {
GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
grpclb_policy->retry_timer_callback_pending_ = false;
if (!grpclb_policy->shutting_down_ && error == GRPC_ERROR_NONE &&
grpclb_policy->lb_calld_ == nullptr) {
void GrpcLb::OnBalancerCallRetryTimerLocked(grpc_error* error) {
retry_timer_callback_pending_ = false;
if (!shutting_down_ && error == GRPC_ERROR_NONE && lb_calld_ == nullptr) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
gpr_log(GPR_INFO, "[grpclb %p] Restarting call to LB server",
grpclb_policy);
gpr_log(GPR_INFO, "[grpclb %p] Restarting call to LB server", this);
}
grpclb_policy->StartBalancerCallLocked();
StartBalancerCallLocked();
}
grpclb_policy->Unref(DEBUG_LOCATION, "on_balancer_call_retry_timer");
Unref(DEBUG_LOCATION, "on_balancer_call_retry_timer");
GRPC_ERROR_UNREF(error);
}
//
@ -1582,28 +1569,28 @@ void GrpcLb::MaybeEnterFallbackModeAfterStartup() {
void GrpcLb::OnFallbackTimer(void* arg, grpc_error* error) {
GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
grpclb_policy->combiner()->Run(
GRPC_CLOSURE_INIT(&grpclb_policy->lb_on_fallback_,
&GrpcLb::OnFallbackTimerLocked, grpclb_policy, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // ref owned by lambda
grpclb_policy->work_serializer()->Run(
[grpclb_policy, error]() { grpclb_policy->OnFallbackTimerLocked(error); },
DEBUG_LOCATION);
}
void GrpcLb::OnFallbackTimerLocked(void* arg, grpc_error* error) {
GrpcLb* grpclb_policy = static_cast<GrpcLb*>(arg);
void GrpcLb::OnFallbackTimerLocked(grpc_error* error) {
// If we receive a serverlist after the timer fires but before this callback
// actually runs, don't fall back.
if (grpclb_policy->fallback_at_startup_checks_pending_ &&
!grpclb_policy->shutting_down_ && error == GRPC_ERROR_NONE) {
if (fallback_at_startup_checks_pending_ && !shutting_down_ &&
error == GRPC_ERROR_NONE) {
gpr_log(GPR_INFO,
"[grpclb %p] No response from balancer after fallback timeout; "
"entering fallback mode",
grpclb_policy);
grpclb_policy->fallback_at_startup_checks_pending_ = false;
grpclb_policy->CancelBalancerChannelConnectivityWatchLocked();
grpclb_policy->fallback_mode_ = true;
grpclb_policy->CreateOrUpdateChildPolicyLocked();
this);
fallback_at_startup_checks_pending_ = false;
CancelBalancerChannelConnectivityWatchLocked();
fallback_mode_ = true;
CreateOrUpdateChildPolicyLocked();
}
grpclb_policy->Unref(DEBUG_LOCATION, "on_fallback_timer");
Unref(DEBUG_LOCATION, "on_fallback_timer");
GRPC_ERROR_UNREF(error);
}
//
@ -1612,7 +1599,7 @@ void GrpcLb::OnFallbackTimerLocked(void* arg, grpc_error* error) {
grpc_channel_args* GrpcLb::CreateChildPolicyArgsLocked(
bool is_backend_from_grpclb_load_balancer) {
InlinedVector<grpc_arg, 2> args_to_add;
absl::InlinedVector<grpc_arg, 2> args_to_add;
args_to_add.emplace_back(grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER),
is_backend_from_grpclb_load_balancer));
@ -1627,7 +1614,7 @@ grpc_channel_args* GrpcLb::CreateChildPolicyArgsLocked(
OrphanablePtr<LoadBalancingPolicy> GrpcLb::CreateChildPolicyLocked(
const grpc_channel_args* args) {
LoadBalancingPolicy::Args lb_policy_args;
lb_policy_args.combiner = combiner();
lb_policy_args.work_serializer = work_serializer();
lb_policy_args.args = args;
lb_policy_args.channel_control_helper = absl::make_unique<Helper>(Ref());
OrphanablePtr<LoadBalancingPolicy> lb_policy =

@ -22,6 +22,8 @@
#include <string.h>
#include "absl/container/inlined_vector.h"
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
@ -71,8 +73,8 @@ RefCountedPtr<TargetAuthorityTable> CreateTargetAuthorityTable(
grpc_channel_args* ModifyGrpclbBalancerChannelArgs(
const ServerAddressList& addresses, grpc_channel_args* args) {
InlinedVector<const char*, 1> args_to_remove;
InlinedVector<grpc_arg, 2> args_to_add;
absl::InlinedVector<const char*, 1> args_to_remove;
absl::InlinedVector<grpc_arg, 2> args_to_add;
// Add arg for targets info table.
RefCountedPtr<TargetAuthorityTable> target_authority_table =
CreateTargetAuthorityTable(addresses);

@ -23,7 +23,8 @@
#include <grpc/support/atm.h>
#include "src/core/lib/gprpp/inlined_vector.h"
#include "absl/container/inlined_vector.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/sync.h"
@ -40,7 +41,7 @@ class GrpcLbClientStats : public RefCounted<GrpcLbClientStats> {
: token(std::move(token)), count(count) {}
};
typedef InlinedVector<DropTokenCount, 10> DroppedCallCounts;
typedef absl::InlinedVector<DropTokenCount, 10> DroppedCallCounts;
void AddCallStarted();
void AddCallFinished(bool finished_with_client_failed_to_send,

@ -31,8 +31,8 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
namespace grpc_core {
@ -152,7 +152,8 @@ class PriorityLb : public LoadBalancingPolicy {
void UpdateState(grpc_connectivity_state state,
std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity, StringView message) override;
void AddTraceEvent(TraceSeverity severity,
absl::string_view message) override;
private:
RefCountedPtr<ChildPriority> priority_;
@ -169,9 +170,9 @@ class PriorityLb : public LoadBalancingPolicy {
void StartFailoverTimerLocked();
static void OnFailoverTimer(void* arg, grpc_error* error);
static void OnFailoverTimerLocked(void* arg, grpc_error* error);
void OnFailoverTimerLocked(grpc_error* error);
static void OnDeactivationTimer(void* arg, grpc_error* error);
static void OnDeactivationTimerLocked(void* arg, grpc_error* error);
void OnDeactivationTimerLocked(grpc_error* error);
RefCountedPtr<PriorityLb> priority_policy_;
const std::string name_;
@ -189,7 +190,6 @@ class PriorityLb : public LoadBalancingPolicy {
// States of failover.
grpc_timer failover_timer_;
grpc_closure on_failover_timer_;
grpc_closure on_failover_timer_locked_;
bool failover_timer_callback_pending_ = false;
};
@ -492,8 +492,8 @@ PriorityLb::ChildPriority::ChildPriority(
}
GRPC_CLOSURE_INIT(&on_failover_timer_, OnFailoverTimer, this,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&on_failover_timer_locked_, OnFailoverTimerLocked, this,
nullptr);
GRPC_CLOSURE_INIT(&on_deactivation_timer_, OnDeactivationTimer, this,
grpc_schedule_on_exec_ctx);
// Start the failover timer.
StartFailoverTimerLocked();
}
@ -550,7 +550,7 @@ OrphanablePtr<LoadBalancingPolicy>
PriorityLb::ChildPriority::CreateChildPolicyLocked(
const grpc_channel_args* args) {
LoadBalancingPolicy::Args lb_policy_args;
lb_policy_args.combiner = priority_policy_->combiner();
lb_policy_args.work_serializer = priority_policy_->work_serializer();
lb_policy_args.args = args;
lb_policy_args.channel_control_helper =
absl::make_unique<Helper>(this->Ref(DEBUG_LOCATION, "Helper"));
@ -631,26 +631,25 @@ void PriorityLb::ChildPriority::MaybeCancelFailoverTimerLocked() {
void PriorityLb::ChildPriority::OnFailoverTimer(void* arg, grpc_error* error) {
ChildPriority* self = static_cast<ChildPriority*>(arg);
self->priority_policy_->combiner()->Run(&self->on_failover_timer_locked_,
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // ref owned by lambda
self->priority_policy_->work_serializer()->Run(
[self, error]() { self->OnFailoverTimerLocked(error); }, DEBUG_LOCATION);
}
void PriorityLb::ChildPriority::OnFailoverTimerLocked(void* arg,
grpc_error* error) {
ChildPriority* self = static_cast<ChildPriority*>(arg);
if (error == GRPC_ERROR_NONE && self->failover_timer_callback_pending_ &&
!self->priority_policy_->shutting_down_) {
void PriorityLb::ChildPriority::OnFailoverTimerLocked(grpc_error* error) {
if (error == GRPC_ERROR_NONE && failover_timer_callback_pending_ &&
!priority_policy_->shutting_down_) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) {
gpr_log(GPR_INFO,
"[priority_lb %p] child %s (%p): failover timer fired, "
"reporting TRANSIENT_FAILURE",
self->priority_policy_.get(), self->name_.c_str(), self);
priority_policy_.get(), name_.c_str(), this);
}
self->failover_timer_callback_pending_ = false;
self->OnConnectivityStateUpdateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE,
nullptr);
failover_timer_callback_pending_ = false;
OnConnectivityStateUpdateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, nullptr);
}
self->Unref(DEBUG_LOCATION, "ChildPriority+OnFailoverTimerLocked");
Unref(DEBUG_LOCATION, "ChildPriority+OnFailoverTimerLocked");
GRPC_ERROR_UNREF(error);
}
void PriorityLb::ChildPriority::DeactivateLocked() {
@ -666,8 +665,6 @@ void PriorityLb::ChildPriority::DeactivateLocked() {
MaybeCancelFailoverTimerLocked();
// Start a timer to delete the child.
Ref(DEBUG_LOCATION, "ChildPriority+timer").release();
GRPC_CLOSURE_INIT(&on_deactivation_timer_, OnDeactivationTimer, this,
grpc_schedule_on_exec_ctx);
grpc_timer_init(&deactivation_timer_,
ExecCtx::Get()->Now() + kChildRetentionIntervalMs,
&on_deactivation_timer_);
@ -688,27 +685,26 @@ void PriorityLb::ChildPriority::MaybeReactivateLocked() {
void PriorityLb::ChildPriority::OnDeactivationTimer(void* arg,
grpc_error* error) {
ChildPriority* self = static_cast<ChildPriority*>(arg);
self->priority_policy_->combiner()->Run(
GRPC_CLOSURE_INIT(&self->on_deactivation_timer_,
OnDeactivationTimerLocked, self, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // ref owned by lambda
self->priority_policy_->work_serializer()->Run(
[self, error]() { self->OnDeactivationTimerLocked(error); },
DEBUG_LOCATION);
}
void PriorityLb::ChildPriority::OnDeactivationTimerLocked(void* arg,
grpc_error* error) {
ChildPriority* self = static_cast<ChildPriority*>(arg);
if (error == GRPC_ERROR_NONE && self->deactivation_timer_callback_pending_ &&
!self->priority_policy_->shutting_down_) {
void PriorityLb::ChildPriority::OnDeactivationTimerLocked(grpc_error* error) {
if (error == GRPC_ERROR_NONE && deactivation_timer_callback_pending_ &&
!priority_policy_->shutting_down_) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) {
gpr_log(GPR_INFO,
"[priority_lb %p] child %s (%p): deactivation timer fired, "
"deleting child",
self->priority_policy_.get(), self->name_.c_str(), self);
priority_policy_.get(), name_.c_str(), this);
}
self->deactivation_timer_callback_pending_ = false;
self->priority_policy_->DeleteChild(self);
deactivation_timer_callback_pending_ = false;
priority_policy_->DeleteChild(this);
}
self->Unref(DEBUG_LOCATION, "ChildPriority+timer");
Unref(DEBUG_LOCATION, "ChildPriority+timer");
GRPC_ERROR_UNREF(error);
}
//
@ -735,8 +731,8 @@ void PriorityLb::ChildPriority::Helper::UpdateState(
priority_->OnConnectivityStateUpdateLocked(state, std::move(picker));
}
void PriorityLb::ChildPriority::Helper::AddTraceEvent(TraceSeverity severity,
StringView message) {
void PriorityLb::ChildPriority::Helper::AddTraceEvent(
TraceSeverity severity, absl::string_view message) {
if (priority_->priority_policy_->shutting_down_) return;
priority_->priority_policy_->channel_control_helper()->AddTraceEvent(severity,
message);

@ -160,7 +160,7 @@ class RoundRobin : public LoadBalancingPolicy {
RoundRobin* parent_;
size_t last_picked_index_;
InlinedVector<RefCountedPtr<SubchannelInterface>, 10> subchannels_;
absl::InlinedVector<RefCountedPtr<SubchannelInterface>, 10> subchannels_;
};
void ShutdownLocked() override;

@ -25,6 +25,8 @@
#include <grpc/support/alloc.h>
#include "absl/container/inlined_vector.h"
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/ext/filters/client_channel/server_address.h"
// TODO(roth): Should not need the include of subchannel.h here, since
@ -33,7 +35,6 @@
#include "src/core/ext/filters/client_channel/subchannel_interface.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/inlined_vector.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"
@ -62,7 +63,7 @@ class MySubchannelList
};
*/
// All methods will be called from within the client_channel combiner.
// All methods will be called from within the client_channel work serializer.
namespace grpc_core {
@ -172,7 +173,7 @@ class SubchannelData {
template <typename SubchannelListType, typename SubchannelDataType>
class SubchannelList : public InternallyRefCounted<SubchannelListType> {
public:
typedef InlinedVector<SubchannelDataType, 10> SubchannelVector;
typedef absl::InlinedVector<SubchannelDataType, 10> SubchannelVector;
// The number of subchannels in the list.
size_t num_subchannels() const { return subchannels_.size(); }
@ -370,7 +371,7 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
GRPC_ARG_SERVICE_CONFIG};
// Create a subchannel for each address.
for (size_t i = 0; i < addresses.size(); i++) {
InlinedVector<grpc_arg, 3> args_to_add;
absl::InlinedVector<grpc_arg, 3> args_to_add;
const size_t subchannel_address_arg_index = args_to_add.size();
args_to_add.emplace_back(
Subchannel::CreateSubchannelAddressArg(&addresses[i].address()));

@ -20,6 +20,7 @@
#include <limits.h>
#include <string.h>
#include "absl/container/inlined_vector.h"
#include "absl/strings/str_cat.h"
#include <grpc/grpc.h>
@ -33,8 +34,8 @@
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
namespace grpc_core {
@ -99,9 +100,8 @@ class WeightedTargetLb : public LoadBalancingPolicy {
// ready state. The first element in the pair represents the end of a
// range proportional to the child's weight. The start of the range
// is the previous value in the vector and is 0 for the first element.
using PickerList =
InlinedVector<std::pair<uint32_t, RefCountedPtr<ChildPickerWrapper>>,
1>;
using PickerList = absl::InlinedVector<
std::pair<uint32_t, RefCountedPtr<ChildPickerWrapper>>, 1>;
explicit WeightedPicker(PickerList pickers)
: pickers_(std::move(pickers)) {}
@ -148,7 +148,8 @@ class WeightedTargetLb : public LoadBalancingPolicy {
void UpdateState(grpc_connectivity_state state,
std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity, StringView message) override;
void AddTraceEvent(TraceSeverity severity,
absl::string_view message) override;
private:
RefCountedPtr<WeightedChild> weighted_child_;
@ -163,7 +164,7 @@ class WeightedTargetLb : public LoadBalancingPolicy {
std::unique_ptr<SubchannelPicker> picker);
static void OnDelayedRemovalTimer(void* arg, grpc_error* error);
static void OnDelayedRemovalTimerLocked(void* arg, grpc_error* error);
void OnDelayedRemovalTimerLocked(grpc_error* error);
// The owning LB policy.
RefCountedPtr<WeightedTargetLb> weighted_target_policy_;
@ -392,6 +393,8 @@ WeightedTargetLb::WeightedChild::WeightedChild(
gpr_log(GPR_INFO, "[weighted_target_lb %p] created WeightedChild %p for %s",
weighted_target_policy_.get(), this, name_.c_str());
}
GRPC_CLOSURE_INIT(&on_delayed_removal_timer_, OnDelayedRemovalTimer, this,
grpc_schedule_on_exec_ctx);
}
WeightedTargetLb::WeightedChild::~WeightedChild() {
@ -430,7 +433,7 @@ OrphanablePtr<LoadBalancingPolicy>
WeightedTargetLb::WeightedChild::CreateChildPolicyLocked(
const grpc_channel_args* args) {
LoadBalancingPolicy::Args lb_policy_args;
lb_policy_args.combiner = weighted_target_policy_->combiner();
lb_policy_args.work_serializer = weighted_target_policy_->work_serializer();
lb_policy_args.args = args;
lb_policy_args.channel_control_helper =
absl::make_unique<Helper>(this->Ref(DEBUG_LOCATION, "Helper"));
@ -536,8 +539,6 @@ void WeightedTargetLb::WeightedChild::DeactivateLocked() {
weight_ = 0;
// Start a timer to delete the child.
Ref(DEBUG_LOCATION, "WeightedChild+timer").release();
GRPC_CLOSURE_INIT(&on_delayed_removal_timer_, OnDelayedRemovalTimer, this,
grpc_schedule_on_exec_ctx);
delayed_removal_timer_callback_pending_ = true;
grpc_timer_init(&delayed_removal_timer_,
ExecCtx::Get()->Now() + kChildRetentionIntervalMs,
@ -547,22 +548,21 @@ void WeightedTargetLb::WeightedChild::DeactivateLocked() {
void WeightedTargetLb::WeightedChild::OnDelayedRemovalTimer(void* arg,
grpc_error* error) {
WeightedChild* self = static_cast<WeightedChild*>(arg);
self->weighted_target_policy_->combiner()->Run(
GRPC_CLOSURE_INIT(&self->on_delayed_removal_timer_,
OnDelayedRemovalTimerLocked, self, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // ref owned by lambda
self->weighted_target_policy_->work_serializer()->Run(
[self, error]() { self->OnDelayedRemovalTimerLocked(error); },
DEBUG_LOCATION);
}
void WeightedTargetLb::WeightedChild::OnDelayedRemovalTimerLocked(
void* arg, grpc_error* error) {
WeightedChild* self = static_cast<WeightedChild*>(arg);
if (error == GRPC_ERROR_NONE &&
self->delayed_removal_timer_callback_pending_ && !self->shutdown_ &&
self->weight_ == 0) {
self->delayed_removal_timer_callback_pending_ = false;
self->weighted_target_policy_->targets_.erase(self->name_);
grpc_error* error) {
if (error == GRPC_ERROR_NONE && delayed_removal_timer_callback_pending_ &&
!shutdown_ && weight_ == 0) {
delayed_removal_timer_callback_pending_ = false;
weighted_target_policy_->targets_.erase(name_);
}
self->Unref(DEBUG_LOCATION, "WeightedChild+timer");
Unref(DEBUG_LOCATION, "WeightedChild+timer");
GRPC_ERROR_UNREF(error);
}
//
@ -590,7 +590,7 @@ void WeightedTargetLb::WeightedChild::Helper::RequestReresolution() {
}
void WeightedTargetLb::WeightedChild::Helper::AddTraceEvent(
TraceSeverity severity, StringView message) {
TraceSeverity severity, absl::string_view message) {
if (weighted_child_->weighted_target_policy_->shutting_down_) return;
weighted_child_->weighted_target_policy_->channel_control_helper()
->AddTraceEvent(severity, message);
@ -676,14 +676,15 @@ class WeightedTargetLbFactory : public LoadBalancingPolicyFactory {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:weight error:must be of type number"));
} else {
child_config->weight =
gpr_parse_nonnegative_int(it->second.string_value().c_str());
if (child_config->weight == -1) {
int weight = gpr_parse_nonnegative_int(it->second.string_value().c_str());
if (weight == -1) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:weight error:unparseable value"));
} else if (child_config->weight == 0) {
} else if (weight == 0) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:weight error:value must be greater than zero"));
} else {
child_config->weight = weight;
}
}
// Child policy.

@ -79,7 +79,8 @@ class CdsLb : public LoadBalancingPolicy {
void UpdateState(grpc_connectivity_state state,
std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity, StringView message) override;
void AddTraceEvent(TraceSeverity severity,
absl::string_view message) override;
private:
RefCountedPtr<CdsLb> parent_;
@ -168,7 +169,7 @@ void CdsLb::ClusterWatcher::OnClusterChanged(XdsApi::CdsUpdate cluster_data) {
// Create child policy if not already present.
if (parent_->child_policy_ == nullptr) {
LoadBalancingPolicy::Args args;
args.combiner = parent_->combiner();
args.work_serializer = parent_->work_serializer();
args.args = parent_->args_;
args.channel_control_helper = absl::make_unique<Helper>(parent_->Ref());
parent_->child_policy_ =
@ -239,7 +240,8 @@ void CdsLb::Helper::RequestReresolution() {
parent_->channel_control_helper()->RequestReresolution();
}
void CdsLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
void CdsLb::Helper::AddTraceEvent(TraceSeverity severity,
absl::string_view message) {
if (parent_->shutting_down_) return;
parent_->channel_control_helper()->AddTraceEvent(severity, message);
}
@ -279,8 +281,7 @@ void CdsLb::ShutdownLocked() {
gpr_log(GPR_INFO, "[cdslb %p] cancelling watch for cluster %s", this,
config_->cluster().c_str());
}
xds_client_->CancelClusterDataWatch(
StringView(config_->cluster().c_str()), cluster_watcher_);
xds_client_->CancelClusterDataWatch(config_->cluster(), cluster_watcher_);
}
xds_client_.reset();
}
@ -309,9 +310,9 @@ void CdsLb::UpdateLocked(UpdateArgs args) {
gpr_log(GPR_INFO, "[cdslb %p] cancelling watch for cluster %s", this,
old_config->cluster().c_str());
}
xds_client_->CancelClusterDataWatch(
StringView(old_config->cluster().c_str()), cluster_watcher_,
/*delay_unsubscription=*/true);
xds_client_->CancelClusterDataWatch(old_config->cluster(),
cluster_watcher_,
/*delay_unsubscription=*/true);
}
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
gpr_log(GPR_INFO, "[cdslb %p] starting watch for cluster %s", this,
@ -319,8 +320,7 @@ void CdsLb::UpdateLocked(UpdateArgs args) {
}
auto watcher = absl::make_unique<ClusterWatcher>(Ref());
cluster_watcher_ = watcher.get();
xds_client_->WatchClusterData(StringView(config_->cluster().c_str()),
std::move(watcher));
xds_client_->WatchClusterData(config_->cluster(), std::move(watcher));
}
}

@ -37,8 +37,8 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
#include "src/core/lib/uri/uri_parser.h"
#define GRPC_EDS_DEFAULT_FALLBACK_TIMEOUT 10000
@ -137,7 +137,8 @@ class EdsLb : public LoadBalancingPolicy {
// This is a no-op, because we get the addresses from the xds
// client, which is a watch-based API.
void RequestReresolution() override {}
void AddTraceEvent(TraceSeverity severity, StringView message) override;
void AddTraceEvent(TraceSeverity severity,
absl::string_view message) override;
private:
RefCountedPtr<EdsLb> eds_policy_;
@ -158,7 +159,7 @@ class EdsLb : public LoadBalancingPolicy {
void MaybeUpdateDropPickerLocked();
// Caller must ensure that config_ is set before calling.
const StringView GetEdsResourceName() const {
const absl::string_view GetEdsResourceName() const {
if (xds_client_from_channel_ == nullptr) return server_name_;
if (!config_->eds_service_name().empty()) {
return config_->eds_service_name();
@ -169,7 +170,7 @@ class EdsLb : public LoadBalancingPolicy {
// Returns a pair containing the cluster and eds_service_name to use
// for LRS load reporting.
// Caller must ensure that config_ is set before calling.
std::pair<StringView, StringView> GetLrsClusterKey() const {
std::pair<absl::string_view, absl::string_view> GetLrsClusterKey() const {
if (xds_client_from_channel_ == nullptr) return {server_name_, nullptr};
return {config_->cluster_name(), config_->eds_service_name()};
}
@ -275,7 +276,8 @@ void EdsLb::Helper::UpdateState(grpc_connectivity_state state,
eds_policy_->MaybeUpdateDropPickerLocked();
}
void EdsLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
void EdsLb::Helper::AddTraceEvent(TraceSeverity severity,
absl::string_view message) {
if (eds_policy_->shutting_down_) return;
eds_policy_->channel_control_helper()->AddTraceEvent(severity, message);
}
@ -424,7 +426,7 @@ void EdsLb::UpdateLocked(UpdateArgs args) {
if (xds_client_from_channel_ == nullptr) {
grpc_error* error = GRPC_ERROR_NONE;
xds_client_ = MakeOrphanable<XdsClient>(
combiner(), interested_parties(), GetEdsResourceName(),
work_serializer(), interested_parties(), GetEdsResourceName(),
nullptr /* service config watcher */, *args_, &error);
// TODO(roth): If we decide that we care about EDS-only mode, add
// proper error handling here.
@ -711,7 +713,7 @@ grpc_channel_args* EdsLb::CreateChildPolicyArgsLocked(
OrphanablePtr<LoadBalancingPolicy> EdsLb::CreateChildPolicyLocked(
const grpc_channel_args* args) {
LoadBalancingPolicy::Args lb_policy_args;
lb_policy_args.combiner = combiner();
lb_policy_args.work_serializer = work_serializer();
lb_policy_args.args = args;
lb_policy_args.channel_control_helper =
absl::make_unique<Helper>(Ref(DEBUG_LOCATION, "Helper"));

@ -27,7 +27,7 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/work_serializer.h"
namespace grpc_core {
@ -123,7 +123,8 @@ class LrsLb : public LoadBalancingPolicy {
void UpdateState(grpc_connectivity_state state,
std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity, StringView message) override;
void AddTraceEvent(TraceSeverity severity,
absl::string_view message) override;
private:
RefCountedPtr<LrsLb> lrs_policy_;
@ -176,7 +177,7 @@ LoadBalancingPolicy::PickResult LrsLb::LoadReportingPicker::Pick(
locality_stats_->Ref(DEBUG_LOCATION, "LocalityStats+call").release();
result.recv_trailing_metadata_ready =
// Note: This callback does not run in either the control plane
// combiner or in the data plane mutex.
// work serializer or in the data plane mutex.
[locality_stats](grpc_error* error, MetadataInterface* /*metadata*/,
CallState* /*call_state*/) {
const bool call_failed = error != GRPC_ERROR_NONE;
@ -273,7 +274,7 @@ void LrsLb::MaybeUpdatePickerLocked() {
OrphanablePtr<LoadBalancingPolicy> LrsLb::CreateChildPolicyLocked(
const grpc_channel_args* args) {
LoadBalancingPolicy::Args lb_policy_args;
lb_policy_args.combiner = combiner();
lb_policy_args.work_serializer = work_serializer();
lb_policy_args.args = args;
lb_policy_args.channel_control_helper =
absl::make_unique<Helper>(Ref(DEBUG_LOCATION, "Helper"));
@ -341,7 +342,8 @@ void LrsLb::Helper::RequestReresolution() {
lrs_policy_->channel_control_helper()->RequestReresolution();
}
void LrsLb::Helper::AddTraceEvent(TraceSeverity severity, StringView message) {
void LrsLb::Helper::AddTraceEvent(TraceSeverity severity,
absl::string_view message) {
if (lrs_policy_->shutting_down_) return;
lrs_policy_->channel_control_helper()->AddTraceEvent(severity, message);
}

@ -0,0 +1,834 @@
//
// Copyright 2018 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 <inttypes.h>
#include <limits.h>
#include <string.h>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include <grpc/grpc.h>
#include "src/core/ext/filters/client_channel/lb_policy.h"
#include "src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h"
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
#define GRPC_XDS_ROUTING_CHILD_RETENTION_INTERVAL_MS (15 * 60 * 1000)
namespace grpc_core {
TraceFlag grpc_xds_routing_lb_trace(false, "xds_routing_lb");
namespace {
constexpr char kXdsRouting[] = "xds_routing_experimental";
// Config for xds_routing LB policy.
class XdsRoutingLbConfig : public LoadBalancingPolicy::Config {
public:
struct Matcher {
std::string service;
std::string method;
};
struct Route {
Matcher matcher;
std::string action;
};
using RouteTable = std::vector<Route>;
using ActionMap =
std::map<std::string, RefCountedPtr<LoadBalancingPolicy::Config>>;
XdsRoutingLbConfig(ActionMap action_map, RouteTable route_table)
: action_map_(std::move(action_map)),
route_table_(std::move(route_table)) {}
const char* name() const override { return kXdsRouting; }
const ActionMap& action_map() const { return action_map_; }
const RouteTable& route_table() const { return route_table_; }
private:
ActionMap action_map_;
RouteTable route_table_;
};
// xds_routing LB policy.
class XdsRoutingLb : public LoadBalancingPolicy {
public:
explicit XdsRoutingLb(Args args);
const char* name() const override { return kXdsRouting; }
void UpdateLocked(UpdateArgs args) override;
void ExitIdleLocked() override;
void ResetBackoffLocked() override;
private:
// A simple wrapper for ref-counting a picker from the child policy.
class ChildPickerWrapper : public RefCounted<ChildPickerWrapper> {
public:
ChildPickerWrapper(std::string name,
std::unique_ptr<SubchannelPicker> picker)
: name_(std::move(name)), picker_(std::move(picker)) {}
PickResult Pick(PickArgs args) { return picker_->Pick(args); }
const std::string& name() const { return name_; }
private:
std::string name_;
std::unique_ptr<SubchannelPicker> picker_;
};
// Picks a child using prefix or path matching and then delegates to that
// child's picker.
class RoutePicker : public SubchannelPicker {
public:
struct Route {
XdsRoutingLbConfig::Matcher matcher;
RefCountedPtr<ChildPickerWrapper> picker;
};
// Maintains an ordered xds route table as provided by RDS response.
using RouteTable = std::vector<Route>;
explicit RoutePicker(RouteTable route_table)
: route_table_(std::move(route_table)) {}
PickResult Pick(PickArgs args) override;
private:
RouteTable route_table_;
};
// Each XdsRoutingChild holds a ref to its parent XdsRoutingLb.
class XdsRoutingChild : public InternallyRefCounted<XdsRoutingChild> {
public:
XdsRoutingChild(RefCountedPtr<XdsRoutingLb> xds_routing_policy,
const std::string& name);
~XdsRoutingChild();
void Orphan() override;
void UpdateLocked(RefCountedPtr<LoadBalancingPolicy::Config> config,
const ServerAddressList& addresses,
const grpc_channel_args* args);
void ExitIdleLocked();
void ResetBackoffLocked();
void DeactivateLocked();
grpc_connectivity_state connectivity_state() const {
return connectivity_state_;
}
RefCountedPtr<ChildPickerWrapper> picker_wrapper() const {
return picker_wrapper_;
}
private:
class Helper : public ChannelControlHelper {
public:
explicit Helper(RefCountedPtr<XdsRoutingChild> xds_routing_child)
: xds_routing_child_(std::move(xds_routing_child)) {}
~Helper() { xds_routing_child_.reset(DEBUG_LOCATION, "Helper"); }
RefCountedPtr<SubchannelInterface> CreateSubchannel(
const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state,
std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
absl::string_view message) override;
private:
RefCountedPtr<XdsRoutingChild> xds_routing_child_;
};
// Methods for dealing with the child policy.
OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked(
const grpc_channel_args* args);
static void OnDelayedRemovalTimer(void* arg, grpc_error* error);
void OnDelayedRemovalTimerLocked(grpc_error* error);
// The owning LB policy.
RefCountedPtr<XdsRoutingLb> xds_routing_policy_;
// Points to the corresponding key in XdsRoutingLb::actions_.
const std::string& name_;
OrphanablePtr<LoadBalancingPolicy> child_policy_;
RefCountedPtr<ChildPickerWrapper> picker_wrapper_;
grpc_connectivity_state connectivity_state_ = GRPC_CHANNEL_IDLE;
bool seen_failure_since_ready_ = false;
// States for delayed removal.
grpc_timer delayed_removal_timer_;
grpc_closure on_delayed_removal_timer_;
bool delayed_removal_timer_callback_pending_ = false;
bool shutdown_ = false;
};
~XdsRoutingLb();
void ShutdownLocked() override;
void UpdateStateLocked();
// Current config from the resolver.
RefCountedPtr<XdsRoutingLbConfig> config_;
// Internal state.
bool shutting_down_ = false;
// Children.
std::map<std::string, OrphanablePtr<XdsRoutingChild>> actions_;
};
//
// XdsRoutingLb::RoutePicker
//
XdsRoutingLb::PickResult XdsRoutingLb::RoutePicker::Pick(PickArgs args) {
absl::string_view path;
// TODO(roth): Using const auto& here trigger a warning in a macos or windows
// build:
//*(args.initial_metadata) is returning values not references.
for (const auto p : *(args.initial_metadata)) {
if (p.first == ":path") {
path = p.second;
break;
}
}
std::vector<absl::string_view> path_elements =
absl::StrSplit(path.substr(1), '/');
for (const Route& route : route_table_) {
if ((path_elements[0] == route.matcher.service &&
(path_elements[1] == route.matcher.method ||
route.matcher.method.empty())) ||
(route.matcher.service.empty() && route.matcher.method.empty())) {
return route.picker->Pick(args);
}
}
PickResult result;
result.type = PickResult::PICK_FAILED;
result.error =
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"xds routing picker: no matching route"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL);
return result;
}
//
// XdsRoutingLb
//
XdsRoutingLb::XdsRoutingLb(Args args) : LoadBalancingPolicy(std::move(args)) {}
XdsRoutingLb::~XdsRoutingLb() {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO, "[xds_routing_lb %p] destroying xds_routing LB policy",
this);
}
}
void XdsRoutingLb::ShutdownLocked() {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO, "[xds_routing_lb %p] shutting down", this);
}
shutting_down_ = true;
actions_.clear();
}
void XdsRoutingLb::ExitIdleLocked() {
for (auto& p : actions_) p.second->ExitIdleLocked();
}
void XdsRoutingLb::ResetBackoffLocked() {
for (auto& p : actions_) p.second->ResetBackoffLocked();
}
void XdsRoutingLb::UpdateLocked(UpdateArgs args) {
if (shutting_down_) return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO, "[xds_routing_lb %p] Received update", this);
}
// Update config.
config_ = std::move(args.config);
// Deactivate the actions not in the new config.
for (const auto& p : actions_) {
const std::string& name = p.first;
XdsRoutingChild* child = p.second.get();
if (config_->action_map().find(name) == config_->action_map().end()) {
child->DeactivateLocked();
}
}
// Add or update the actions in the new config.
for (const auto& p : config_->action_map()) {
const std::string& name = p.first;
const RefCountedPtr<LoadBalancingPolicy::Config>& config = p.second;
auto it = actions_.find(name);
if (it == actions_.end()) {
it = actions_.emplace(std::make_pair(name, nullptr)).first;
it->second = MakeOrphanable<XdsRoutingChild>(
Ref(DEBUG_LOCATION, "XdsRoutingChild"), it->first);
}
it->second->UpdateLocked(config, args.addresses, args.args);
}
}
void XdsRoutingLb::UpdateStateLocked() {
// Also count the number of children in each state, to determine the
// overall state.
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 : actions_) {
const auto& child_name = p.first;
const XdsRoutingChild* child = p.second.get();
// Skip the actions that are not in the latest update.
if (config_->action_map().find(child_name) == config_->action_map().end()) {
continue;
}
switch (child->connectivity_state()) {
case GRPC_CHANNEL_READY: {
++num_ready;
break;
}
case GRPC_CHANNEL_CONNECTING: {
++num_connecting;
break;
}
case GRPC_CHANNEL_IDLE: {
++num_idle;
break;
}
case GRPC_CHANNEL_TRANSIENT_FAILURE: {
++num_transient_failures;
break;
}
default:
GPR_UNREACHABLE_CODE(return );
}
}
// Determine aggregated connectivity state.
grpc_connectivity_state connectivity_state;
if (num_ready > 0) {
connectivity_state = GRPC_CHANNEL_READY;
} else if (num_connecting > 0) {
connectivity_state = GRPC_CHANNEL_CONNECTING;
} else if (num_idle > 0) {
connectivity_state = GRPC_CHANNEL_IDLE;
} else {
connectivity_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
}
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO, "[xds_routing_lb %p] connectivity changed to %s", this,
ConnectivityStateName(connectivity_state));
}
std::unique_ptr<SubchannelPicker> picker;
switch (connectivity_state) {
case GRPC_CHANNEL_READY: {
RoutePicker::RouteTable route_table;
for (const auto& config_route : config_->route_table()) {
RoutePicker::Route route;
route.matcher = config_route.matcher;
route.picker = actions_[config_route.action]->picker_wrapper();
if (route.picker == nullptr) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO,
"[xds_routing_lb %p] child %s has not yet returned a "
"picker; creating a QueuePicker.",
this, config_route.action.c_str());
}
route.picker = MakeRefCounted<ChildPickerWrapper>(
config_route.action, absl::make_unique<QueuePicker>(
Ref(DEBUG_LOCATION, "QueuePicker")));
}
route_table.push_back(std::move(route));
}
picker = absl::make_unique<RoutePicker>(std::move(route_table));
break;
}
case GRPC_CHANNEL_CONNECTING:
case GRPC_CHANNEL_IDLE:
picker =
absl::make_unique<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker"));
break;
default:
picker = absl::make_unique<TransientFailurePicker>(grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"TRANSIENT_FAILURE from XdsRoutingLb"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
}
channel_control_helper()->UpdateState(connectivity_state, std::move(picker));
}
//
// XdsRoutingLb::XdsRoutingChild
//
XdsRoutingLb::XdsRoutingChild::XdsRoutingChild(
RefCountedPtr<XdsRoutingLb> xds_routing_policy, const std::string& name)
: xds_routing_policy_(std::move(xds_routing_policy)), name_(name) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO, "[xds_routing_lb %p] created XdsRoutingChild %p for %s",
xds_routing_policy_.get(), this, name_.c_str());
}
GRPC_CLOSURE_INIT(&on_delayed_removal_timer_, OnDelayedRemovalTimer, this,
grpc_schedule_on_exec_ctx);
}
XdsRoutingLb::XdsRoutingChild::~XdsRoutingChild() {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO,
"[xds_routing_lb %p] XdsRoutingChild %p: destroying child",
xds_routing_policy_.get(), this);
}
xds_routing_policy_.reset(DEBUG_LOCATION, "XdsRoutingChild");
}
void XdsRoutingLb::XdsRoutingChild::Orphan() {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO,
"[xds_routing_lb %p] XdsRoutingChild %p %s: shutting down child",
xds_routing_policy_.get(), this, name_.c_str());
}
// Remove the child policy's interested_parties pollset_set from the
// xDS policy.
grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(),
xds_routing_policy_->interested_parties());
child_policy_.reset();
// Drop our ref to the child's picker, in case it's holding a ref to
// the child.
picker_wrapper_.reset();
if (delayed_removal_timer_callback_pending_) {
grpc_timer_cancel(&delayed_removal_timer_);
}
shutdown_ = true;
Unref();
}
OrphanablePtr<LoadBalancingPolicy>
XdsRoutingLb::XdsRoutingChild::CreateChildPolicyLocked(
const grpc_channel_args* args) {
LoadBalancingPolicy::Args lb_policy_args;
lb_policy_args.work_serializer = xds_routing_policy_->work_serializer();
lb_policy_args.args = args;
lb_policy_args.channel_control_helper =
absl::make_unique<Helper>(this->Ref(DEBUG_LOCATION, "Helper"));
OrphanablePtr<LoadBalancingPolicy> lb_policy =
MakeOrphanable<ChildPolicyHandler>(std::move(lb_policy_args),
&grpc_xds_routing_lb_trace);
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO,
"[xds_routing_lb %p] XdsRoutingChild %p %s: Created new child "
"policy handler %p",
xds_routing_policy_.get(), this, name_.c_str(), lb_policy.get());
}
// Add the xDS's interested_parties pollset_set to that of the newly created
// child policy. This will make the child policy progress upon activity on
// xDS LB, which in turn is tied to the application's call.
grpc_pollset_set_add_pollset_set(lb_policy->interested_parties(),
xds_routing_policy_->interested_parties());
return lb_policy;
}
void XdsRoutingLb::XdsRoutingChild::UpdateLocked(
RefCountedPtr<LoadBalancingPolicy::Config> config,
const ServerAddressList& addresses, const grpc_channel_args* args) {
if (xds_routing_policy_->shutting_down_) return;
// Update child weight.
// Reactivate if needed.
if (delayed_removal_timer_callback_pending_) {
delayed_removal_timer_callback_pending_ = false;
grpc_timer_cancel(&delayed_removal_timer_);
}
// Create child policy if needed.
if (child_policy_ == nullptr) {
child_policy_ = CreateChildPolicyLocked(args);
}
// Construct update args.
UpdateArgs update_args;
update_args.config = std::move(config);
update_args.addresses = addresses;
update_args.args = grpc_channel_args_copy(args);
// Update the policy.
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO,
"[xds_routing_lb %p] XdsRoutingChild %p %s: Updating child "
"policy handler %p",
xds_routing_policy_.get(), this, name_.c_str(),
child_policy_.get());
}
child_policy_->UpdateLocked(std::move(update_args));
}
void XdsRoutingLb::XdsRoutingChild::ExitIdleLocked() {
child_policy_->ExitIdleLocked();
}
void XdsRoutingLb::XdsRoutingChild::ResetBackoffLocked() {
child_policy_->ResetBackoffLocked();
}
void XdsRoutingLb::XdsRoutingChild::DeactivateLocked() {
// If already deactivated, don't do that again.
if (delayed_removal_timer_callback_pending_ == true) return;
// Set the child weight to 0 so that future picker won't contain this child.
// Start a timer to delete the child.
Ref(DEBUG_LOCATION, "XdsRoutingChild+timer").release();
grpc_timer_init(
&delayed_removal_timer_,
ExecCtx::Get()->Now() + GRPC_XDS_ROUTING_CHILD_RETENTION_INTERVAL_MS,
&on_delayed_removal_timer_);
delayed_removal_timer_callback_pending_ = true;
}
void XdsRoutingLb::XdsRoutingChild::OnDelayedRemovalTimer(void* arg,
grpc_error* error) {
XdsRoutingChild* self = static_cast<XdsRoutingChild*>(arg);
GRPC_ERROR_REF(error); // Ref owned by the lambda
self->xds_routing_policy_->work_serializer()->Run(
[self, error]() { self->OnDelayedRemovalTimerLocked(error); },
DEBUG_LOCATION);
}
void XdsRoutingLb::XdsRoutingChild::OnDelayedRemovalTimerLocked(
grpc_error* error) {
delayed_removal_timer_callback_pending_ = false;
if (error == GRPC_ERROR_NONE && !shutdown_) {
xds_routing_policy_->actions_.erase(name_);
}
Unref(DEBUG_LOCATION, "XdsRoutingChild+timer");
GRPC_ERROR_UNREF(error);
}
//
// XdsRoutingLb::XdsRoutingChild::Helper
//
RefCountedPtr<SubchannelInterface>
XdsRoutingLb::XdsRoutingChild::Helper::CreateSubchannel(
const grpc_channel_args& args) {
if (xds_routing_child_->xds_routing_policy_->shutting_down_) return nullptr;
return xds_routing_child_->xds_routing_policy_->channel_control_helper()
->CreateSubchannel(args);
}
void XdsRoutingLb::XdsRoutingChild::Helper::UpdateState(
grpc_connectivity_state state, std::unique_ptr<SubchannelPicker> picker) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO,
"[xds_routing_lb %p] child %s: received update: state=%s picker=%p",
xds_routing_child_->xds_routing_policy_.get(),
xds_routing_child_->name_.c_str(), ConnectivityStateName(state),
picker.get());
}
if (xds_routing_child_->xds_routing_policy_->shutting_down_) return;
// Cache the picker in the XdsRoutingChild.
xds_routing_child_->picker_wrapper_ = MakeRefCounted<ChildPickerWrapper>(
xds_routing_child_->name_, std::move(picker));
// Decide what state to report for aggregation purposes.
// If we haven't seen a failure since the last time we were in state
// READY, then we report the state change as-is. However, once we do see
// a failure, we report TRANSIENT_FAILURE and ignore any subsequent state
// changes until we go back into state READY.
if (!xds_routing_child_->seen_failure_since_ready_) {
if (state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
xds_routing_child_->seen_failure_since_ready_ = true;
}
} else {
if (state != GRPC_CHANNEL_READY) return;
xds_routing_child_->seen_failure_since_ready_ = false;
}
xds_routing_child_->connectivity_state_ = state;
// Notify the LB policy.
xds_routing_child_->xds_routing_policy_->UpdateStateLocked();
}
void XdsRoutingLb::XdsRoutingChild::Helper::RequestReresolution() {
if (xds_routing_child_->xds_routing_policy_->shutting_down_) return;
xds_routing_child_->xds_routing_policy_->channel_control_helper()
->RequestReresolution();
}
void XdsRoutingLb::XdsRoutingChild::Helper::AddTraceEvent(
TraceSeverity severity, absl::string_view message) {
if (xds_routing_child_->xds_routing_policy_->shutting_down_) return;
xds_routing_child_->xds_routing_policy_->channel_control_helper()
->AddTraceEvent(severity, message);
}
//
// factory
//
class XdsRoutingLbFactory : public LoadBalancingPolicyFactory {
public:
OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
LoadBalancingPolicy::Args args) const override {
return MakeOrphanable<XdsRoutingLb>(std::move(args));
}
const char* name() const override { return kXdsRouting; }
RefCountedPtr<LoadBalancingPolicy::Config> ParseLoadBalancingConfig(
const Json& json, grpc_error** error) const override {
GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
if (json.type() == Json::Type::JSON_NULL) {
// xds_routing was mentioned as a policy in the deprecated
// loadBalancingPolicy field or in the client API.
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:loadBalancingPolicy error:xds_routing policy requires "
"configuration. Please use loadBalancingConfig field of service "
"config instead.");
return nullptr;
}
std::vector<grpc_error*> error_list;
// action map.
XdsRoutingLbConfig::ActionMap action_map;
std::set<std::string /*action_name*/> actions_to_be_used;
auto it = json.object_value().find("actions");
if (it == json.object_value().end()) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:actions error:required field not present"));
} else if (it->second.type() != Json::Type::OBJECT) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:actions error:type should be object"));
} else {
for (const auto& p : it->second.object_value()) {
if (p.first.empty()) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:actions element error: name cannot be empty"));
continue;
}
RefCountedPtr<LoadBalancingPolicy::Config> child_config;
std::vector<grpc_error*> child_errors =
ParseChildConfig(p.second, &child_config);
if (!child_errors.empty()) {
// Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
// string is not static in this case.
grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("field:actions name:", p.first).c_str());
for (grpc_error* child_error : child_errors) {
error = grpc_error_add_child(error, child_error);
}
error_list.push_back(error);
} else {
action_map[p.first] = std::move(child_config);
actions_to_be_used.insert(p.first);
}
}
}
if (action_map.empty()) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("no valid actions configured"));
}
XdsRoutingLbConfig::RouteTable route_table;
it = json.object_value().find("routes");
if (it == json.object_value().end()) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:routes error:required field not present"));
} else if (it->second.type() != Json::Type::ARRAY) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:routes error:type should be array"));
} else {
const Json::Array& array = it->second.array_value();
for (size_t i = 0; i < array.size(); ++i) {
XdsRoutingLbConfig::Route route;
std::vector<grpc_error*> route_errors =
ParseRoute(array[i], action_map, &route, &actions_to_be_used);
if (!route_errors.empty()) {
// Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
// string is not static in this case.
grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("field:routes element: ", i, " error").c_str());
for (grpc_error* route_error : route_errors) {
error = grpc_error_add_child(error, route_error);
}
error_list.push_back(error);
}
route_table.emplace_back(std::move(route));
}
}
if (route_table.empty()) {
grpc_error* error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("no valid routes configured");
error_list.push_back(error);
}
if (!route_table.back().matcher.service.empty() ||
!route_table.back().matcher.method.empty()) {
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"default route must not contain service or method");
error_list.push_back(error);
}
if (!actions_to_be_used.empty()) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"some actions were not referenced by any route"));
}
if (!error_list.empty()) {
*error = GRPC_ERROR_CREATE_FROM_VECTOR(
"xds_routing_experimental LB policy config", &error_list);
return nullptr;
}
return MakeRefCounted<XdsRoutingLbConfig>(std::move(action_map),
std::move(route_table));
}
private:
static std::vector<grpc_error*> ParseChildConfig(
const Json& json,
RefCountedPtr<LoadBalancingPolicy::Config>* child_config) {
std::vector<grpc_error*> error_list;
if (json.type() != Json::Type::OBJECT) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"value should be of type object"));
return error_list;
}
auto it = json.object_value().find("child_policy");
if (it == json.object_value().end()) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("did not find childPolicy"));
} else {
grpc_error* parse_error = GRPC_ERROR_NONE;
*child_config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
it->second, &parse_error);
if (*child_config == nullptr) {
GPR_DEBUG_ASSERT(parse_error != GRPC_ERROR_NONE);
std::vector<grpc_error*> child_errors;
child_errors.push_back(parse_error);
error_list.push_back(
GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors));
}
}
return error_list;
}
static std::vector<grpc_error*> ParseMethodName(
const Json& json, XdsRoutingLbConfig::Matcher* route_config) {
std::vector<grpc_error*> error_list;
if (json.type() != Json::Type::OBJECT) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"value should be of type object"));
return error_list;
}
// Parse service
auto it = json.object_value().find("service");
if (it != json.object_value().end()) {
if (it->second.type() != Json::Type::STRING) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:service error: should be string"));
} else {
route_config->service = it->second.string_value();
}
}
// Parse method
it = json.object_value().find("method");
if (it != json.object_value().end()) {
if (it->second.type() != Json::Type::STRING) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:method error: should be string"));
} else {
route_config->method = it->second.string_value();
}
}
if (route_config->service.empty() && !route_config->method.empty()) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"service is empty when method is not"));
}
return error_list;
}
static std::vector<grpc_error*> ParseRoute(
const Json& json, const XdsRoutingLbConfig::ActionMap& action_map,
XdsRoutingLbConfig::Route* route,
std::set<std::string /*action_name*/>* actions_to_be_used) {
std::vector<grpc_error*> error_list;
if (json.type() != Json::Type::OBJECT) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"value should be of type object"));
return error_list;
}
// Parse MethodName.
auto it = json.object_value().find("methodName");
if (it == json.object_value().end()) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:methodName error:required field missing"));
} else {
std::vector<grpc_error*> method_name_errors =
ParseMethodName(it->second, &route->matcher);
if (!method_name_errors.empty()) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_VECTOR(
"field:methodName", &method_name_errors));
}
}
// Parse action.
it = json.object_value().find("action");
if (it == json.object_value().end()) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:action error:required field missing"));
} else if (it->second.type() != Json::Type::STRING) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:action error:should be of type string"));
} else {
route->action = it->second.string_value();
if (route->action.empty()) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"field:action error:cannot be empty"));
} else {
// Validate action exists and mark it as used.
if (action_map.find(route->action) == action_map.end()) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
absl::StrCat("field:action error:", route->action,
" does not exist")
.c_str()));
}
actions_to_be_used->erase(route->action);
}
}
return error_list;
}
};
} // namespace
} // namespace grpc_core
//
// Plugin registration
//
void grpc_lb_policy_xds_routing_init() {
grpc_core::LoadBalancingPolicyRegistry::Builder::
RegisterLoadBalancingPolicyFactory(
absl::make_unique<grpc_core::XdsRoutingLbFactory>());
}
void grpc_lb_policy_xds_routing_shutdown() {}

@ -22,8 +22,9 @@
#include <string.h>
#include "absl/container/inlined_vector.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/inlined_vector.h"
namespace grpc_core {
@ -54,7 +55,8 @@ class RegistryState {
}
private:
InlinedVector<std::unique_ptr<LoadBalancingPolicyFactory>, 10> factories_;
absl::InlinedVector<std::unique_ptr<LoadBalancingPolicyFactory>, 10>
factories_;
};
RegistryState* g_state = nullptr;

@ -38,7 +38,8 @@ class LocalSubchannelPool final : public SubchannelPoolInterface {
~LocalSubchannelPool() override;
// Implements interface methods.
// Thread-unsafe. Intended to be invoked within the client_channel combiner.
// Thread-unsafe. Intended to be invoked within the client_channel work
// serializer.
Subchannel* RegisterSubchannel(SubchannelKey* key,
Subchannel* constructed) override;
void UnregisterSubchannel(SubchannelKey* key) override;

@ -73,8 +73,8 @@ bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr,
bool log_errors) {
bool success = false;
// Split host and port.
grpc_core::UniquePtr<char> host;
grpc_core::UniquePtr<char> port;
std::string host;
std::string port;
if (!grpc_core::SplitHostPort(hostport, &host, &port)) {
if (log_errors) {
gpr_log(GPR_ERROR, "Failed gpr_split_host_port(%s, ...)", hostport);
@ -86,21 +86,21 @@ bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr,
addr->len = static_cast<socklen_t>(sizeof(grpc_sockaddr_in));
grpc_sockaddr_in* in = reinterpret_cast<grpc_sockaddr_in*>(addr->addr);
in->sin_family = GRPC_AF_INET;
if (grpc_inet_pton(GRPC_AF_INET, host.get(), &in->sin_addr) == 0) {
if (grpc_inet_pton(GRPC_AF_INET, host.c_str(), &in->sin_addr) == 0) {
if (log_errors) {
gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host.get());
gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host.c_str());
}
goto done;
}
// Parse port.
if (port == nullptr) {
if (port.empty()) {
if (log_errors) gpr_log(GPR_ERROR, "no port given for ipv4 scheme");
goto done;
}
int port_num;
if (sscanf(port.get(), "%d", &port_num) != 1 || port_num < 0 ||
if (sscanf(port.c_str(), "%d", &port_num) != 1 || port_num < 0 ||
port_num > 65535) {
if (log_errors) gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port.get());
if (log_errors) gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port.c_str());
goto done;
}
in->sin_port = grpc_htons(static_cast<uint16_t>(port_num));
@ -125,8 +125,8 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
bool log_errors) {
bool success = false;
// Split host and port.
grpc_core::UniquePtr<char> host;
grpc_core::UniquePtr<char> port;
std::string host;
std::string port;
if (!grpc_core::SplitHostPort(hostport, &host, &port)) {
if (log_errors) {
gpr_log(GPR_ERROR, "Failed gpr_split_host_port(%s, ...)", hostport);
@ -140,11 +140,12 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
in6->sin6_family = GRPC_AF_INET6;
// Handle the RFC6874 syntax for IPv6 zone identifiers.
char* host_end =
static_cast<char*>(gpr_memrchr(host.get(), '%', strlen(host.get())));
static_cast<char*>(gpr_memrchr(host.c_str(), '%', host.size()));
if (host_end != nullptr) {
GPR_ASSERT(host_end >= host.get());
GPR_ASSERT(host_end >= host.c_str());
char host_without_scope[GRPC_INET6_ADDRSTRLEN + 1];
size_t host_without_scope_len = static_cast<size_t>(host_end - host.get());
size_t host_without_scope_len =
static_cast<size_t>(host_end - host.c_str());
uint32_t sin6_scope_id = 0;
if (host_without_scope_len > GRPC_INET6_ADDRSTRLEN) {
if (log_errors) {
@ -156,7 +157,7 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
}
goto done;
}
strncpy(host_without_scope, host.get(), host_without_scope_len);
strncpy(host_without_scope, host.c_str(), host_without_scope_len);
host_without_scope[host_without_scope_len] = '\0';
if (grpc_inet_pton(GRPC_AF_INET6, host_without_scope, &in6->sin6_addr) ==
0) {
@ -165,9 +166,9 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
}
goto done;
}
if (gpr_parse_bytes_to_uint32(
host_end + 1, strlen(host.get()) - host_without_scope_len - 1,
&sin6_scope_id) == 0) {
if (gpr_parse_bytes_to_uint32(host_end + 1,
host.size() - host_without_scope_len - 1,
&sin6_scope_id) == 0) {
if ((sin6_scope_id = grpc_if_nametoindex(host_end + 1)) == 0) {
gpr_log(GPR_ERROR,
"Invalid interface name: '%s'. "
@ -179,22 +180,22 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr,
// Handle "sin6_scope_id" being type "u_long". See grpc issue #10027.
in6->sin6_scope_id = sin6_scope_id;
} else {
if (grpc_inet_pton(GRPC_AF_INET6, host.get(), &in6->sin6_addr) == 0) {
if (grpc_inet_pton(GRPC_AF_INET6, host.c_str(), &in6->sin6_addr) == 0) {
if (log_errors) {
gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host.get());
gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host.c_str());
}
goto done;
}
}
// Parse port.
if (port == nullptr) {
if (port.empty()) {
if (log_errors) gpr_log(GPR_ERROR, "no port given for ipv6 scheme");
goto done;
}
int port_num;
if (sscanf(port.get(), "%d", &port_num) != 1 || port_num < 0 ||
if (sscanf(port.c_str(), "%d", &port_num) != 1 || port_num < 0 ||
port_num > 65535) {
if (log_errors) gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port.get());
if (log_errors) gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port.c_str());
goto done;
}
in6->sin6_port = grpc_htons(static_cast<uint16_t>(port_num));

@ -19,7 +19,6 @@
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/resolver.h"
#include "src/core/lib/iomgr/combiner.h"
grpc_core::DebugOnlyTraceFlag grpc_trace_resolver_refcount(false,
"resolver_refcount");
@ -30,13 +29,11 @@ namespace grpc_core {
// Resolver
//
Resolver::Resolver(Combiner* combiner,
Resolver::Resolver(std::shared_ptr<WorkSerializer> work_serializer,
std::unique_ptr<ResultHandler> result_handler)
: InternallyRefCounted(&grpc_trace_resolver_refcount),
result_handler_(std::move(result_handler)),
combiner_(GRPC_COMBINER_REF(combiner, "resolver")) {}
Resolver::~Resolver() { GRPC_COMBINER_UNREF(combiner_, "resolver"); }
work_serializer_(std::move(work_serializer)),
result_handler_(std::move(result_handler)) {}
//
// Resolver::Result

@ -27,8 +27,8 @@
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/work_serializer.h"
extern grpc_core::DebugOnlyTraceFlag grpc_trace_resolver_refcount;
@ -45,7 +45,7 @@ namespace grpc_core {
/// DNS).
///
/// Note: All methods with a "Locked" suffix must be called from the
/// combiner passed to the constructor.
/// work_serializer passed to the constructor.
class Resolver : public InternallyRefCounted<Resolver> {
public:
/// Results returned by the resolver.
@ -87,7 +87,7 @@ class Resolver : public InternallyRefCounted<Resolver> {
// Not copyable nor movable.
Resolver(const Resolver&) = delete;
Resolver& operator=(const Resolver&) = delete;
virtual ~Resolver();
virtual ~Resolver() = default;
/// Starts resolving.
virtual void StartLocked() = 0;
@ -115,30 +115,28 @@ class Resolver : public InternallyRefCounted<Resolver> {
/// implementations. At that point, this method can go away.
virtual void ResetBackoffLocked() {}
// Note: This must be invoked while holding the combiner.
// Note: This must be invoked while holding the work_serializer.
void Orphan() override {
ShutdownLocked();
Unref();
}
protected:
/// Does NOT take ownership of the reference to \a combiner.
// TODO(roth): Once we have a C++-like interface for combiners, this
// API should change to take a RefCountedPtr<>, so that we always take
// ownership of a new ref.
explicit Resolver(Combiner* combiner,
std::unique_ptr<ResultHandler> result_handler);
Resolver(std::shared_ptr<WorkSerializer> work_serializer,
std::unique_ptr<ResultHandler> result_handler);
/// Shuts down the resolver.
virtual void ShutdownLocked() = 0;
Combiner* combiner() const { return combiner_; }
std::shared_ptr<WorkSerializer> work_serializer() const {
return work_serializer_;
}
ResultHandler* result_handler() const { return result_handler_.get(); }
private:
std::shared_ptr<WorkSerializer> work_serializer_;
std::unique_ptr<ResultHandler> result_handler_;
Combiner* combiner_;
};
} // namespace grpc_core

@ -24,6 +24,8 @@
#include <stdio.h>
#include <string.h>
#include "absl/container/inlined_vector.h"
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
@ -41,11 +43,11 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/manual_constructor.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/gethostname.h"
#include "src/core/lib/iomgr/iomgr_custom.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
#include "src/core/lib/json/json.h"
#define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1
@ -79,8 +81,8 @@ class AresDnsResolver : public Resolver {
static void OnNextResolution(void* arg, grpc_error* error);
static void OnResolved(void* arg, grpc_error* error);
static void OnNextResolutionLocked(void* arg, grpc_error* error);
static void OnResolvedLocked(void* arg, grpc_error* error);
void OnNextResolutionLocked(grpc_error* error);
void OnResolvedLocked(grpc_error* error);
/// DNS server to use (if not system default)
char* dns_server_;
@ -92,7 +94,7 @@ class AresDnsResolver : public Resolver {
bool request_service_config_;
/// pollset_set to drive the name resolution process
grpc_pollset_set* interested_parties_;
/// closures used by the combiner
/// closures used by the work_serializer
grpc_closure on_next_resolution_;
grpc_closure on_resolved_;
/// are we currently resolving?
@ -123,7 +125,7 @@ class AresDnsResolver : public Resolver {
};
AresDnsResolver::AresDnsResolver(ResolverArgs args)
: Resolver(args.combiner, std::move(args.result_handler)),
: Resolver(std::move(args.work_serializer), std::move(args.result_handler)),
backoff_(
BackOff::Options()
.set_initial_backoff(GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS *
@ -131,6 +133,10 @@ AresDnsResolver::AresDnsResolver(ResolverArgs args)
.set_multiplier(GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER)
.set_jitter(GRPC_DNS_RECONNECT_JITTER)
.set_max_backoff(GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS * 1000)) {
// Closure Initialization
GRPC_CLOSURE_INIT(&on_next_resolution_, OnNextResolution, this,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&on_resolved_, OnResolved, this, grpc_schedule_on_exec_ctx);
// Get name to resolve from URI path.
const char* path = args.uri->path;
if (path[0] == '/') ++path;
@ -204,26 +210,26 @@ void AresDnsResolver::ShutdownLocked() {
void AresDnsResolver::OnNextResolution(void* arg, grpc_error* error) {
AresDnsResolver* r = static_cast<AresDnsResolver*>(arg);
r->combiner()->Run(GRPC_CLOSURE_INIT(&r->on_next_resolution_,
OnNextResolutionLocked, r, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // ref owned by lambda
r->work_serializer()->Run([r, error]() { r->OnNextResolutionLocked(error); },
DEBUG_LOCATION);
}
void AresDnsResolver::OnNextResolutionLocked(void* arg, grpc_error* error) {
AresDnsResolver* r = static_cast<AresDnsResolver*>(arg);
void AresDnsResolver::OnNextResolutionLocked(grpc_error* error) {
GRPC_CARES_TRACE_LOG(
"resolver:%p re-resolution timer fired. error: %s. shutdown_initiated_: "
"%d",
r, grpc_error_string(error), r->shutdown_initiated_);
r->have_next_resolution_timer_ = false;
if (error == GRPC_ERROR_NONE && !r->shutdown_initiated_) {
if (!r->resolving_) {
this, grpc_error_string(error), shutdown_initiated_);
have_next_resolution_timer_ = false;
if (error == GRPC_ERROR_NONE && !shutdown_initiated_) {
if (!resolving_) {
GRPC_CARES_TRACE_LOG(
"resolver:%p start resolving due to re-resolution timer", r);
r->StartResolvingLocked();
"resolver:%p start resolving due to re-resolution timer", this);
StartResolvingLocked();
}
}
r->Unref(DEBUG_LOCATION, "next_resolution_timer");
Unref(DEBUG_LOCATION, "next_resolution_timer");
GRPC_ERROR_UNREF(error);
}
bool ValueInJsonArray(const Json::Array& array, const char* value) {
@ -245,7 +251,7 @@ std::string ChooseServiceConfig(char* service_config_choice_json,
return "";
}
const Json* service_config = nullptr;
InlinedVector<grpc_error*, 4> error_list;
absl::InlinedVector<grpc_error*, 4> error_list;
for (const Json& choice : json.array_value()) {
if (choice.type() != Json::Type::OBJECT) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
@ -316,81 +322,79 @@ std::string ChooseServiceConfig(char* service_config_choice_json,
void AresDnsResolver::OnResolved(void* arg, grpc_error* error) {
AresDnsResolver* r = static_cast<AresDnsResolver*>(arg);
r->combiner()->Run(
GRPC_CLOSURE_INIT(&r->on_resolved_, OnResolvedLocked, r, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // ref owned by lambda
r->work_serializer()->Run([r, error]() { r->OnResolvedLocked(error); },
DEBUG_LOCATION);
}
void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
AresDnsResolver* r = static_cast<AresDnsResolver*>(arg);
GPR_ASSERT(r->resolving_);
r->resolving_ = false;
gpr_free(r->pending_request_);
r->pending_request_ = nullptr;
if (r->shutdown_initiated_) {
r->Unref(DEBUG_LOCATION, "OnResolvedLocked() shutdown");
void AresDnsResolver::OnResolvedLocked(grpc_error* error) {
GPR_ASSERT(resolving_);
resolving_ = false;
gpr_free(pending_request_);
pending_request_ = nullptr;
if (shutdown_initiated_) {
Unref(DEBUG_LOCATION, "OnResolvedLocked() shutdown");
GRPC_ERROR_UNREF(error);
return;
}
if (r->addresses_ != nullptr || r->balancer_addresses_ != nullptr) {
if (addresses_ != nullptr || balancer_addresses_ != nullptr) {
Result result;
if (r->addresses_ != nullptr) {
result.addresses = std::move(*r->addresses_);
if (addresses_ != nullptr) {
result.addresses = std::move(*addresses_);
}
if (r->service_config_json_ != nullptr) {
if (service_config_json_ != nullptr) {
std::string service_config_string = ChooseServiceConfig(
r->service_config_json_, &result.service_config_error);
gpr_free(r->service_config_json_);
service_config_json_, &result.service_config_error);
gpr_free(service_config_json_);
if (result.service_config_error == GRPC_ERROR_NONE &&
!service_config_string.empty()) {
GRPC_CARES_TRACE_LOG("resolver:%p selected service config choice: %s",
r, service_config_string.c_str());
this, service_config_string.c_str());
result.service_config = ServiceConfig::Create(
service_config_string, &result.service_config_error);
}
}
InlinedVector<grpc_arg, 1> new_args;
if (r->balancer_addresses_ != nullptr) {
absl::InlinedVector<grpc_arg, 1> new_args;
if (balancer_addresses_ != nullptr) {
new_args.push_back(
CreateGrpclbBalancerAddressesArg(r->balancer_addresses_.get()));
CreateGrpclbBalancerAddressesArg(balancer_addresses_.get()));
}
result.args = grpc_channel_args_copy_and_add(
r->channel_args_, new_args.data(), new_args.size());
r->result_handler()->ReturnResult(std::move(result));
r->addresses_.reset();
r->balancer_addresses_.reset();
result.args = grpc_channel_args_copy_and_add(channel_args_, new_args.data(),
new_args.size());
result_handler()->ReturnResult(std::move(result));
addresses_.reset();
balancer_addresses_.reset();
// Reset backoff state so that we start from the beginning when the
// next request gets triggered.
r->backoff_.Reset();
backoff_.Reset();
} else {
GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed: %s", r,
GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed: %s", this,
grpc_error_string(error));
r->result_handler()->ReturnError(grpc_error_set_int(
result_handler()->ReturnError(grpc_error_set_int(
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"DNS resolution failed", &error, 1),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
// Set retry timer.
grpc_millis next_try = r->backoff_.NextAttemptTime();
grpc_millis next_try = backoff_.NextAttemptTime();
grpc_millis timeout = next_try - ExecCtx::Get()->Now();
GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed (will retry): %s",
r, grpc_error_string(error));
GPR_ASSERT(!r->have_next_resolution_timer_);
r->have_next_resolution_timer_ = true;
this, grpc_error_string(error));
GPR_ASSERT(!have_next_resolution_timer_);
have_next_resolution_timer_ = true;
// TODO(roth): We currently deal with this ref manually. Once the
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
r->Ref(DEBUG_LOCATION, "retry-timer").release();
Ref(DEBUG_LOCATION, "retry-timer").release();
if (timeout > 0) {
GRPC_CARES_TRACE_LOG("resolver:%p retrying in %" PRId64 " milliseconds",
r, timeout);
this, timeout);
} else {
GRPC_CARES_TRACE_LOG("resolver:%p retrying immediately", r);
GRPC_CARES_TRACE_LOG("resolver:%p retrying immediately", this);
}
GRPC_CLOSURE_INIT(&r->on_next_resolution_, OnNextResolution, r,
grpc_schedule_on_exec_ctx);
grpc_timer_init(&r->next_resolution_timer_, next_try,
&r->on_next_resolution_);
grpc_timer_init(&next_resolution_timer_, next_try, &on_next_resolution_);
}
r->Unref(DEBUG_LOCATION, "dns-resolving");
Unref(DEBUG_LOCATION, "dns-resolving");
GRPC_ERROR_UNREF(error);
}
void AresDnsResolver::MaybeStartResolvingLocked() {
@ -414,8 +418,6 @@ void AresDnsResolver::MaybeStartResolvingLocked() {
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown").release();
GRPC_CLOSURE_INIT(&on_next_resolution_, OnNextResolution, this,
grpc_schedule_on_exec_ctx);
grpc_timer_init(&next_resolution_timer_,
ExecCtx::Get()->Now() + ms_until_next_resolution,
&on_next_resolution_);
@ -433,13 +435,12 @@ void AresDnsResolver::StartResolvingLocked() {
GPR_ASSERT(!resolving_);
resolving_ = true;
service_config_json_ = nullptr;
GRPC_CLOSURE_INIT(&on_resolved_, OnResolved, this, grpc_schedule_on_exec_ctx);
pending_request_ = grpc_dns_lookup_ares_locked(
dns_server_, name_to_resolve_, kDefaultPort, interested_parties_,
&on_resolved_, &addresses_,
enable_srv_queries_ ? &balancer_addresses_ : nullptr,
request_service_config_ ? &service_config_json_ : nullptr,
query_timeout_ms_, combiner());
query_timeout_ms_, work_serializer());
last_resolution_timestamp_ = grpc_core::ExecCtx::Get()->Now();
GRPC_CARES_TRACE_LOG("resolver:%p Started resolving. pending_request_:%p",
this, pending_request_);

@ -31,7 +31,6 @@
#include <grpc/support/time.h>
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/iomgr_internal.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/timer.h"
@ -66,8 +65,8 @@ struct grpc_ares_ev_driver {
/** refcount of the event driver */
gpr_refcount refs;
/** combiner to synchronize c-ares and I/O callbacks on */
grpc_core::Combiner* combiner;
/** work_serializer to synchronize c-ares and I/O callbacks on */
std::shared_ptr<grpc_core::WorkSerializer> work_serializer;
/** a list of grpc_fd that this event driver is currently using. */
fd_node* fds;
/** is this event driver currently working? */
@ -107,7 +106,6 @@ static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) {
GRPC_CARES_TRACE_LOG("request:%p destroy ev_driver %p", ev_driver->request,
ev_driver);
GPR_ASSERT(ev_driver->fds == nullptr);
GRPC_COMBINER_UNREF(ev_driver->combiner, "free ares event driver");
ares_destroy(ev_driver->channel);
grpc_ares_complete_request_locked(ev_driver->request);
delete ev_driver;
@ -133,21 +131,22 @@ static void fd_node_shutdown_locked(fd_node* fdn, const char* reason) {
}
static void on_timeout(void* arg, grpc_error* error);
static void on_timeout_locked(void* arg, grpc_error* error);
static void on_timeout_locked(grpc_ares_ev_driver* arg, grpc_error* error);
static void on_ares_backup_poll_alarm(void* arg, grpc_error* error);
static void on_ares_backup_poll_alarm_locked(void* arg, grpc_error* error);
static void on_ares_backup_poll_alarm_locked(grpc_ares_ev_driver* arg,
grpc_error* error);
static void noop_inject_channel_config(ares_channel /*channel*/) {}
void (*grpc_ares_test_only_inject_config)(ares_channel channel) =
noop_inject_channel_config;
grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
grpc_pollset_set* pollset_set,
int query_timeout_ms,
grpc_core::Combiner* combiner,
grpc_ares_request* request) {
grpc_error* grpc_ares_ev_driver_create_locked(
grpc_ares_ev_driver** ev_driver, grpc_pollset_set* pollset_set,
int query_timeout_ms,
std::shared_ptr<grpc_core::WorkSerializer> work_serializer,
grpc_ares_request* request) {
*ev_driver = new grpc_ares_ev_driver();
ares_options opts;
memset(&opts, 0, sizeof(opts));
@ -164,7 +163,7 @@ grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
gpr_free(*ev_driver);
return err;
}
(*ev_driver)->combiner = GRPC_COMBINER_REF(combiner, "ares event driver");
(*ev_driver)->work_serializer = std::move(work_serializer);
gpr_ref_init(&(*ev_driver)->refs, 1);
(*ev_driver)->pollset_set = pollset_set;
(*ev_driver)->fds = nullptr;
@ -172,7 +171,7 @@ grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
(*ev_driver)->shutting_down = false;
(*ev_driver)->request = request;
(*ev_driver)->polled_fd_factory =
grpc_core::NewGrpcPolledFdFactory((*ev_driver)->combiner);
grpc_core::NewGrpcPolledFdFactory((*ev_driver)->work_serializer);
(*ev_driver)
->polled_fd_factory->ConfigureAresChannelLocked((*ev_driver)->channel);
(*ev_driver)->query_timeout_ms = query_timeout_ms;
@ -234,13 +233,12 @@ static grpc_millis calculate_next_ares_backup_poll_alarm_ms(
static void on_timeout(void* arg, grpc_error* error) {
grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg);
driver->combiner->Run(GRPC_CLOSURE_INIT(&driver->on_timeout_locked,
on_timeout_locked, driver, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // ref owned by lambda
driver->work_serializer->Run(
[driver, error]() { on_timeout_locked(driver, error); }, DEBUG_LOCATION);
}
static void on_timeout_locked(void* arg, grpc_error* error) {
grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg);
static void on_timeout_locked(grpc_ares_ev_driver* driver, grpc_error* error) {
GRPC_CARES_TRACE_LOG(
"request:%p ev_driver=%p on_timeout_locked. driver->shutting_down=%d. "
"err=%s",
@ -249,14 +247,15 @@ static void on_timeout_locked(void* arg, grpc_error* error) {
grpc_ares_ev_driver_shutdown_locked(driver);
}
grpc_ares_ev_driver_unref(driver);
GRPC_ERROR_UNREF(error);
}
static void on_ares_backup_poll_alarm(void* arg, grpc_error* error) {
grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg);
driver->combiner->Run(
GRPC_CLOSURE_INIT(&driver->on_ares_backup_poll_alarm_locked,
on_ares_backup_poll_alarm_locked, driver, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error);
driver->work_serializer->Run(
[driver, error]() { on_ares_backup_poll_alarm_locked(driver, error); },
DEBUG_LOCATION);
}
/* In case of non-responsive DNS servers, dropped packets, etc., c-ares has
@ -267,8 +266,8 @@ static void on_ares_backup_poll_alarm(void* arg, grpc_error* error) {
* b) when some time has passed without fd events having happened
* For the latter, we use this backup poller. Also see
* https://github.com/grpc/grpc/pull/17688 description for more details. */
static void on_ares_backup_poll_alarm_locked(void* arg, grpc_error* error) {
grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg);
static void on_ares_backup_poll_alarm_locked(grpc_ares_ev_driver* driver,
grpc_error* error) {
GRPC_CARES_TRACE_LOG(
"request:%p ev_driver=%p on_ares_backup_poll_alarm_locked. "
"driver->shutting_down=%d. "
@ -301,10 +300,10 @@ static void on_ares_backup_poll_alarm_locked(void* arg, grpc_error* error) {
grpc_ares_notify_on_event_locked(driver);
}
grpc_ares_ev_driver_unref(driver);
GRPC_ERROR_UNREF(error);
}
static void on_readable_locked(void* arg, grpc_error* error) {
fd_node* fdn = static_cast<fd_node*>(arg);
static void on_readable_locked(fd_node* fdn, grpc_error* error) {
GPR_ASSERT(fdn->readable_registered);
grpc_ares_ev_driver* ev_driver = fdn->ev_driver;
const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked();
@ -326,17 +325,17 @@ static void on_readable_locked(void* arg, grpc_error* error) {
}
grpc_ares_notify_on_event_locked(ev_driver);
grpc_ares_ev_driver_unref(ev_driver);
GRPC_ERROR_UNREF(error);
}
static void on_readable(void* arg, grpc_error* error) {
fd_node* fdn = static_cast<fd_node*>(arg);
fdn->ev_driver->combiner->Run(
GRPC_CLOSURE_INIT(&fdn->read_closure, on_readable_locked, fdn, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); /* ref owned by lambda */
fdn->ev_driver->work_serializer->Run(
[fdn, error]() { on_readable_locked(fdn, error); }, DEBUG_LOCATION);
}
static void on_writable_locked(void* arg, grpc_error* error) {
fd_node* fdn = static_cast<fd_node*>(arg);
static void on_writable_locked(fd_node* fdn, grpc_error* error) {
GPR_ASSERT(fdn->writable_registered);
grpc_ares_ev_driver* ev_driver = fdn->ev_driver;
const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked();
@ -356,13 +355,14 @@ static void on_writable_locked(void* arg, grpc_error* error) {
}
grpc_ares_notify_on_event_locked(ev_driver);
grpc_ares_ev_driver_unref(ev_driver);
GRPC_ERROR_UNREF(error);
}
static void on_writable(void* arg, grpc_error* error) {
fd_node* fdn = static_cast<fd_node*>(arg);
fdn->ev_driver->combiner->Run(
GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable_locked, fdn, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); /* ref owned by lambda */
fdn->ev_driver->work_serializer->Run(
[fdn, error]() { on_writable_locked(fdn, error); }, DEBUG_LOCATION);
}
ares_channel* grpc_ares_ev_driver_get_channel_locked(
@ -387,7 +387,7 @@ static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) {
fdn = static_cast<fd_node*>(gpr_malloc(sizeof(fd_node)));
fdn->grpc_polled_fd =
ev_driver->polled_fd_factory->NewGrpcPolledFdLocked(
socks[i], ev_driver->pollset_set, ev_driver->combiner);
socks[i], ev_driver->pollset_set, ev_driver->work_serializer);
GRPC_CARES_TRACE_LOG("request:%p new fd: %s", ev_driver->request,
fdn->grpc_polled_fd->GetName());
fdn->ev_driver = ev_driver;

@ -40,11 +40,11 @@ ares_channel* grpc_ares_ev_driver_get_channel_locked(
/* Creates a new grpc_ares_ev_driver. Returns GRPC_ERROR_NONE if \a ev_driver is
created successfully. */
grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
grpc_pollset_set* pollset_set,
int query_timeout_ms,
grpc_core::Combiner* combiner,
grpc_ares_request* request);
grpc_error* grpc_ares_ev_driver_create_locked(
grpc_ares_ev_driver** ev_driver, grpc_pollset_set* pollset_set,
int query_timeout_ms,
std::shared_ptr<grpc_core::WorkSerializer> work_serializer,
grpc_ares_request* request);
/* Called back when all DNS lookups have completed. */
void grpc_ares_ev_driver_on_queries_complete_locked(
@ -90,12 +90,13 @@ class GrpcPolledFdFactory {
/* Creates a new wrapped fd for the current platform */
virtual GrpcPolledFd* NewGrpcPolledFdLocked(
ares_socket_t as, grpc_pollset_set* driver_pollset_set,
Combiner* combiner) = 0;
std::shared_ptr<grpc_core::WorkSerializer> work_serializer) = 0;
/* Optionally configures the ares channel after creation */
virtual void ConfigureAresChannelLocked(ares_channel channel) = 0;
};
std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(Combiner* combiner);
std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(
std::shared_ptr<grpc_core::WorkSerializer> work_serializer);
} // namespace grpc_core

@ -31,7 +31,7 @@
#include <grpc/support/time.h>
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/work_serializer.h"
namespace grpc_core {
@ -41,19 +41,16 @@ void ares_uv_poll_close_cb(uv_handle_t* handle) { delete handle; }
class GrpcPolledFdLibuv : public GrpcPolledFd {
public:
GrpcPolledFdLibuv(ares_socket_t as, Combiner* combiner)
: as_(as), combiner_(combiner) {
GrpcPolledFdLibuv(ares_socket_t as,
std::shared_ptr<WorkSerializer> work_serializer)
: as_(as), work_serializer_(std::move(work_serializer)) {
gpr_asprintf(&name_, "c-ares socket: %" PRIdPTR, (intptr_t)as);
handle_ = new uv_poll_t();
uv_poll_init_socket(uv_default_loop(), handle_, as);
handle_->data = this;
GRPC_COMBINER_REF(combiner_, "libuv ares event driver");
}
~GrpcPolledFdLibuv() {
gpr_free(name_);
GRPC_COMBINER_UNREF(combiner_, "libuv ares event driver");
}
~GrpcPolledFdLibuv() { gpr_free(name_); }
void RegisterForOnReadableLocked(grpc_closure* read_closure) override {
GPR_ASSERT(read_closure_ == nullptr);
@ -109,7 +106,7 @@ class GrpcPolledFdLibuv : public GrpcPolledFd {
grpc_closure* read_closure_ = nullptr;
grpc_closure* write_closure_ = nullptr;
int poll_events_ = 0;
Combiner* combiner_;
std::shared_ptr<WorkSerializer> work_serializer_;
};
struct AresUvPollCbArg {
@ -121,14 +118,14 @@ struct AresUvPollCbArg {
int events;
};
static void ares_uv_poll_cb_locked(void* arg, grpc_error* error) {
std::unique_ptr<AresUvPollCbArg> arg_struct(
reinterpret_cast<AresUvPollCbArg*>(arg));
static void ares_uv_poll_cb_locked(AresUvPollCbArg* arg) {
std::unique_ptr<AresUvPollCbArg> arg_struct(arg);
uv_poll_t* handle = arg_struct->handle;
int status = arg_struct->status;
int events = arg_struct->events;
GrpcPolledFdLibuv* polled_fd =
reinterpret_cast<GrpcPolledFdLibuv*>(handle->data);
grpc_error* error = GRPC_ERROR_NONE;
if (status < 0) {
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("cares polling error");
error =
@ -155,24 +152,23 @@ void ares_uv_poll_cb(uv_poll_t* handle, int status, int events) {
GrpcPolledFdLibuv* polled_fd =
reinterpret_cast<GrpcPolledFdLibuv*>(handle->data);
AresUvPollCbArg* arg = new AresUvPollCbArg(handle, status, events);
polled_fd->combiner_->Run(
GRPC_CLOSURE_CREATE(ares_uv_poll_cb_locked, arg, nullptr),
GRPC_ERROR_NONE);
polled_fd->work_serializer_->Run([arg]() { ares_uv_poll_cb_locked(arg); },
DEBUG_LOCATION);
}
class GrpcPolledFdFactoryLibuv : public GrpcPolledFdFactory {
public:
GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
grpc_pollset_set* driver_pollset_set,
Combiner* combiner) override {
return new GrpcPolledFdLibuv(as, combiner);
GrpcPolledFd* NewGrpcPolledFdLocked(
ares_socket_t as, grpc_pollset_set* driver_pollset_set,
std::shared_ptr<WorkSerializer> work_serializer) override {
return new GrpcPolledFdLibuv(as, std::move(work_serializer));
}
void ConfigureAresChannelLocked(ares_channel channel) override {}
};
std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(
Combiner* combiner) {
std::shared_ptr<WorkSerializer> work_serializer) {
return absl::make_unique<GrpcPolledFdFactoryLibuv>();
}

@ -88,9 +88,9 @@ class GrpcPolledFdPosix : public GrpcPolledFd {
class GrpcPolledFdFactoryPosix : public GrpcPolledFdFactory {
public:
GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
grpc_pollset_set* driver_pollset_set,
Combiner* /*combiner*/) override {
GrpcPolledFd* NewGrpcPolledFdLocked(
ares_socket_t as, grpc_pollset_set* driver_pollset_set,
std::shared_ptr<WorkSerializer> /*work_serializer*/) override {
return new GrpcPolledFdPosix(as, driver_pollset_set);
}
@ -98,7 +98,7 @@ class GrpcPolledFdFactoryPosix : public GrpcPolledFdFactory {
};
std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(
Combiner* /*combiner*/) {
std::shared_ptr<WorkSerializer> work_serializer) { /* NOLINT */
return absl::make_unique<GrpcPolledFdFactoryPosix>();
}

@ -30,12 +30,12 @@
#include <string.h>
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/iocp_windows.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/sockaddr_windows.h"
#include "src/core/lib/iomgr/socket_windows.h"
#include "src/core/lib/iomgr/tcp_windows.h"
#include "src/core/lib/iomgr/work_serializer.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
@ -97,28 +97,31 @@ class GrpcPolledFdWindows {
WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY,
};
GrpcPolledFdWindows(ares_socket_t as, Combiner* combiner, int address_family,
int socket_type)
: read_buf_(grpc_empty_slice()),
GrpcPolledFdWindows(ares_socket_t as,
std::shared_ptr<WorkSerializer> work_serializer,
int address_family, int socket_type)
: work_serializer_(std::move(work_serializer)),
read_buf_(grpc_empty_slice()),
write_buf_(grpc_empty_slice()),
tcp_write_state_(WRITE_IDLE),
gotten_into_driver_list_(false),
address_family_(address_family),
socket_type_(socket_type) {
gpr_asprintf(&name_, "c-ares socket: %" PRIdPTR, as);
// Closure Initialization
GRPC_CLOSURE_INIT(&outer_read_closure_,
&GrpcPolledFdWindows::OnIocpReadable, this,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&outer_write_closure_,
&GrpcPolledFdWindows::OnIocpWriteable, this,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&on_tcp_connect_locked_,
&GrpcPolledFdWindows::OnTcpConnect, this,
grpc_schedule_on_exec_ctx);
winsocket_ = grpc_winsocket_create(as, name_);
combiner_ = GRPC_COMBINER_REF(combiner, name_);
GRPC_CLOSURE_INIT(&continue_register_for_on_readable_locked_,
&GrpcPolledFdWindows::ContinueRegisterForOnReadableLocked,
this, nullptr);
GRPC_CLOSURE_INIT(
&continue_register_for_on_writeable_locked_,
&GrpcPolledFdWindows::ContinueRegisterForOnWriteableLocked, this,
nullptr);
}
~GrpcPolledFdWindows() {
GRPC_COMBINER_UNREF(combiner_, name_);
grpc_slice_unref_internal(read_buf_);
grpc_slice_unref_internal(write_buf_);
GPR_ASSERT(read_closure_ == nullptr);
@ -145,23 +148,15 @@ class GrpcPolledFdWindows {
GPR_ASSERT(!read_buf_has_data_);
read_buf_ = GRPC_SLICE_MALLOC(4192);
if (connect_done_) {
combiner_->Run(&continue_register_for_on_readable_locked_,
GRPC_ERROR_NONE);
work_serializer_->Run([this]() { ContinueRegisterForOnReadableLocked(); },
DEBUG_LOCATION);
} else {
GPR_ASSERT(pending_continue_register_for_on_readable_locked_ == nullptr);
pending_continue_register_for_on_readable_locked_ =
&continue_register_for_on_readable_locked_;
GPR_ASSERT(pending_continue_register_for_on_readable_locked_ == false);
pending_continue_register_for_on_readable_locked_ = true;
}
}
static void ContinueRegisterForOnReadableLocked(void* arg,
grpc_error* unused_error) {
GrpcPolledFdWindows* grpc_polled_fd =
static_cast<GrpcPolledFdWindows*>(arg);
grpc_polled_fd->InnerContinueRegisterForOnReadableLocked(GRPC_ERROR_NONE);
}
void InnerContinueRegisterForOnReadableLocked(grpc_error* unused_error) {
void ContinueRegisterForOnReadableLocked() {
GRPC_CARES_TRACE_LOG(
"fd:|%s| InnerContinueRegisterForOnReadableLocked "
"wsa_connect_error_:%d",
@ -194,10 +189,7 @@ class GrpcPolledFdWindows {
return;
}
}
grpc_socket_notify_on_read(
winsocket_, GRPC_CLOSURE_INIT(&outer_read_closure_,
&GrpcPolledFdWindows::OnIocpReadable,
this, grpc_schedule_on_exec_ctx));
grpc_socket_notify_on_read(winsocket_, &outer_read_closure_);
}
void RegisterForOnWriteableLocked(grpc_closure* write_closure) {
@ -213,23 +205,15 @@ class GrpcPolledFdWindows {
GPR_ASSERT(write_closure_ == nullptr);
write_closure_ = write_closure;
if (connect_done_) {
combiner_->Run(&continue_register_for_on_writeable_locked_,
GRPC_ERROR_NONE);
work_serializer_->Run(
[this]() { ContinueRegisterForOnWriteableLocked(); }, DEBUG_LOCATION);
} else {
GPR_ASSERT(pending_continue_register_for_on_writeable_locked_ == nullptr);
pending_continue_register_for_on_writeable_locked_ =
&continue_register_for_on_writeable_locked_;
GPR_ASSERT(pending_continue_register_for_on_writeable_locked_ == false);
pending_continue_register_for_on_writeable_locked_ = true;
}
}
static void ContinueRegisterForOnWriteableLocked(void* arg,
grpc_error* unused_error) {
GrpcPolledFdWindows* grpc_polled_fd =
static_cast<GrpcPolledFdWindows*>(arg);
grpc_polled_fd->InnerContinueRegisterForOnWriteableLocked(GRPC_ERROR_NONE);
}
void InnerContinueRegisterForOnWriteableLocked(grpc_error* unused_error) {
void ContinueRegisterForOnWriteableLocked() {
GRPC_CARES_TRACE_LOG(
"fd:|%s| InnerContinueRegisterForOnWriteableLocked "
"wsa_connect_error_:%d",
@ -256,11 +240,7 @@ class GrpcPolledFdWindows {
ScheduleAndNullWriteClosure(
GRPC_WSA_ERROR(wsa_error_code, "WSASend (overlapped)"));
} else {
grpc_socket_notify_on_write(
winsocket_,
GRPC_CLOSURE_INIT(&outer_write_closure_,
&GrpcPolledFdWindows::OnIocpWriteable, this,
grpc_schedule_on_exec_ctx));
grpc_socket_notify_on_write(winsocket_, &outer_write_closure_);
}
break;
case WRITE_PENDING:
@ -440,24 +420,19 @@ class GrpcPolledFdWindows {
static void OnTcpConnect(void* arg, grpc_error* error) {
GrpcPolledFdWindows* grpc_polled_fd =
static_cast<GrpcPolledFdWindows*>(arg);
grpc_polled_fd->combiner_->Run(
GRPC_CLOSURE_INIT(&grpc_polled_fd->on_tcp_connect_locked_,
&GrpcPolledFdWindows::OnTcpConnectLocked,
grpc_polled_fd, nullptr),
GRPC_ERROR_REF(error));
}
static void OnTcpConnectLocked(void* arg, grpc_error* error) {
GrpcPolledFdWindows* grpc_polled_fd =
static_cast<GrpcPolledFdWindows*>(arg);
grpc_polled_fd->InnerOnTcpConnectLocked(error);
GRPC_ERROR_REF(error); // ref owned by lambda
grpc_polled_fd->work_serializer_->Run(
[grpc_polled_fd, error]() {
grpc_polled_fd->OnTcpConnectLocked(error);
},
DEBUG_LOCATION);
}
void InnerOnTcpConnectLocked(grpc_error* error) {
void OnTcpConnectLocked(grpc_error* error) {
GRPC_CARES_TRACE_LOG(
"fd:%s InnerOnTcpConnectLocked error:|%s| "
"pending_register_for_readable:%" PRIdPTR
" pending_register_for_writeable:%" PRIdPTR,
"pending_register_for_readable:%d"
" pending_register_for_writeable:%d",
GetName(), grpc_error_string(error),
pending_continue_register_for_on_readable_locked_,
pending_continue_register_for_on_writeable_locked_);
@ -486,14 +461,15 @@ class GrpcPolledFdWindows {
// this fd to abort.
wsa_connect_error_ = WSA_OPERATION_ABORTED;
}
if (pending_continue_register_for_on_readable_locked_ != nullptr) {
combiner_->Run(pending_continue_register_for_on_readable_locked_,
GRPC_ERROR_NONE);
if (pending_continue_register_for_on_readable_locked_) {
work_serializer_->Run([this]() { ContinueRegisterForOnReadableLocked(); },
DEBUG_LOCATION);
}
if (pending_continue_register_for_on_writeable_locked_ != nullptr) {
combiner_->Run(pending_continue_register_for_on_writeable_locked_,
GRPC_ERROR_NONE);
if (pending_continue_register_for_on_writeable_locked_) {
work_serializer_->Run(
[this]() { ContinueRegisterForOnWriteableLocked(); }, DEBUG_LOCATION);
}
GRPC_ERROR_UNREF(error);
}
int Connect(WSAErrorContext* wsa_error_ctx, const struct sockaddr* target,
@ -593,25 +569,16 @@ class GrpcPolledFdWindows {
return -1;
}
}
GRPC_CLOSURE_INIT(&on_tcp_connect_locked_,
&GrpcPolledFdWindows::OnTcpConnect, this,
grpc_schedule_on_exec_ctx);
grpc_socket_notify_on_write(winsocket_, &on_tcp_connect_locked_);
return out;
}
static void OnIocpReadable(void* arg, grpc_error* error) {
GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg);
polled_fd->combiner_->Run(
GRPC_CLOSURE_INIT(&polled_fd->outer_read_closure_,
&GrpcPolledFdWindows::OnIocpReadableLocked, polled_fd,
nullptr),
GRPC_ERROR_REF(error));
}
static void OnIocpReadableLocked(void* arg, grpc_error* error) {
GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg);
polled_fd->OnIocpReadableInner(error);
GRPC_ERROR_REF(error); // ref owned by lambda
polled_fd->work_serializer_->Run(
[polled_fd, error]() { polled_fd->OnIocpReadableLocked(error); },
DEBUG_LOCATION);
}
// TODO(apolcyn): improve this error handling to be less conversative.
@ -619,7 +586,7 @@ class GrpcPolledFdWindows {
// c-ares reads from this socket later, but it shouldn't necessarily cancel
// the entire resolution attempt. Doing so will allow the "inject broken
// nameserver list" test to pass on Windows.
void OnIocpReadableInner(grpc_error* error) {
void OnIocpReadableLocked(grpc_error* error) {
if (error == GRPC_ERROR_NONE) {
if (winsocket_->read_info.wsa_error != 0) {
/* WSAEMSGSIZE would be due to receiving more data
@ -627,7 +594,6 @@ class GrpcPolledFdWindows {
* the connection is TCP and read the leftovers
* in subsequent c-ares reads. */
if (winsocket_->read_info.wsa_error != WSAEMSGSIZE) {
GRPC_ERROR_UNREF(error);
error = GRPC_WSA_ERROR(winsocket_->read_info.wsa_error,
"OnIocpReadableInner");
GRPC_CARES_TRACE_LOG(
@ -654,24 +620,17 @@ class GrpcPolledFdWindows {
static void OnIocpWriteable(void* arg, grpc_error* error) {
GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg);
polled_fd->combiner_->Run(
GRPC_CLOSURE_INIT(&polled_fd->outer_write_closure_,
&GrpcPolledFdWindows::OnIocpWriteableLocked,
polled_fd, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // error owned by lambda
polled_fd->work_serializer_->Run(
[polled_fd, error]() { polled_fd->OnIocpWriteableLocked(error); },
DEBUG_LOCATION);
}
static void OnIocpWriteableLocked(void* arg, grpc_error* error) {
GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg);
polled_fd->OnIocpWriteableInner(error);
}
void OnIocpWriteableInner(grpc_error* error) {
void OnIocpWriteableLocked(grpc_error* error) {
GRPC_CARES_TRACE_LOG("OnIocpWriteableInner. fd:|%s|", GetName());
GPR_ASSERT(socket_type_ == SOCK_STREAM);
if (error == GRPC_ERROR_NONE) {
if (winsocket_->write_info.wsa_error != 0) {
GRPC_ERROR_UNREF(error);
error = GRPC_WSA_ERROR(winsocket_->write_info.wsa_error,
"OnIocpWriteableInner");
GRPC_CARES_TRACE_LOG(
@ -698,7 +657,7 @@ class GrpcPolledFdWindows {
bool gotten_into_driver_list() const { return gotten_into_driver_list_; }
void set_gotten_into_driver_list() { gotten_into_driver_list_ = true; }
Combiner* combiner_;
std::shared_ptr<WorkSerializer> work_serializer_;
char recv_from_source_addr_[200];
ares_socklen_t recv_from_source_addr_len_;
grpc_slice read_buf_;
@ -721,10 +680,8 @@ class GrpcPolledFdWindows {
// We don't run register_for_{readable,writeable} logic until
// a socket is connected. In the interim, we queue readable/writeable
// registrations with the following state.
grpc_closure continue_register_for_on_readable_locked_;
grpc_closure continue_register_for_on_writeable_locked_;
grpc_closure* pending_continue_register_for_on_readable_locked_ = nullptr;
grpc_closure* pending_continue_register_for_on_writeable_locked_ = nullptr;
bool pending_continue_register_for_on_readable_locked_ = false;
bool pending_continue_register_for_on_writeable_locked_ = false;
};
struct SockToPolledFdEntry {
@ -742,14 +699,10 @@ struct SockToPolledFdEntry {
* with a GrpcPolledFdWindows factory and event driver */
class SockToPolledFdMap {
public:
SockToPolledFdMap(Combiner* combiner) {
combiner_ = GRPC_COMBINER_REF(combiner, "sock to polled fd map");
}
explicit SockToPolledFdMap(std::shared_ptr<WorkSerializer> work_serializer)
: work_serializer_(std::move(work_serializer)) {}
~SockToPolledFdMap() {
GPR_ASSERT(head_ == nullptr);
GRPC_COMBINER_UNREF(combiner_, "sock to polled fd map");
}
~SockToPolledFdMap() { GPR_ASSERT(head_ == nullptr); }
void AddNewSocket(SOCKET s, GrpcPolledFdWindows* polled_fd) {
SockToPolledFdEntry* new_node = new SockToPolledFdEntry(s, polled_fd);
@ -805,7 +758,7 @@ class SockToPolledFdMap {
}
grpc_tcp_set_non_block(s);
GrpcPolledFdWindows* polled_fd =
new GrpcPolledFdWindows(s, map->combiner_, af, type);
new GrpcPolledFdWindows(s, map->work_serializer_, af, type);
GRPC_CARES_TRACE_LOG(
"fd:|%s| created with params af:%d type:%d protocol:%d",
polled_fd->GetName(), af, type, protocol);
@ -861,7 +814,7 @@ class SockToPolledFdMap {
private:
SockToPolledFdEntry* head_ = nullptr;
Combiner* combiner_;
std::shared_ptr<WorkSerializer> work_serializer_;
};
const struct ares_socket_functions custom_ares_sock_funcs = {
@ -877,7 +830,7 @@ const struct ares_socket_functions custom_ares_sock_funcs = {
so that c-ares can close it via usual socket teardown. */
class GrpcPolledFdWindowsWrapper : public GrpcPolledFd {
public:
GrpcPolledFdWindowsWrapper(GrpcPolledFdWindows* wrapped)
explicit GrpcPolledFdWindowsWrapper(GrpcPolledFdWindows* wrapped)
: wrapped_(wrapped) {}
~GrpcPolledFdWindowsWrapper() {}
@ -910,12 +863,13 @@ class GrpcPolledFdWindowsWrapper : public GrpcPolledFd {
class GrpcPolledFdFactoryWindows : public GrpcPolledFdFactory {
public:
GrpcPolledFdFactoryWindows(Combiner* combiner)
: sock_to_polled_fd_map_(combiner) {}
explicit GrpcPolledFdFactoryWindows(
std::shared_ptr<WorkSerializer> work_serializer)
: sock_to_polled_fd_map_(std::move(work_serializer)) {}
GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,
grpc_pollset_set* driver_pollset_set,
Combiner* combiner) override {
GrpcPolledFd* NewGrpcPolledFdLocked(
ares_socket_t as, grpc_pollset_set* driver_pollset_set,
std::shared_ptr<WorkSerializer> work_serializer) 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.
@ -933,8 +887,9 @@ class GrpcPolledFdFactoryWindows : public GrpcPolledFdFactory {
};
std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(
Combiner* combiner) {
return absl::make_unique<GrpcPolledFdFactoryWindows>(combiner);
std::shared_ptr<WorkSerializer> work_serializer) {
return absl::make_unique<GrpcPolledFdFactoryWindows>(
std::move(work_serializer));
}
} // namespace grpc_core

@ -26,6 +26,8 @@
#include <string.h>
#include <sys/types.h>
#include "absl/container/inlined_vector.h"
#include <ares.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@ -38,7 +40,6 @@
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/iomgr/iomgr_internal.h"
@ -162,7 +163,7 @@ void grpc_ares_complete_request_locked(grpc_ares_request* r) {
}
static grpc_ares_hostbyname_request* create_hostbyname_request_locked(
grpc_ares_request* parent_request, char* host, uint16_t port,
grpc_ares_request* parent_request, const char* host, uint16_t port,
bool is_balancer) {
GRPC_CARES_TRACE_LOG(
"request:%p create_hostbyname_request_locked host:%s port:%d "
@ -201,7 +202,7 @@ static void on_hostbyname_done_locked(void* arg, int status, int /*timeouts*/,
}
ServerAddressList& addresses = **address_list_ptr;
for (size_t i = 0; hostent->h_addr_list[i] != nullptr; ++i) {
grpc_core::InlinedVector<grpc_arg, 1> args_to_add;
absl::InlinedVector<grpc_arg, 1> args_to_add;
if (hr->is_balancer) {
args_to_add.emplace_back(
grpc_core::CreateGrpclbBalancerNameArg(hr->host));
@ -360,30 +361,32 @@ done:
void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
grpc_ares_request* r, const char* dns_server, const char* name,
const char* default_port, grpc_pollset_set* interested_parties,
int query_timeout_ms, grpc_core::Combiner* combiner) {
int query_timeout_ms,
std::shared_ptr<grpc_core::WorkSerializer> work_serializer) {
grpc_error* error = GRPC_ERROR_NONE;
grpc_ares_hostbyname_request* hr = nullptr;
ares_channel* channel = nullptr;
/* parse name, splitting it into host and port parts */
grpc_core::UniquePtr<char> host;
grpc_core::UniquePtr<char> port;
std::string host;
std::string port;
grpc_core::SplitHostPort(name, &host, &port);
if (host == nullptr) {
if (host.empty()) {
error = grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
goto error_cleanup;
} else if (port == nullptr) {
} else if (port.empty()) {
if (default_port == nullptr) {
error = grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"),
GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
goto error_cleanup;
}
port.reset(gpr_strdup(default_port));
port = default_port;
}
error = grpc_ares_ev_driver_create_locked(&r->ev_driver, interested_parties,
query_timeout_ms, combiner, r);
query_timeout_ms,
std::move(work_serializer), r);
if (error != GRPC_ERROR_NONE) goto error_cleanup;
channel = grpc_ares_ev_driver_get_channel_locked(r->ev_driver);
// If dns_server is specified, use it.
@ -424,22 +427,22 @@ void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
}
r->pending_queries = 1;
if (grpc_ares_query_ipv6()) {
hr = create_hostbyname_request_locked(r, host.get(),
grpc_strhtons(port.get()),
hr = create_hostbyname_request_locked(r, host.c_str(),
grpc_strhtons(port.c_str()),
/*is_balancer=*/false);
ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked,
hr);
}
hr =
create_hostbyname_request_locked(r, host.get(), grpc_strhtons(port.get()),
/*is_balancer=*/false);
hr = create_hostbyname_request_locked(r, host.c_str(),
grpc_strhtons(port.c_str()),
/*is_balancer=*/false);
ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_locked,
hr);
if (r->balancer_addresses_out != nullptr) {
/* Query the SRV record */
grpc_ares_request_ref_locked(r);
char* service_name;
gpr_asprintf(&service_name, "_grpclb._tcp.%s", host.get());
gpr_asprintf(&service_name, "_grpclb._tcp.%s", host.c_str());
ares_query(*channel, service_name, ns_c_in, ns_t_srv,
on_srv_query_done_locked, r);
gpr_free(service_name);
@ -447,7 +450,7 @@ void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
if (r->service_config_json_out != nullptr) {
grpc_ares_request_ref_locked(r);
char* config_name;
gpr_asprintf(&config_name, "_grpc_config.%s", host.get());
gpr_asprintf(&config_name, "_grpc_config.%s", host.c_str());
ares_search(*channel, config_name, ns_c_in, ns_t_txt, on_txt_done_locked,
r);
gpr_free(config_name);
@ -462,18 +465,17 @@ error_cleanup:
static bool inner_resolve_as_ip_literal_locked(
const char* name, const char* default_port,
std::unique_ptr<grpc_core::ServerAddressList>* addrs,
grpc_core::UniquePtr<char>* host, grpc_core::UniquePtr<char>* port,
grpc_core::UniquePtr<char>* hostport) {
std::unique_ptr<grpc_core::ServerAddressList>* addrs, std::string* host,
std::string* port, std::string* hostport) {
grpc_core::SplitHostPort(name, host, port);
if (*host == nullptr) {
if (host->empty()) {
gpr_log(GPR_ERROR,
"Failed to parse %s to host:port while attempting to resolve as ip "
"literal.",
name);
return false;
}
if (*port == nullptr) {
if (port->empty()) {
if (default_port == nullptr) {
gpr_log(GPR_ERROR,
"No port or default port for %s while attempting to resolve as "
@ -481,13 +483,13 @@ static bool inner_resolve_as_ip_literal_locked(
name);
return false;
}
port->reset(gpr_strdup(default_port));
*port = default_port;
}
grpc_resolved_address addr;
GPR_ASSERT(grpc_core::JoinHostPort(hostport, host->get(), atoi(port->get())));
if (grpc_parse_ipv4_hostport(hostport->get(), &addr,
*hostport = grpc_core::JoinHostPort(*host, atoi(port->c_str()));
if (grpc_parse_ipv4_hostport(hostport->c_str(), &addr,
false /* log errors */) ||
grpc_parse_ipv6_hostport(hostport->get(), &addr,
grpc_parse_ipv6_hostport(hostport->c_str(), &addr,
false /* log errors */)) {
GPR_ASSERT(*addrs == nullptr);
*addrs = absl::make_unique<ServerAddressList>();
@ -500,22 +502,21 @@ static bool inner_resolve_as_ip_literal_locked(
static bool resolve_as_ip_literal_locked(
const char* name, const char* default_port,
std::unique_ptr<grpc_core::ServerAddressList>* addrs) {
grpc_core::UniquePtr<char> host;
grpc_core::UniquePtr<char> port;
grpc_core::UniquePtr<char> hostport;
std::string host;
std::string port;
std::string hostport;
bool out = inner_resolve_as_ip_literal_locked(name, default_port, addrs,
&host, &port, &hostport);
return out;
}
static bool target_matches_localhost_inner(const char* name,
grpc_core::UniquePtr<char>* host,
grpc_core::UniquePtr<char>* port) {
static bool target_matches_localhost_inner(const char* name, std::string* host,
std::string* port) {
if (!grpc_core::SplitHostPort(name, host, port)) {
gpr_log(GPR_ERROR, "Unable to split host and port for name: %s", name);
return false;
}
if (gpr_stricmp(host->get(), "localhost") == 0) {
if (gpr_stricmp(host->c_str(), "localhost") == 0) {
return true;
} else {
return false;
@ -523,25 +524,25 @@ static bool target_matches_localhost_inner(const char* name,
}
static bool target_matches_localhost(const char* name) {
grpc_core::UniquePtr<char> host;
grpc_core::UniquePtr<char> port;
std::string host;
std::string port;
return target_matches_localhost_inner(name, &host, &port);
}
#ifdef GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY
static bool inner_maybe_resolve_localhost_manually_locked(
const grpc_ares_request* r, const char* name, const char* default_port,
std::unique_ptr<grpc_core::ServerAddressList>* addrs,
grpc_core::UniquePtr<char>* host, grpc_core::UniquePtr<char>* port) {
std::unique_ptr<grpc_core::ServerAddressList>* addrs, std::string* host,
std::string* port) {
grpc_core::SplitHostPort(name, host, port);
if (*host == nullptr) {
if (host->empty()) {
gpr_log(GPR_ERROR,
"Failed to parse %s into host:port during manual localhost "
"resolution check.",
name);
return false;
}
if (*port == nullptr) {
if (port->empty()) {
if (default_port == nullptr) {
gpr_log(GPR_ERROR,
"No port or default port for %s during manual localhost "
@ -549,12 +550,12 @@ static bool inner_maybe_resolve_localhost_manually_locked(
name);
return false;
}
port->reset(gpr_strdup(default_port));
*port = default_port;
}
if (gpr_stricmp(host->get(), "localhost") == 0) {
if (gpr_stricmp(host->c_str(), "localhost") == 0) {
GPR_ASSERT(*addrs == nullptr);
*addrs = absl::make_unique<grpc_core::ServerAddressList>();
uint16_t numeric_port = grpc_strhtons(port->get());
uint16_t numeric_port = grpc_strhtons(port->c_str());
// Append the ipv6 loopback address.
struct sockaddr_in6 ipv6_loopback_addr;
memset(&ipv6_loopback_addr, 0, sizeof(ipv6_loopback_addr));
@ -582,8 +583,8 @@ static bool inner_maybe_resolve_localhost_manually_locked(
static bool grpc_ares_maybe_resolve_localhost_manually_locked(
const grpc_ares_request* r, const char* name, const char* default_port,
std::unique_ptr<grpc_core::ServerAddressList>* addrs) {
grpc_core::UniquePtr<char> host;
grpc_core::UniquePtr<char> port;
std::string host;
std::string port;
return inner_maybe_resolve_localhost_manually_locked(r, name, default_port,
addrs, &host, &port);
}
@ -602,7 +603,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
std::unique_ptr<grpc_core::ServerAddressList>* addrs,
std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs,
char** service_config_json, int query_timeout_ms,
grpc_core::Combiner* combiner) {
std::shared_ptr<grpc_core::WorkSerializer> work_serializer) {
grpc_ares_request* r =
static_cast<grpc_ares_request*>(gpr_zalloc(sizeof(grpc_ares_request)));
r->ev_driver = nullptr;
@ -637,7 +638,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
// Look up name using c-ares lib.
grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
r, dns_server, name, default_port, interested_parties, query_timeout_ms,
combiner);
std::move(work_serializer));
return r;
}
@ -647,7 +648,8 @@ grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
std::unique_ptr<grpc_core::ServerAddressList>* addrs,
std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs,
char** service_config_json, int query_timeout_ms,
grpc_core::Combiner* combiner) = grpc_dns_lookup_ares_locked_impl;
std::shared_ptr<grpc_core::WorkSerializer> work_serializer) =
grpc_dns_lookup_ares_locked_impl;
static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) {
GPR_ASSERT(r != nullptr);
@ -687,8 +689,8 @@ void grpc_ares_cleanup(void) {}
*/
typedef struct grpc_resolve_address_ares_request {
/* combiner that queries and related callbacks run under */
grpc_core::Combiner* combiner;
/* work_serializer that queries and related callbacks run under */
std::shared_ptr<grpc_core::WorkSerializer> work_serializer;
/** the pointer to receive the resolved addresses */
grpc_resolved_addresses** addrs_out;
/** currently resolving addresses */
@ -708,9 +710,8 @@ typedef struct grpc_resolve_address_ares_request {
grpc_ares_request* ares_request = nullptr;
} grpc_resolve_address_ares_request;
static void on_dns_lookup_done_locked(void* arg, grpc_error* error) {
grpc_resolve_address_ares_request* r =
static_cast<grpc_resolve_address_ares_request*>(arg);
static void on_dns_lookup_done_locked(grpc_resolve_address_ares_request* r,
grpc_error* error) {
gpr_free(r->ares_request);
grpc_resolved_addresses** resolved_addresses = r->addrs_out;
if (r->addresses == nullptr || r->addresses->empty()) {
@ -727,22 +728,19 @@ static void on_dns_lookup_done_locked(void* arg, grpc_error* error) {
sizeof(grpc_resolved_address));
}
}
grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_resolve_address_done,
GRPC_ERROR_REF(error));
GRPC_COMBINER_UNREF(r->combiner, "on_dns_lookup_done_cb");
grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_resolve_address_done, error);
delete r;
}
static void on_dns_lookup_done(void* arg, grpc_error* error) {
grpc_resolve_address_ares_request* r =
static_cast<grpc_resolve_address_ares_request*>(arg);
r->combiner->Run(GRPC_CLOSURE_INIT(&r->on_dns_lookup_done_locked,
on_dns_lookup_done_locked, r, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // ref owned by lambda
r->work_serializer->Run([r, error]() { on_dns_lookup_done_locked(r, error); },
DEBUG_LOCATION);
}
static void grpc_resolve_address_invoke_dns_lookup_ares_locked(
void* arg, grpc_error* /*unused_error*/) {
static void grpc_resolve_address_invoke_dns_lookup_ares_locked(void* arg) {
grpc_resolve_address_ares_request* r =
static_cast<grpc_resolve_address_ares_request*>(arg);
GRPC_CLOSURE_INIT(&r->on_dns_lookup_done_locked, on_dns_lookup_done, r,
@ -751,7 +749,7 @@ static void grpc_resolve_address_invoke_dns_lookup_ares_locked(
nullptr /* dns_server */, r->name, r->default_port, r->interested_parties,
&r->on_dns_lookup_done_locked, &r->addresses,
nullptr /* balancer_addresses */, nullptr /* service_config_json */,
GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS, r->combiner);
GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS, r->work_serializer);
}
static void grpc_resolve_address_ares_impl(const char* name,
@ -761,16 +759,15 @@ static void grpc_resolve_address_ares_impl(const char* name,
grpc_resolved_addresses** addrs) {
grpc_resolve_address_ares_request* r =
new grpc_resolve_address_ares_request();
r->combiner = grpc_combiner_create();
r->work_serializer = std::make_shared<grpc_core::WorkSerializer>();
r->addrs_out = addrs;
r->on_resolve_address_done = on_done;
r->name = name;
r->default_port = default_port;
r->interested_parties = interested_parties;
r->combiner->Run(
GRPC_CLOSURE_CREATE(grpc_resolve_address_invoke_dns_lookup_ares_locked, r,
nullptr),
GRPC_ERROR_NONE);
r->work_serializer->Run(
[r]() { grpc_resolve_address_invoke_dns_lookup_ares_locked(r); },
DEBUG_LOCATION);
}
void (*grpc_resolve_address_ares)(

@ -25,6 +25,7 @@
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/work_serializer.h"
#define GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS 120000
@ -66,7 +67,7 @@ extern grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
std::unique_ptr<grpc_core::ServerAddressList>* addresses,
std::unique_ptr<grpc_core::ServerAddressList>* balancer_addresses,
char** service_config_json, int query_timeout_ms,
grpc_core::Combiner* combiner);
std::shared_ptr<grpc_core::WorkSerializer> work_serializer);
/* Cancel the pending grpc_ares_request \a request */
extern void (*grpc_cancel_ares_request_locked)(grpc_ares_request* request);

@ -32,7 +32,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
std::unique_ptr<grpc_core::ServerAddressList>* addrs,
std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs,
char** service_config_json, int query_timeout_ms,
grpc_core::Combiner* combiner) {
std::shared_ptr<grpc_core::WorkSerializer> work_serializer) {
return NULL;
}
@ -42,7 +42,8 @@ grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
std::unique_ptr<grpc_core::ServerAddressList>* addrs,
std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs,
char** service_config_json, int query_timeout_ms,
grpc_core::Combiner* combiner) = grpc_dns_lookup_ares_locked_impl;
std::shared_ptr<grpc_core::WorkSerializer> work_serializer) =
grpc_dns_lookup_ares_locked_impl;
static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) {}

@ -33,9 +33,9 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/manual_constructor.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
#define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1
#define GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER 1.6
@ -67,9 +67,9 @@ class NativeDnsResolver : public Resolver {
void StartResolvingLocked();
static void OnNextResolution(void* arg, grpc_error* error);
static void OnNextResolutionLocked(void* arg, grpc_error* error);
void OnNextResolutionLocked(grpc_error* error);
static void OnResolved(void* arg, grpc_error* error);
static void OnResolvedLocked(void* arg, grpc_error* error);
void OnResolvedLocked(grpc_error* error);
/// name to resolve
char* name_to_resolve_ = nullptr;
@ -97,7 +97,7 @@ class NativeDnsResolver : public Resolver {
};
NativeDnsResolver::NativeDnsResolver(ResolverArgs args)
: Resolver(args.combiner, std::move(args.result_handler)),
: Resolver(std::move(args.work_serializer), std::move(args.result_handler)),
backoff_(
BackOff::Options()
.set_initial_backoff(GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS *
@ -149,79 +149,76 @@ void NativeDnsResolver::ShutdownLocked() {
void NativeDnsResolver::OnNextResolution(void* arg, grpc_error* error) {
NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg);
r->combiner()->Run(
GRPC_CLOSURE_INIT(&r->on_next_resolution_,
NativeDnsResolver::OnNextResolutionLocked, r, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // ref owned by lambda
r->work_serializer()->Run([r, error]() { r->OnNextResolutionLocked(error); },
DEBUG_LOCATION);
}
void NativeDnsResolver::OnNextResolutionLocked(void* arg, grpc_error* error) {
NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg);
r->have_next_resolution_timer_ = false;
if (error == GRPC_ERROR_NONE && !r->resolving_) {
r->StartResolvingLocked();
void NativeDnsResolver::OnNextResolutionLocked(grpc_error* error) {
have_next_resolution_timer_ = false;
if (error == GRPC_ERROR_NONE && !resolving_) {
StartResolvingLocked();
}
r->Unref(DEBUG_LOCATION, "retry-timer");
Unref(DEBUG_LOCATION, "retry-timer");
GRPC_ERROR_UNREF(error);
}
void NativeDnsResolver::OnResolved(void* arg, grpc_error* error) {
NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg);
r->combiner()->Run(
GRPC_CLOSURE_INIT(&r->on_resolved_, NativeDnsResolver::OnResolvedLocked,
r, nullptr),
GRPC_ERROR_REF(error));
GRPC_ERROR_REF(error); // owned by lambda
r->work_serializer()->Run([r, error]() { r->OnResolvedLocked(error); },
DEBUG_LOCATION);
}
void NativeDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg);
GPR_ASSERT(r->resolving_);
r->resolving_ = false;
if (r->shutdown_) {
r->Unref(DEBUG_LOCATION, "dns-resolving");
void NativeDnsResolver::OnResolvedLocked(grpc_error* error) {
GPR_ASSERT(resolving_);
resolving_ = false;
if (shutdown_) {
Unref(DEBUG_LOCATION, "dns-resolving");
GRPC_ERROR_UNREF(error);
return;
}
if (r->addresses_ != nullptr) {
if (addresses_ != nullptr) {
Result result;
for (size_t i = 0; i < r->addresses_->naddrs; ++i) {
result.addresses.emplace_back(&r->addresses_->addrs[i].addr,
r->addresses_->addrs[i].len,
for (size_t i = 0; i < addresses_->naddrs; ++i) {
result.addresses.emplace_back(&addresses_->addrs[i].addr,
addresses_->addrs[i].len,
nullptr /* args */);
}
grpc_resolved_addresses_destroy(r->addresses_);
result.args = grpc_channel_args_copy(r->channel_args_);
r->result_handler()->ReturnResult(std::move(result));
grpc_resolved_addresses_destroy(addresses_);
result.args = grpc_channel_args_copy(channel_args_);
result_handler()->ReturnResult(std::move(result));
// Reset backoff state so that we start from the beginning when the
// next request gets triggered.
r->backoff_.Reset();
backoff_.Reset();
} else {
gpr_log(GPR_INFO, "dns resolution failed (will retry): %s",
grpc_error_string(error));
// Return transient error.
r->result_handler()->ReturnError(grpc_error_set_int(
result_handler()->ReturnError(grpc_error_set_int(
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"DNS resolution failed", &error, 1),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
// Set up for retry.
grpc_millis next_try = r->backoff_.NextAttemptTime();
grpc_millis next_try = backoff_.NextAttemptTime();
grpc_millis timeout = next_try - ExecCtx::Get()->Now();
GPR_ASSERT(!r->have_next_resolution_timer_);
r->have_next_resolution_timer_ = true;
GPR_ASSERT(!have_next_resolution_timer_);
have_next_resolution_timer_ = true;
// TODO(roth): We currently deal with this ref manually. Once the
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
r->Ref(DEBUG_LOCATION, "next_resolution_timer").release();
Ref(DEBUG_LOCATION, "next_resolution_timer").release();
if (timeout > 0) {
gpr_log(GPR_DEBUG, "retrying in %" PRId64 " milliseconds", timeout);
} else {
gpr_log(GPR_DEBUG, "retrying immediately");
}
GRPC_CLOSURE_INIT(&r->on_next_resolution_,
NativeDnsResolver::OnNextResolution, r,
grpc_schedule_on_exec_ctx);
grpc_timer_init(&r->next_resolution_timer_, next_try,
&r->on_next_resolution_);
GRPC_CLOSURE_INIT(&on_next_resolution_, NativeDnsResolver::OnNextResolution,
this, grpc_schedule_on_exec_ctx);
grpc_timer_init(&next_resolution_timer_, next_try, &on_next_resolution_);
}
r->Unref(DEBUG_LOCATION, "dns-resolving");
Unref(DEBUG_LOCATION, "dns-resolving");
GRPC_ERROR_UNREF(error);
}
void NativeDnsResolver::MaybeStartResolvingLocked() {

@ -35,9 +35,9 @@
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/iomgr/work_serializer.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
@ -57,20 +57,15 @@ class FakeResolver : public Resolver {
private:
friend class FakeResolverResponseGenerator;
friend class FakeResolverResponseSetter;
virtual ~FakeResolver();
void ShutdownLocked() override {
shutdown_ = true;
if (response_generator_ != nullptr) {
response_generator_->SetFakeResolver(nullptr);
response_generator_.reset();
}
}
void ShutdownLocked() override;
void MaybeSendResultLocked();
static void ReturnReresolutionResult(void* arg, grpc_error* error);
void ReturnReresolutionResult();
// passed-in parameters
grpc_channel_args* channel_args_ = nullptr;
@ -90,12 +85,11 @@ class FakeResolver : public Resolver {
// if true, return failure
bool return_failure_ = false;
// pending re-resolution
grpc_closure reresolution_closure_;
bool reresolution_closure_pending_ = false;
};
FakeResolver::FakeResolver(ResolverArgs args)
: Resolver(args.combiner, std::move(args.result_handler)),
: Resolver(std::move(args.work_serializer), std::move(args.result_handler)),
response_generator_(
FakeResolverResponseGenerator::GetFromArgs(args.args)) {
// Channels sharing the same subchannels may have different resolver response
@ -127,13 +121,20 @@ void FakeResolver::RequestReresolutionLocked() {
if (!reresolution_closure_pending_) {
reresolution_closure_pending_ = true;
Ref().release(); // ref held by closure
GRPC_CLOSURE_INIT(&reresolution_closure_, ReturnReresolutionResult, this,
nullptr);
combiner()->Run(&reresolution_closure_, GRPC_ERROR_NONE);
work_serializer()->Run([this]() { ReturnReresolutionResult(); },
DEBUG_LOCATION);
}
}
}
void FakeResolver::ShutdownLocked() {
shutdown_ = true;
if (response_generator_ != nullptr) {
response_generator_->SetFakeResolver(nullptr);
response_generator_.reset();
}
}
void FakeResolver::MaybeSendResultLocked() {
if (!started_ || shutdown_) return;
if (return_failure_) {
@ -159,11 +160,59 @@ void FakeResolver::MaybeSendResultLocked() {
}
}
void FakeResolver::ReturnReresolutionResult(void* arg, grpc_error* /*error*/) {
FakeResolver* self = static_cast<FakeResolver*>(arg);
self->reresolution_closure_pending_ = false;
self->MaybeSendResultLocked();
self->Unref();
void FakeResolver::ReturnReresolutionResult() {
reresolution_closure_pending_ = false;
MaybeSendResultLocked();
Unref();
}
class FakeResolverResponseSetter {
public:
explicit FakeResolverResponseSetter(RefCountedPtr<FakeResolver> resolver,
Resolver::Result result,
bool has_result = false,
bool immediate = true)
: resolver_(std::move(resolver)),
result_(std::move(result)),
has_result_(has_result),
immediate_(immediate) {}
void SetResponseLocked();
void SetReresolutionResponseLocked();
void SetFailureLocked();
private:
RefCountedPtr<FakeResolver> resolver_;
Resolver::Result result_;
bool has_result_;
bool immediate_;
};
// Deletes object when done
void FakeResolverResponseSetter::SetReresolutionResponseLocked() {
if (!resolver_->shutdown_) {
resolver_->reresolution_result_ = std::move(result_);
resolver_->has_reresolution_result_ = has_result_;
}
delete this;
}
// Deletes object when done
void FakeResolverResponseSetter::SetResponseLocked() {
if (!resolver_->shutdown_) {
resolver_->next_result_ = std::move(result_);
resolver_->has_next_result_ = true;
resolver_->MaybeSendResultLocked();
}
delete this;
}
// Deletes object when done
void FakeResolverResponseSetter::SetFailureLocked() {
if (!resolver_->shutdown_) {
resolver_->return_failure_ = true;
if (immediate_) resolver_->MaybeSendResultLocked();
}
delete this;
}
//
@ -174,26 +223,6 @@ FakeResolverResponseGenerator::FakeResolverResponseGenerator() {}
FakeResolverResponseGenerator::~FakeResolverResponseGenerator() {}
struct SetResponseClosureArg {
grpc_closure set_response_closure;
RefCountedPtr<FakeResolver> resolver;
Resolver::Result result;
bool has_result = false;
bool immediate = true;
};
void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
grpc_error* /*error*/) {
SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
auto& resolver = closure_arg->resolver;
if (!resolver->shutdown_) {
resolver->next_result_ = std::move(closure_arg->result);
resolver->has_next_result_ = true;
resolver->MaybeSendResultLocked();
}
delete closure_arg;
}
void FakeResolverResponseGenerator::SetResponse(Resolver::Result result) {
RefCountedPtr<FakeResolver> resolver;
{
@ -205,24 +234,10 @@ void FakeResolverResponseGenerator::SetResponse(Resolver::Result result) {
}
resolver = resolver_->Ref();
}
SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
closure_arg->resolver = std::move(resolver);
closure_arg->result = std::move(result);
closure_arg->resolver->combiner()->Run(
GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
closure_arg, nullptr),
GRPC_ERROR_NONE);
}
void FakeResolverResponseGenerator::SetReresolutionResponseLocked(
void* arg, grpc_error* /*error*/) {
SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
auto& resolver = closure_arg->resolver;
if (!resolver->shutdown_) {
resolver->reresolution_result_ = std::move(closure_arg->result);
resolver->has_reresolution_result_ = closure_arg->has_result;
}
delete closure_arg;
FakeResolverResponseSetter* arg =
new FakeResolverResponseSetter(resolver, std::move(result));
resolver->work_serializer()->Run([arg]() { arg->SetResponseLocked(); },
DEBUG_LOCATION);
}
void FakeResolverResponseGenerator::SetReresolutionResponse(
@ -233,14 +248,10 @@ void FakeResolverResponseGenerator::SetReresolutionResponse(
GPR_ASSERT(resolver_ != nullptr);
resolver = resolver_->Ref();
}
SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
closure_arg->resolver = std::move(resolver);
closure_arg->result = std::move(result);
closure_arg->has_result = true;
closure_arg->resolver->combiner()->Run(
GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
SetReresolutionResponseLocked, closure_arg, nullptr),
GRPC_ERROR_NONE);
FakeResolverResponseSetter* arg = new FakeResolverResponseSetter(
resolver, std::move(result), true /* has_result */);
resolver->work_serializer()->Run(
[arg]() { arg->SetReresolutionResponseLocked(); }, DEBUG_LOCATION);
}
void FakeResolverResponseGenerator::UnsetReresolutionResponse() {
@ -250,23 +261,10 @@ void FakeResolverResponseGenerator::UnsetReresolutionResponse() {
GPR_ASSERT(resolver_ != nullptr);
resolver = resolver_->Ref();
}
SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
closure_arg->resolver = std::move(resolver);
closure_arg->resolver->combiner()->Run(
GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
SetReresolutionResponseLocked, closure_arg, nullptr),
GRPC_ERROR_NONE);
}
void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
grpc_error* /*error*/) {
SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
auto& resolver = closure_arg->resolver;
if (!resolver->shutdown_) {
resolver->return_failure_ = true;
if (closure_arg->immediate) resolver->MaybeSendResultLocked();
}
delete closure_arg;
FakeResolverResponseSetter* arg =
new FakeResolverResponseSetter(resolver, Resolver::Result());
resolver->work_serializer()->Run(
[arg]() { arg->SetReresolutionResponseLocked(); }, DEBUG_LOCATION);
}
void FakeResolverResponseGenerator::SetFailure() {
@ -276,12 +274,10 @@ void FakeResolverResponseGenerator::SetFailure() {
GPR_ASSERT(resolver_ != nullptr);
resolver = resolver_->Ref();
}
SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
closure_arg->resolver = std::move(resolver);
closure_arg->resolver->combiner()->Run(
GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
closure_arg, nullptr),
GRPC_ERROR_NONE);
FakeResolverResponseSetter* arg =
new FakeResolverResponseSetter(resolver, Resolver::Result());
resolver->work_serializer()->Run([arg]() { arg->SetFailureLocked(); },
DEBUG_LOCATION);
}
void FakeResolverResponseGenerator::SetFailureOnReresolution() {
@ -291,13 +287,11 @@ void FakeResolverResponseGenerator::SetFailureOnReresolution() {
GPR_ASSERT(resolver_ != nullptr);
resolver = resolver_->Ref();
}
SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
closure_arg->resolver = std::move(resolver);
closure_arg->immediate = false;
closure_arg->resolver->combiner()->Run(
GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
closure_arg, nullptr),
GRPC_ERROR_NONE);
FakeResolverResponseSetter* arg = new FakeResolverResponseSetter(
resolver, Resolver::Result(), false /* has_result */,
false /* immediate */);
resolver->work_serializer()->Run([arg]() { arg->SetFailureLocked(); },
DEBUG_LOCATION);
}
void FakeResolverResponseGenerator::SetFakeResolver(
@ -306,13 +300,10 @@ void FakeResolverResponseGenerator::SetFakeResolver(
resolver_ = std::move(resolver);
if (resolver_ == nullptr) return;
if (has_result_) {
SetResponseClosureArg* closure_arg = new SetResponseClosureArg();
closure_arg->resolver = resolver_->Ref();
closure_arg->result = std::move(result_);
resolver_->combiner()->Run(
GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
closure_arg, nullptr),
GRPC_ERROR_NONE);
FakeResolverResponseSetter* arg =
new FakeResolverResponseSetter(resolver_, std::move(result_));
resolver_->work_serializer()->Run([arg]() { arg->SetResponseLocked(); },
DEBUG_LOCATION);
has_result_ = false;
}
}

@ -80,10 +80,6 @@ class FakeResolverResponseGenerator
// Set the corresponding FakeResolver to this generator.
void SetFakeResolver(RefCountedPtr<FakeResolver> resolver);
static void SetResponseLocked(void* arg, grpc_error* error);
static void SetReresolutionResponseLocked(void* arg, grpc_error* error);
static void SetFailureLocked(void* arg, grpc_error* error);
// Mutex protecting the members below.
Mutex mu_;
RefCountedPtr<FakeResolver> resolver_;

@ -31,9 +31,9 @@
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/iomgr/work_serializer.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
@ -57,7 +57,7 @@ class SockaddrResolver : public Resolver {
SockaddrResolver::SockaddrResolver(ServerAddressList addresses,
ResolverArgs args)
: Resolver(args.combiner, std::move(args.result_handler)),
: Resolver(std::move(args.work_serializer), std::move(args.result_handler)),
addresses_(std::move(addresses)),
channel_args_(grpc_channel_args_copy(args.args)) {}

@ -20,7 +20,6 @@
#include "src/core/ext/filters/client_channel/resolver_registry.h"
#include "src/core/ext/filters/client_channel/xds/xds_client.h"
#include "src/core/lib/gprpp/string_view.h"
namespace grpc_core {
@ -35,7 +34,8 @@ namespace {
class XdsResolver : public Resolver {
public:
explicit XdsResolver(ResolverArgs args)
: Resolver(args.combiner, std::move(args.result_handler)),
: Resolver(std::move(args.work_serializer),
std::move(args.result_handler)),
args_(grpc_channel_args_copy(args.args)),
interested_parties_(args.pollset_set) {
char* path = args.uri->path;
@ -112,7 +112,7 @@ void XdsResolver::ServiceConfigWatcher::OnError(grpc_error* error) {
void XdsResolver::StartLocked() {
grpc_error* error = GRPC_ERROR_NONE;
xds_client_ = MakeOrphanable<XdsClient>(
combiner(), interested_parties_, server_name_,
work_serializer(), interested_parties_, server_name_,
absl::make_unique<ServiceConfigWatcher>(Ref()), *args_, &error);
if (error != GRPC_ERROR_NONE) {
gpr_log(GPR_ERROR,

@ -38,8 +38,8 @@ struct ResolverArgs {
const grpc_channel_args* args = nullptr;
/// Used to drive I/O in the name resolution process.
grpc_pollset_set* pollset_set = nullptr;
/// The combiner under which all resolver calls will be run.
Combiner* combiner = nullptr;
/// The work_serializer under which all resolver calls will be run.
std::shared_ptr<WorkSerializer> work_serializer;
/// The result handler to be used by the resolver.
std::unique_ptr<Resolver::ResultHandler> result_handler;
};

@ -22,6 +22,8 @@
#include <string.h>
#include "absl/container/inlined_vector.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
@ -90,7 +92,7 @@ class RegistryState {
// more factories are needed and the additional allocations are
// hurting performance (which is unlikely, since these allocations
// only occur at gRPC initialization time).
InlinedVector<std::unique_ptr<ResolverFactory>, 10> factories_;
absl::InlinedVector<std::unique_ptr<ResolverFactory>, 10> factories_;
grpc_core::UniquePtr<char> default_prefix_;
};
@ -145,7 +147,8 @@ bool ResolverRegistry::IsValidTarget(const char* target) {
OrphanablePtr<Resolver> ResolverRegistry::CreateResolver(
const char* target, const grpc_channel_args* args,
grpc_pollset_set* pollset_set, Combiner* combiner,
grpc_pollset_set* pollset_set,
std::shared_ptr<WorkSerializer> work_serializer,
std::unique_ptr<Resolver::ResultHandler> result_handler) {
GPR_ASSERT(g_state != nullptr);
grpc_uri* uri = nullptr;
@ -156,7 +159,7 @@ OrphanablePtr<Resolver> ResolverRegistry::CreateResolver(
resolver_args.uri = uri;
resolver_args.args = args;
resolver_args.pollset_set = pollset_set;
resolver_args.combiner = combiner;
resolver_args.work_serializer = std::move(work_serializer);
resolver_args.result_handler = std::move(result_handler);
OrphanablePtr<Resolver> resolver =
factory == nullptr ? nullptr

@ -22,7 +22,6 @@
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/resolver_factory.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/iomgr/pollset_set.h"
@ -61,15 +60,16 @@ class ResolverRegistry {
/// prepends default_prefix to target and tries again.
/// If a resolver factory is found, uses it to instantiate a resolver and
/// returns it; otherwise, returns nullptr.
/// \a args, \a pollset_set, and \a combiner are passed to the factory's
/// \a CreateResolver() method.
/// \a args are the channel args to be included in resolver results.
/// \a pollset_set is used to drive I/O in the name resolution process.
/// \a combiner is the combiner under which all resolver calls will be run.
/// \a result_handler is used to return results from the resolver.
/// \a args, \a pollset_set, and \a work_serializer are passed to the
/// factory's \a CreateResolver() method. \a args are the channel args to be
/// included in resolver results. \a pollset_set is used to drive I/O in the
/// name resolution process. \a work_serializer is the work_serializer under
/// which all resolver calls will be run. \a result_handler is used to return
/// results from the resolver.
static OrphanablePtr<Resolver> CreateResolver(
const char* target, const grpc_channel_args* args,
grpc_pollset_set* pollset_set, Combiner* combiner,
grpc_pollset_set* pollset_set,
std::shared_ptr<WorkSerializer> work_serializer,
std::unique_ptr<Resolver::ResultHandler> result_handler);
/// Returns the default authority to pass from a client for \a target.

@ -24,6 +24,8 @@
#include <stdio.h>
#include <string.h>
#include "absl/types/optional.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
@ -35,7 +37,6 @@
#include "src/core/lib/channel/status_util.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/optional.h"
#include "src/core/lib/uri/uri_parser.h"
// As per the retry design, we do not allow more than 5 retry attempts.
@ -318,7 +319,8 @@ ClientChannelServiceConfigParser::ParseGlobalParams(const Json& json,
std::vector<grpc_error*> error_list;
RefCountedPtr<LoadBalancingPolicy::Config> parsed_lb_config;
std::string lb_policy_name;
Optional<ClientChannelGlobalParsedConfig::RetryThrottling> retry_throttling;
absl::optional<ClientChannelGlobalParsedConfig::RetryThrottling>
retry_throttling;
const char* health_check_service_name = nullptr;
// Parse LB config.
auto it = json.object_value().find("loadBalancingConfig");
@ -396,7 +398,7 @@ ClientChannelServiceConfigParser::ParsePerMethodParams(const Json& json,
grpc_error** error) {
GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
std::vector<grpc_error*> error_list;
Optional<bool> wait_for_ready;
absl::optional<bool> wait_for_ready;
grpc_millis timeout = 0;
std::unique_ptr<ClientChannelMethodParsedConfig::RetryPolicy> retry_policy;
// Parse waitForReady.

@ -21,13 +21,14 @@
#include <grpc/support/port_platform.h>
#include "absl/types/optional.h"
#include "src/core/ext/filters/client_channel/lb_policy.h"
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include "src/core/ext/filters/client_channel/resolver.h"
#include "src/core/ext/filters/client_channel/retry_throttle.h"
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/lib/channel/status_util.h"
#include "src/core/lib/gprpp/optional.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/exec_ctx.h" // for grpc_millis
@ -47,14 +48,14 @@ class ClientChannelGlobalParsedConfig : public ServiceConfig::ParsedConfig {
ClientChannelGlobalParsedConfig(
RefCountedPtr<LoadBalancingPolicy::Config> parsed_lb_config,
std::string parsed_deprecated_lb_policy,
const Optional<RetryThrottling>& retry_throttling,
const absl::optional<RetryThrottling>& retry_throttling,
const char* health_check_service_name)
: parsed_lb_config_(std::move(parsed_lb_config)),
parsed_deprecated_lb_policy_(std::move(parsed_deprecated_lb_policy)),
retry_throttling_(retry_throttling),
health_check_service_name_(health_check_service_name) {}
Optional<RetryThrottling> retry_throttling() const {
absl::optional<RetryThrottling> retry_throttling() const {
return retry_throttling_;
}
@ -73,7 +74,7 @@ class ClientChannelGlobalParsedConfig : public ServiceConfig::ParsedConfig {
private:
RefCountedPtr<LoadBalancingPolicy::Config> parsed_lb_config_;
std::string parsed_deprecated_lb_policy_;
Optional<RetryThrottling> retry_throttling_;
absl::optional<RetryThrottling> retry_throttling_;
const char* health_check_service_name_;
};
@ -88,7 +89,7 @@ class ClientChannelMethodParsedConfig : public ServiceConfig::ParsedConfig {
};
ClientChannelMethodParsedConfig(grpc_millis timeout,
const Optional<bool>& wait_for_ready,
const absl::optional<bool>& wait_for_ready,
std::unique_ptr<RetryPolicy> retry_policy)
: timeout_(timeout),
wait_for_ready_(wait_for_ready),
@ -96,13 +97,13 @@ class ClientChannelMethodParsedConfig : public ServiceConfig::ParsedConfig {
grpc_millis timeout() const { return timeout_; }
Optional<bool> wait_for_ready() const { return wait_for_ready_; }
absl::optional<bool> wait_for_ready() const { return wait_for_ready_; }
const RetryPolicy* retry_policy() const { return retry_policy_.get(); }
private:
grpc_millis timeout_ = 0;
Optional<bool> wait_for_ready_;
absl::optional<bool> wait_for_ready_;
std::unique_ptr<RetryPolicy> retry_policy_;
};

@ -47,10 +47,8 @@
#include "src/core/lib/channel/connected_channel.h"
#include "src/core/lib/channel/status_util.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/manual_constructor.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/profiling/timers.h"
@ -128,7 +126,8 @@ class ResolvingLoadBalancingPolicy::ResolvingControlHelper
parent_->resolver_->RequestReresolutionLocked();
}
void AddTraceEvent(TraceSeverity severity, StringView message) override {
void AddTraceEvent(TraceSeverity severity,
absl::string_view message) override {
if (parent_->resolver_ == nullptr) return; // Shutting down.
parent_->channel_control_helper()->AddTraceEvent(severity, message);
}
@ -152,7 +151,7 @@ ResolvingLoadBalancingPolicy::ResolvingLoadBalancingPolicy(
process_resolver_result_user_data_(process_resolver_result_user_data) {
GPR_ASSERT(process_resolver_result != nullptr);
resolver_ = ResolverRegistry::CreateResolver(
target_uri_.get(), args.args, interested_parties(), combiner(),
target_uri_.get(), args.args, interested_parties(), work_serializer(),
absl::make_unique<ResolverResultHandler>(Ref()));
// Since the validity of args has been checked when create the channel,
// CreateResolver() must return a non-null result.
@ -247,7 +246,7 @@ OrphanablePtr<LoadBalancingPolicy>
ResolvingLoadBalancingPolicy::CreateLbPolicyLocked(
const grpc_channel_args& args) {
LoadBalancingPolicy::Args lb_policy_args;
lb_policy_args.combiner = combiner();
lb_policy_args.work_serializer = work_serializer();
lb_policy_args.channel_control_helper =
absl::make_unique<ResolvingControlHelper>(Ref());
lb_policy_args.args = &args;
@ -289,7 +288,7 @@ void ResolvingLoadBalancingPolicy::ConcatenateAndAddChannelTraceLocked(
size_t len = 0;
grpc_core::UniquePtr<char> message(gpr_strvec_flatten(&v, &len));
channel_control_helper()->AddTraceEvent(ChannelControlHelper::TRACE_INFO,
StringView(message.get()));
absl::string_view(message.get()));
gpr_strvec_destroy(&v);
}
}

@ -21,13 +21,14 @@
#include <grpc/support/port_platform.h>
#include "absl/container/inlined_vector.h"
#include "src/core/ext/filters/client_channel/lb_policy.h"
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include "src/core/ext/filters/client_channel/resolver.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/iomgr/call_combiner.h"
#include "src/core/lib/iomgr/closure.h"
@ -80,7 +81,7 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
void ResetBackoffLocked() override;
private:
using TraceStringVector = InlinedVector<char*, 3>;
using TraceStringVector = absl::InlinedVector<char*, 3>;
class ResolverResultHandler;
class ResolvingControlHelper;

@ -21,8 +21,9 @@
#include <grpc/support/port_platform.h>
#include "absl/container/inlined_vector.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/iomgr/resolve_address.h"
namespace grpc_core {
@ -82,7 +83,7 @@ class ServerAddress {
// ServerAddressList
//
typedef InlinedVector<ServerAddress, 1> ServerAddressList;
typedef absl::InlinedVector<ServerAddress, 1> ServerAddressList;
} // namespace grpc_core

@ -34,14 +34,14 @@
namespace grpc_core {
namespace {
typedef InlinedVector<std::unique_ptr<ServiceConfig::Parser>,
ServiceConfig::kNumPreallocatedParsers>
typedef absl::InlinedVector<std::unique_ptr<ServiceConfig::Parser>,
ServiceConfig::kNumPreallocatedParsers>
ServiceConfigParserList;
ServiceConfigParserList* g_registered_parsers;
} // namespace
RefCountedPtr<ServiceConfig> ServiceConfig::Create(StringView json_string,
grpc_error** error) {
RefCountedPtr<ServiceConfig> ServiceConfig::Create(
absl::string_view json_string, grpc_error** error) {
GPR_DEBUG_ASSERT(error != nullptr);
Json json = Json::Parse(json_string, error);
if (*error != GRPC_ERROR_NONE) return nullptr;
@ -100,7 +100,7 @@ grpc_error* ServiceConfig::ParseGlobalParams() {
grpc_error* ServiceConfig::ParseJsonMethodConfig(const Json& json) {
// Parse method config with each registered parser.
auto objs_vector = absl::make_unique<ParsedConfigVector>();
InlinedVector<grpc_error*, 4> error_list;
std::vector<grpc_error*> error_list;
for (size_t i = 0; i < g_registered_parsers->size(); i++) {
grpc_error* parser_error = GRPC_ERROR_NONE;
auto parsed_obj =

@ -21,10 +21,11 @@
#include <unordered_map>
#include "absl/container/inlined_vector.h"
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/error.h"
@ -89,7 +90,8 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
};
static constexpr int kNumPreallocatedParsers = 4;
typedef InlinedVector<std::unique_ptr<ParsedConfig>, kNumPreallocatedParsers>
typedef absl::InlinedVector<std::unique_ptr<ParsedConfig>,
kNumPreallocatedParsers>
ParsedConfigVector;
/// When a service config is applied to a call in the client_channel_filter,
@ -127,7 +129,7 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
/// Creates a new service config from parsing \a json_string.
/// Returns null on parse error.
static RefCountedPtr<ServiceConfig> Create(StringView json_string,
static RefCountedPtr<ServiceConfig> Create(absl::string_view json_string,
grpc_error** error);
ServiceConfig(std::string json_string, Json json, grpc_error** error);
@ -175,7 +177,7 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
std::string json_string_;
Json json_;
InlinedVector<std::unique_ptr<ParsedConfig>, kNumPreallocatedParsers>
absl::InlinedVector<std::unique_ptr<ParsedConfig>, kNumPreallocatedParsers>
parsed_global_configs_;
// A map from the method name to the parsed config vector. Note that we are
// using a raw pointer and not a unique pointer so that we can use the same
@ -186,7 +188,7 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
const ParsedConfigVector* default_method_config_vector_ = nullptr;
// Storage for all the vectors that are being used in
// parsed_method_configs_table_.
InlinedVector<std::unique_ptr<ParsedConfigVector>, 32>
absl::InlinedVector<std::unique_ptr<ParsedConfigVector>, 32>
parsed_method_config_vectors_storage_;
};

@ -362,12 +362,44 @@ class Subchannel::ConnectedSubchannelStateWatcher
Subchannel* subchannel_;
};
// Asynchronously notifies the \a watcher of a change in the connectvity state
// of \a subchannel to the current \a state. Deletes itself when done.
class Subchannel::AsyncWatcherNotifierLocked {
public:
AsyncWatcherNotifierLocked(
RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface> watcher,
Subchannel* subchannel, grpc_connectivity_state state)
: watcher_(std::move(watcher)) {
RefCountedPtr<ConnectedSubchannel> connected_subchannel;
if (state == GRPC_CHANNEL_READY) {
connected_subchannel = subchannel->connected_subchannel_;
}
watcher_->PushConnectivityStateChange(
{state, std::move(connected_subchannel)});
ExecCtx::Run(
DEBUG_LOCATION,
GRPC_CLOSURE_INIT(&closure_,
[](void* arg, grpc_error* /*error*/) {
auto* self =
static_cast<AsyncWatcherNotifierLocked*>(arg);
self->watcher_->OnConnectivityStateChange();
delete self;
},
this, nullptr),
GRPC_ERROR_NONE);
}
private:
RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface> watcher_;
grpc_closure closure_;
};
//
// Subchannel::ConnectivityStateWatcherList
//
void Subchannel::ConnectivityStateWatcherList::AddWatcherLocked(
OrphanablePtr<ConnectivityStateWatcherInterface> watcher) {
RefCountedPtr<ConnectivityStateWatcherInterface> watcher) {
watchers_.insert(std::make_pair(watcher.get(), std::move(watcher)));
}
@ -379,19 +411,7 @@ void Subchannel::ConnectivityStateWatcherList::RemoveWatcherLocked(
void Subchannel::ConnectivityStateWatcherList::NotifyLocked(
Subchannel* subchannel, grpc_connectivity_state state) {
for (const auto& p : watchers_) {
RefCountedPtr<ConnectedSubchannel> connected_subchannel;
if (state == GRPC_CHANNEL_READY) {
connected_subchannel = subchannel->connected_subchannel_;
}
// TODO(roth): In principle, it seems wrong to send this notification
// to the watcher while holding the subchannel's mutex, since it could
// lead to a deadlock if the watcher calls back into the subchannel
// before returning back to us. In practice, this doesn't happen,
// because the LB policy code that watches subchannels always bounces
// the notification into the client_channel control-plane combiner
// before processing it. But if we ever have any other callers here,
// we will probably need to change this.
p.second->OnConnectivityStateChange(state, std::move(connected_subchannel));
new AsyncWatcherNotifierLocked(p.second, subchannel, state);
}
}
@ -428,14 +448,9 @@ class Subchannel::HealthWatcherMap::HealthWatcher
void AddWatcherLocked(
grpc_connectivity_state initial_state,
OrphanablePtr<Subchannel::ConnectivityStateWatcherInterface> watcher) {
RefCountedPtr<Subchannel::ConnectivityStateWatcherInterface> watcher) {
if (state_ != initial_state) {
RefCountedPtr<ConnectedSubchannel> connected_subchannel;
if (state_ == GRPC_CHANNEL_READY) {
connected_subchannel = subchannel_->connected_subchannel_;
}
watcher->OnConnectivityStateChange(state_,
std::move(connected_subchannel));
new AsyncWatcherNotifierLocked(watcher, subchannel_, state_);
}
watcher_list_.AddWatcherLocked(std::move(watcher));
}
@ -503,7 +518,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
void Subchannel::HealthWatcherMap::AddWatcherLocked(
Subchannel* subchannel, grpc_connectivity_state initial_state,
grpc_core::UniquePtr<char> health_check_service_name,
OrphanablePtr<ConnectivityStateWatcherInterface> watcher) {
RefCountedPtr<ConnectivityStateWatcherInterface> watcher) {
// If the health check service name is not already present in the map,
// add it.
auto it = map_.find(health_check_service_name.get());
@ -613,6 +628,21 @@ BackOff::Options ParseArgsForBackoffValues(
} // namespace
void Subchannel::ConnectivityStateWatcherInterface::PushConnectivityStateChange(
ConnectivityStateChange state_change) {
MutexLock lock(&mu_);
connectivity_state_queue_.push_back(std::move(state_change));
}
Subchannel::ConnectivityStateWatcherInterface::ConnectivityStateChange
Subchannel::ConnectivityStateWatcherInterface::PopConnectivityStateChange() {
MutexLock lock(&mu_);
GPR_ASSERT(!connectivity_state_queue_.empty());
ConnectivityStateChange state_change = connectivity_state_queue_.front();
connectivity_state_queue_.pop_front();
return state_change;
}
Subchannel::Subchannel(SubchannelKey* key,
OrphanablePtr<SubchannelConnector> connector,
const grpc_channel_args* args)
@ -788,7 +818,7 @@ grpc_connectivity_state Subchannel::CheckConnectivityState(
void Subchannel::WatchConnectivityState(
grpc_connectivity_state initial_state,
grpc_core::UniquePtr<char> health_check_service_name,
OrphanablePtr<ConnectivityStateWatcherInterface> watcher) {
RefCountedPtr<ConnectivityStateWatcherInterface> watcher) {
MutexLock lock(&mu_);
grpc_pollset_set* interested_parties = watcher->interested_parties();
if (interested_parties != nullptr) {
@ -796,7 +826,7 @@ void Subchannel::WatchConnectivityState(
}
if (health_check_service_name == nullptr) {
if (state_ != initial_state) {
watcher->OnConnectivityStateChange(state_, connected_subchannel_);
new AsyncWatcherNotifierLocked(watcher, this, state_);
}
watcher_list_.AddWatcherLocked(std::move(watcher));
} else {

@ -21,6 +21,8 @@
#include <grpc/support/port_platform.h>
#include <deque>
#include "src/core/ext/filters/client_channel/client_channel_channelz.h"
#include "src/core/ext/filters/client_channel/connector.h"
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
@ -176,24 +178,44 @@ class SubchannelCall {
class Subchannel {
public:
class ConnectivityStateWatcherInterface
: public InternallyRefCounted<ConnectivityStateWatcherInterface> {
: public RefCounted<ConnectivityStateWatcherInterface> {
public:
struct ConnectivityStateChange {
grpc_connectivity_state state;
RefCountedPtr<ConnectedSubchannel> connected_subchannel;
};
virtual ~ConnectivityStateWatcherInterface() = default;
// Will be invoked whenever the subchannel's connectivity state
// changes. There will be only one invocation of this method on a
// given watcher instance at any given time.
//
// Implementations should call PopConnectivityStateChange to get the next
// connectivity state change.
virtual void OnConnectivityStateChange() = 0;
virtual grpc_pollset_set* interested_parties() = 0;
// Enqueues connectivity state change notifications.
// When the state changes to READY, connected_subchannel will
// contain a ref to the connected subchannel. When it changes from
// READY to some other state, the implementation must release its
// ref to the connected subchannel.
virtual void OnConnectivityStateChange(
grpc_connectivity_state new_state,
RefCountedPtr<ConnectedSubchannel> connected_subchannel) // NOLINT
= 0;
// TODO(yashkt): This is currently needed to send the state updates in the
// right order when asynchronously notifying. This will no longer be
// necessary when we have access to EventManager.
void PushConnectivityStateChange(ConnectivityStateChange state_change);
virtual grpc_pollset_set* interested_parties() = 0;
// Dequeues connectivity state change notifications.
ConnectivityStateChange PopConnectivityStateChange();
private:
// Keeps track of the updates that the watcher instance must be notified of.
// TODO(yashkt): This is currently needed to send the state updates in the
// right order when asynchronously notifying. This will no longer be
// necessary when we have access to EventManager.
std::deque<ConnectivityStateChange> connectivity_state_queue_;
Mutex mu_; // protects the queue
};
// The ctor and dtor are not intended to use directly.
@ -243,7 +265,7 @@ class Subchannel {
void WatchConnectivityState(
grpc_connectivity_state initial_state,
grpc_core::UniquePtr<char> health_check_service_name,
OrphanablePtr<ConnectivityStateWatcherInterface> watcher);
RefCountedPtr<ConnectivityStateWatcherInterface> watcher);
// Cancels a connectivity state watch.
// If the watcher has already been destroyed, this is a no-op.
@ -280,7 +302,7 @@ class Subchannel {
~ConnectivityStateWatcherList() { Clear(); }
void AddWatcherLocked(
OrphanablePtr<ConnectivityStateWatcherInterface> watcher);
RefCountedPtr<ConnectivityStateWatcherInterface> watcher);
void RemoveWatcherLocked(ConnectivityStateWatcherInterface* watcher);
// Notifies all watchers in the list about a change to state.
@ -294,7 +316,7 @@ class Subchannel {
// TODO(roth): Once we can use C++-14 heterogeneous lookups, this can
// be a set instead of a map.
std::map<ConnectivityStateWatcherInterface*,
OrphanablePtr<ConnectivityStateWatcherInterface>>
RefCountedPtr<ConnectivityStateWatcherInterface>>
watchers_;
};
@ -312,7 +334,7 @@ class Subchannel {
void AddWatcherLocked(
Subchannel* subchannel, grpc_connectivity_state initial_state,
grpc_core::UniquePtr<char> health_check_service_name,
OrphanablePtr<ConnectivityStateWatcherInterface> watcher);
RefCountedPtr<ConnectivityStateWatcherInterface> watcher);
void RemoveWatcherLocked(const char* health_check_service_name,
ConnectivityStateWatcherInterface* watcher);
@ -332,6 +354,8 @@ class Subchannel {
class ConnectedSubchannelStateWatcher;
class AsyncWatcherNotifierLocked;
// Sets the subchannel's connectivity state to \a state.
void SetConnectivityStateLocked(grpc_connectivity_state state);

@ -24,13 +24,14 @@
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
#include <grpc/impl/codegen/log.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/filters/client_channel/xds/xds_api.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
@ -514,10 +515,10 @@ grpc_slice XdsApi::CreateRdsRequest(const std::string& route_config_name,
return SerializeDiscoveryRequest(arena.ptr(), request);
}
grpc_slice XdsApi::CreateCdsRequest(const std::set<StringView>& cluster_names,
const std::string& version,
const std::string& nonce, grpc_error* error,
bool populate_node) {
grpc_slice XdsApi::CreateCdsRequest(
const std::set<absl::string_view>& cluster_names,
const std::string& version, const std::string& nonce, grpc_error* error,
bool populate_node) {
upb::Arena arena;
envoy_api_v2_DiscoveryRequest* request =
CreateDiscoveryRequest(arena.ptr(), kCdsTypeUrl, version, nonce, error);
@ -539,8 +540,9 @@ grpc_slice XdsApi::CreateCdsRequest(const std::set<StringView>& cluster_names,
}
grpc_slice XdsApi::CreateEdsRequest(
const std::set<StringView>& eds_service_names, const std::string& version,
const std::string& nonce, grpc_error* error, bool populate_node) {
const std::set<absl::string_view>& eds_service_names,
const std::string& version, const std::string& nonce, grpc_error* error,
bool populate_node) {
upb::Arena arena;
envoy_api_v2_DiscoveryRequest* request =
CreateDiscoveryRequest(arena.ptr(), kEdsTypeUrl, version, nonce, error);
@ -923,16 +925,18 @@ bool DomainMatch(MatchType match_type, std::string domain_pattern,
} else if (match_type == SUFFIX_MATCH) {
// Asterisk must match at least one char.
if (expected_host_name.size() < domain_pattern.size()) return false;
StringView pattern_suffix(domain_pattern.c_str() + 1);
StringView host_suffix(expected_host_name.c_str() +
expected_host_name.size() - pattern_suffix.size());
absl::string_view pattern_suffix(domain_pattern.c_str() + 1);
absl::string_view host_suffix(expected_host_name.c_str() +
expected_host_name.size() -
pattern_suffix.size());
return pattern_suffix == host_suffix;
} else if (match_type == PREFIX_MATCH) {
// Asterisk must match at least one char.
if (expected_host_name.size() < domain_pattern.size()) return false;
StringView pattern_prefix(domain_pattern.c_str(),
domain_pattern.size() - 1);
StringView host_prefix(expected_host_name.c_str(), pattern_prefix.size());
absl::string_view pattern_prefix(domain_pattern.c_str(),
domain_pattern.size() - 1);
absl::string_view host_prefix(expected_host_name.c_str(),
pattern_prefix.size());
return pattern_prefix == host_prefix;
} else {
return match_type == UNIVERSE_MATCH;
@ -951,7 +955,8 @@ MatchType DomainPatternMatchType(const std::string& domain_pattern) {
grpc_error* RouteConfigParse(
XdsClient* client, TraceFlag* tracer,
const envoy_api_v2_RouteConfiguration* route_config,
const std::string& expected_server_name, XdsApi::RdsUpdate* rds_update) {
const std::string& expected_server_name, const bool xds_routing_enabled,
XdsApi::RdsUpdate* rds_update) {
MaybeLogRouteConfiguration(client, tracer, route_config);
// Get the virtual hosts.
size_t size;
@ -1011,40 +1016,105 @@ grpc_error* RouteConfigParse(
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"No route found in the virtual host.");
}
// Only look at the last one in the route list (the default route),
const envoy_api_v2_route_Route* route = routes[size - 1];
// Validate that the match field must have a prefix field which is an empty
// string.
const envoy_api_v2_route_RouteMatch* match =
envoy_api_v2_route_Route_match(route);
if (!envoy_api_v2_route_RouteMatch_has_prefix(match)) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"No prefix field found in RouteMatch.");
}
const upb_strview prefix = envoy_api_v2_route_RouteMatch_prefix(match);
if (!upb_strview_eql(prefix, upb_strview_makez(""))) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Prefix is not empty string.");
}
if (!envoy_api_v2_route_Route_has_route(route)) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"No RouteAction found in route.");
// If xds_routing is not configured, only look at the last one in the route
// list (the default route)
size_t start_index = xds_routing_enabled ? 0 : size - 1;
for (size_t i = start_index; i < size; ++i) {
const envoy_api_v2_route_Route* route = routes[i];
const envoy_api_v2_route_RouteMatch* match =
envoy_api_v2_route_Route_match(route);
XdsApi::RdsRoute rds_route;
if (envoy_api_v2_route_RouteMatch_has_prefix(match)) {
upb_strview prefix = envoy_api_v2_route_RouteMatch_prefix(match);
// Empty prefix "" is accepted.
if (prefix.size > 0) {
// Prefix "/" is accepted.
if (prefix.data[0] != '/') {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Prefix does not start with a /");
}
if (prefix.size > 1) {
std::vector<absl::string_view> prefix_elements = absl::StrSplit(
absl::string_view(prefix.data, prefix.size).substr(1),
absl::MaxSplits('/', 1));
if (prefix_elements.size() != 2) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Prefix not in the required format of /service/");
} else if (!prefix_elements[1].empty()) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Prefix does not end with a /");
} else if (prefix_elements[0].empty()) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Prefix contains empty service name");
}
rds_route.service = std::string(prefix_elements[0]);
}
}
} else if (envoy_api_v2_route_RouteMatch_has_path(match)) {
upb_strview path = envoy_api_v2_route_RouteMatch_path(match);
if (path.size == 0) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Path if set cannot be empty");
}
if (path.data[0] != '/') {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Path does not start with a /");
}
std::vector<absl::string_view> path_elements = absl::StrSplit(
absl::string_view(path.data, path.size).substr(1), '/');
if (path_elements.size() != 2) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Path not in the required format of /service/method");
} else if (path_elements[0].empty()) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Path contains empty service name");
} else if (path_elements[1].empty()) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Path contains empty method name");
}
rds_route.service = std::string(path_elements[0]);
rds_route.method = std::string(path_elements[1]);
} else {
// TODO(donnadionne): We may change this behavior once we decide how to
// handle unsupported fields.
continue;
}
if (!envoy_api_v2_route_Route_has_route(route)) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"No RouteAction found in route.");
}
const envoy_api_v2_route_RouteAction* route_action =
envoy_api_v2_route_Route_route(route);
// Get the cluster in the RouteAction.
if (!envoy_api_v2_route_RouteAction_has_cluster(route_action)) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"No cluster found in RouteAction.");
}
const upb_strview action =
envoy_api_v2_route_RouteAction_cluster(route_action);
if (action.size == 0) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"RouteAction contains empty cluster.");
}
rds_route.cluster_name = std::string(action.data, action.size);
rds_update->routes.emplace_back(std::move(rds_route));
}
const envoy_api_v2_route_RouteAction* route_action =
envoy_api_v2_route_Route_route(route);
// Get the cluster in the RouteAction.
if (!envoy_api_v2_route_RouteAction_has_cluster(route_action)) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"No cluster found in RouteAction.");
if (rds_update->routes.empty()) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No valid routes specified.");
} else {
if (!rds_update->routes.back().service.empty() ||
!rds_update->routes.back().method.empty()) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Default route must have empty service and method");
}
}
const upb_strview cluster =
envoy_api_v2_route_RouteAction_cluster(route_action);
rds_update->cluster_name = std::string(cluster.data, cluster.size);
return GRPC_ERROR_NONE;
}
grpc_error* LdsResponseParse(XdsClient* client, TraceFlag* tracer,
const envoy_api_v2_DiscoveryResponse* response,
const std::string& expected_server_name,
const bool xds_routing_enabled,
absl::optional<XdsApi::LdsUpdate>* lds_update,
upb_arena* arena) {
// Get the resources from the response.
@ -1090,8 +1160,9 @@ grpc_error* LdsResponseParse(XdsClient* client, TraceFlag* tracer,
envoy_config_filter_network_http_connection_manager_v2_HttpConnectionManager_route_config(
http_connection_manager);
XdsApi::RdsUpdate rds_update;
grpc_error* error = RouteConfigParse(client, tracer, route_config,
expected_server_name, &rds_update);
grpc_error* error =
RouteConfigParse(client, tracer, route_config, expected_server_name,
xds_routing_enabled, &rds_update);
if (error != GRPC_ERROR_NONE) return error;
lds_update->emplace();
(*lds_update)->rds_update.emplace(std::move(rds_update));
@ -1122,6 +1193,7 @@ grpc_error* RdsResponseParse(XdsClient* client, TraceFlag* tracer,
const envoy_api_v2_DiscoveryResponse* response,
const std::string& expected_server_name,
const std::string& expected_route_config_name,
const bool xds_routing_enabled,
absl::optional<XdsApi::RdsUpdate>* rds_update,
upb_arena* arena) {
// Get the resources from the response.
@ -1150,8 +1222,9 @@ grpc_error* RdsResponseParse(XdsClient* client, TraceFlag* tracer,
if (!upb_strview_eql(name, expected_name)) continue;
// Parse the route_config.
XdsApi::RdsUpdate local_rds_update;
grpc_error* error = RouteConfigParse(
client, tracer, route_config, expected_server_name, &local_rds_update);
grpc_error* error =
RouteConfigParse(client, tracer, route_config, expected_server_name,
xds_routing_enabled, &local_rds_update);
if (error != GRPC_ERROR_NONE) return error;
rds_update->emplace(std::move(local_rds_update));
return GRPC_ERROR_NONE;
@ -1159,11 +1232,11 @@ grpc_error* RdsResponseParse(XdsClient* client, TraceFlag* tracer,
return GRPC_ERROR_NONE;
}
grpc_error* CdsResponseParse(XdsClient* client, TraceFlag* tracer,
const envoy_api_v2_DiscoveryResponse* response,
const std::set<StringView>& expected_cluster_names,
XdsApi::CdsUpdateMap* cds_update_map,
upb_arena* arena) {
grpc_error* CdsResponseParse(
XdsClient* client, TraceFlag* tracer,
const envoy_api_v2_DiscoveryResponse* response,
const std::set<absl::string_view>& expected_cluster_names,
XdsApi::CdsUpdateMap* cds_update_map, upb_arena* arena) {
// Get the resources from the response.
size_t size;
const google_protobuf_Any* const* resources =
@ -1186,7 +1259,8 @@ grpc_error* CdsResponseParse(XdsClient* client, TraceFlag* tracer,
MaybeLogCluster(client, tracer, cluster);
// Ignore unexpected cluster names.
upb_strview cluster_name = envoy_api_v2_Cluster_name(cluster);
StringView cluster_name_strview(cluster_name.data, cluster_name.size);
absl::string_view cluster_name_strview(cluster_name.data,
cluster_name.size);
if (expected_cluster_names.find(cluster_name_strview) ==
expected_cluster_names.end()) {
continue;
@ -1349,7 +1423,7 @@ grpc_error* DropParseAndAppend(
grpc_error* EdsResponseParse(
XdsClient* client, TraceFlag* tracer,
const envoy_api_v2_DiscoveryResponse* response,
const std::set<StringView>& expected_eds_service_names,
const std::set<absl::string_view>& expected_eds_service_names,
XdsApi::EdsUpdateMap* eds_update_map, upb_arena* arena) {
// Get the resources from the response.
size_t size;
@ -1378,7 +1452,8 @@ grpc_error* EdsResponseParse(
// unexpected names.
upb_strview cluster_name = envoy_api_v2_ClusterLoadAssignment_cluster_name(
cluster_load_assignment);
StringView cluster_name_strview(cluster_name.data, cluster_name.size);
absl::string_view cluster_name_strview(cluster_name.data,
cluster_name.size);
if (expected_eds_service_names.find(cluster_name_strview) ==
expected_eds_service_names.end()) {
continue;
@ -1431,8 +1506,9 @@ grpc_error* EdsResponseParse(
grpc_error* XdsApi::ParseAdsResponse(
const grpc_slice& encoded_response, const std::string& expected_server_name,
const std::string& expected_route_config_name,
const std::set<StringView>& expected_cluster_names,
const std::set<StringView>& expected_eds_service_names,
const bool xds_routing_enabled,
const std::set<absl::string_view>& expected_cluster_names,
const std::set<absl::string_view>& expected_eds_service_names,
absl::optional<LdsUpdate>* lds_update,
absl::optional<RdsUpdate>* rds_update, CdsUpdateMap* cds_update_map,
EdsUpdateMap* eds_update_map, std::string* version, std::string* nonce,
@ -1462,11 +1538,11 @@ grpc_error* XdsApi::ParseAdsResponse(
// Parse the response according to the resource type.
if (*type_url == kLdsTypeUrl) {
return LdsResponseParse(client_, tracer_, response, expected_server_name,
lds_update, arena.ptr());
xds_routing_enabled, lds_update, arena.ptr());
} else if (*type_url == kRdsTypeUrl) {
return RdsResponseParse(client_, tracer_, response, expected_server_name,
expected_route_config_name, rds_update,
arena.ptr());
expected_route_config_name, xds_routing_enabled,
rds_update, arena.ptr());
} else if (*type_url == kCdsTypeUrl) {
return CdsResponseParse(client_, tracer_, response, expected_cluster_names,
cds_update_map, arena.ptr());

@ -25,6 +25,7 @@
#include <set>
#include "absl/container/inlined_vector.h"
#include "absl/types/optional.h"
#include <grpc/slice_buffer.h>
@ -44,12 +45,22 @@ class XdsApi {
static const char* kCdsTypeUrl;
static const char* kEdsTypeUrl;
struct RdsUpdate {
// The name to use in the CDS request.
struct RdsRoute {
std::string service;
std::string method;
std::string cluster_name;
bool operator==(const RdsRoute& other) const {
return (service == other.service && method == other.method &&
cluster_name == other.cluster_name);
}
};
struct RdsUpdate {
std::vector<RdsRoute> routes;
bool operator==(const RdsUpdate& other) const {
return cluster_name == other.cluster_name;
return routes == other.routes;
}
};
@ -140,7 +151,7 @@ class XdsApi {
}
private:
InlinedVector<LocalityMap, 2> priorities_;
absl::InlinedVector<LocalityMap, 2> priorities_;
};
// There are two phases of accessing this class's content:
@ -159,7 +170,7 @@ class XdsApi {
const uint32_t parts_per_million;
};
using DropCategoryList = InlinedVector<DropCategory, 2>;
using DropCategoryList = absl::InlinedVector<DropCategory, 2>;
void AddCategory(std::string name, uint32_t parts_per_million) {
drop_category_list_.emplace_back(
@ -228,17 +239,17 @@ class XdsApi {
// Creates a CDS request querying \a cluster_names.
// Takes ownership of \a error.
grpc_slice CreateCdsRequest(const std::set<StringView>& cluster_names,
grpc_slice CreateCdsRequest(const std::set<absl::string_view>& cluster_names,
const std::string& version,
const std::string& nonce, grpc_error* error,
bool populate_node);
// Creates an EDS request querying \a eds_service_names.
// Takes ownership of \a error.
grpc_slice CreateEdsRequest(const std::set<StringView>& eds_service_names,
const std::string& version,
const std::string& nonce, grpc_error* error,
bool populate_node);
grpc_slice CreateEdsRequest(
const std::set<absl::string_view>& eds_service_names,
const std::string& version, const std::string& nonce, grpc_error* error,
bool populate_node);
// Parses the ADS response and outputs the validated update for either CDS or
// EDS. If the response can't be parsed at the top level, \a type_url will
@ -247,8 +258,9 @@ class XdsApi {
const grpc_slice& encoded_response,
const std::string& expected_server_name,
const std::string& expected_route_config_name,
const std::set<StringView>& expected_cluster_names,
const std::set<StringView>& expected_eds_service_names,
const bool xds_routing_enabled,
const std::set<absl::string_view>& expected_cluster_names,
const std::set<absl::string_view>& expected_eds_service_names,
absl::optional<LdsUpdate>* lds_update,
absl::optional<RdsUpdate>* rds_update, CdsUpdateMap* cds_update_map,
EdsUpdateMap* eds_update_map, std::string* version, std::string* nonce,

@ -18,12 +18,17 @@
#include "src/core/ext/filters/client_channel/xds/xds_bootstrap.h"
#include <vector>
#include <errno.h>
#include <stdlib.h>
#include "absl/strings/string_view.h"
#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/env.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/slice/slice_internal.h"
@ -94,11 +99,10 @@ std::unique_ptr<XdsBootstrap> XdsBootstrap::ReadFromFile(XdsClient* client,
grpc_slice contents;
*error = grpc_load_file(path.get(), /*add_null_terminator=*/true, &contents);
if (*error != GRPC_ERROR_NONE) return nullptr;
StringView contents_str_view = StringViewFromSlice(contents);
absl::string_view contents_str_view = StringViewFromSlice(contents);
if (GRPC_TRACE_FLAG_ENABLED(*tracer)) {
UniquePtr<char> str = StringViewToCString(contents_str_view);
gpr_log(GPR_DEBUG, "[xds_client %p] Bootstrap file contents: %s", client,
str.get());
std::string(contents_str_view).c_str());
}
Json json = Json::Parse(contents_str_view, error);
grpc_slice_unref_internal(contents);
@ -128,7 +132,7 @@ XdsBootstrap::XdsBootstrap(Json json, grpc_error** error) {
"malformed JSON in bootstrap file");
return;
}
InlinedVector<grpc_error*, 1> error_list;
std::vector<grpc_error*> error_list;
auto it = json.mutable_object()->find("xds_servers");
if (it == json.mutable_object()->end()) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
@ -155,7 +159,7 @@ XdsBootstrap::XdsBootstrap(Json json, grpc_error** error) {
}
grpc_error* XdsBootstrap::ParseXdsServerList(Json* json) {
InlinedVector<grpc_error*, 1> error_list;
std::vector<grpc_error*> error_list;
for (size_t i = 0; i < json->mutable_array()->size(); ++i) {
Json& child = json->mutable_array()->at(i);
if (child.type() != Json::Type::OBJECT) {
@ -173,7 +177,7 @@ grpc_error* XdsBootstrap::ParseXdsServerList(Json* json) {
}
grpc_error* XdsBootstrap::ParseXdsServer(Json* json, size_t idx) {
InlinedVector<grpc_error*, 1> error_list;
std::vector<grpc_error*> error_list;
servers_.emplace_back();
XdsServer& server = servers_[servers_.size() - 1];
auto it = json->mutable_object()->find("server_uri");
@ -211,7 +215,7 @@ grpc_error* XdsBootstrap::ParseXdsServer(Json* json, size_t idx) {
grpc_error* XdsBootstrap::ParseChannelCredsArray(Json* json,
XdsServer* server) {
InlinedVector<grpc_error*, 1> error_list;
std::vector<grpc_error*> error_list;
for (size_t i = 0; i < json->mutable_array()->size(); ++i) {
Json& child = json->mutable_array()->at(i);
if (child.type() != Json::Type::OBJECT) {
@ -230,7 +234,7 @@ grpc_error* XdsBootstrap::ParseChannelCredsArray(Json* json,
grpc_error* XdsBootstrap::ParseChannelCreds(Json* json, size_t idx,
XdsServer* server) {
InlinedVector<grpc_error*, 1> error_list;
std::vector<grpc_error*> error_list;
ChannelCreds channel_creds;
auto it = json->mutable_object()->find("type");
if (it == json->mutable_object()->end()) {
@ -268,7 +272,7 @@ grpc_error* XdsBootstrap::ParseChannelCreds(Json* json, size_t idx,
}
grpc_error* XdsBootstrap::ParseNode(Json* json) {
InlinedVector<grpc_error*, 1> error_list;
std::vector<grpc_error*> error_list;
node_ = absl::make_unique<Node>();
auto it = json->mutable_object()->find("id");
if (it != json->mutable_object()->end()) {
@ -312,7 +316,7 @@ grpc_error* XdsBootstrap::ParseNode(Json* json) {
}
grpc_error* XdsBootstrap::ParseLocality(Json* json) {
InlinedVector<grpc_error*, 1> error_list;
std::vector<grpc_error*> error_list;
auto it = json->mutable_object()->find("region");
if (it != json->mutable_object()->end()) {
if (it->second.type() != Json::Type::STRING) {

@ -23,9 +23,10 @@
#include <string>
#include <vector>
#include "absl/container/inlined_vector.h"
#include <grpc/impl/codegen/slice.h>
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/map.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/error.h"
@ -53,7 +54,7 @@ class XdsBootstrap {
struct XdsServer {
std::string server_uri;
InlinedVector<ChannelCreds, 1> channel_creds;
absl::InlinedVector<ChannelCreds, 1> channel_creds;
};
// If *error is not GRPC_ERROR_NONE after returning, then there was an
@ -78,7 +79,7 @@ class XdsBootstrap {
grpc_error* ParseNode(Json* json);
grpc_error* ParseLocality(Json* json);
InlinedVector<XdsServer, 1> servers_;
absl::InlinedVector<XdsServer, 1> servers_;
std::unique_ptr<Node> node_;
};

@ -22,6 +22,8 @@
#include <string.h>
#include "absl/container/inlined_vector.h"
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
@ -39,8 +41,8 @@
namespace grpc_core {
grpc_channel_args* ModifyXdsChannelArgs(grpc_channel_args* args) {
InlinedVector<const char*, 1> args_to_remove;
InlinedVector<grpc_arg, 2> args_to_add;
absl::InlinedVector<const char*, 1> args_to_remove;
absl::InlinedVector<grpc_arg, 2> args_to_add;
// Substitute the channel credentials with a version without call
// credentials: the load balancer is not necessarily trusted to handle
// bearer token credentials.

File diff suppressed because it is too large Load Diff

@ -21,6 +21,7 @@
#include <set>
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "src/core/ext/filters/client_channel/service_config.h"
@ -32,8 +33,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/string_view.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/work_serializer.h"
namespace grpc_core {
@ -74,8 +74,8 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
// If *error is not GRPC_ERROR_NONE after construction, then there was
// an error initializing the client.
XdsClient(Combiner* combiner, grpc_pollset_set* interested_parties,
StringView server_name,
XdsClient(std::shared_ptr<WorkSerializer> work_serializer,
grpc_pollset_set* interested_parties, absl::string_view server_name,
std::unique_ptr<ServiceConfigWatcherInterface> watcher,
const grpc_channel_args& channel_args, grpc_error** error);
~XdsClient();
@ -89,9 +89,9 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
// pointer must not be used for any other purpose.)
// If the caller is going to start a new watch after cancelling the
// old one, it should set delay_unsubscription to true.
void WatchClusterData(StringView cluster_name,
void WatchClusterData(absl::string_view cluster_name,
std::unique_ptr<ClusterWatcherInterface> watcher);
void CancelClusterDataWatch(StringView cluster_name,
void CancelClusterDataWatch(absl::string_view cluster_name,
ClusterWatcherInterface* watcher,
bool delay_unsubscription = false);
@ -102,29 +102,30 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
// pointer must not be used for any other purpose.)
// If the caller is going to start a new watch after cancelling the
// old one, it should set delay_unsubscription to true.
void WatchEndpointData(StringView eds_service_name,
void WatchEndpointData(absl::string_view eds_service_name,
std::unique_ptr<EndpointWatcherInterface> watcher);
void CancelEndpointDataWatch(StringView eds_service_name,
void CancelEndpointDataWatch(absl::string_view eds_service_name,
EndpointWatcherInterface* watcher,
bool delay_unsubscription = false);
// Adds and removes drop stats for cluster_name and eds_service_name.
RefCountedPtr<XdsClusterDropStats> AddClusterDropStats(
StringView lrs_server, StringView cluster_name,
StringView eds_service_name);
void RemoveClusterDropStats(StringView /*lrs_server*/,
StringView cluster_name,
StringView eds_service_name,
absl::string_view lrs_server, absl::string_view cluster_name,
absl::string_view eds_service_name);
void RemoveClusterDropStats(absl::string_view /*lrs_server*/,
absl::string_view cluster_name,
absl::string_view eds_service_name,
XdsClusterDropStats* cluster_drop_stats);
// Adds and removes locality stats for cluster_name and eds_service_name
// for the specified locality.
RefCountedPtr<XdsClusterLocalityStats> AddClusterLocalityStats(
StringView lrs_server, StringView cluster_name,
StringView eds_service_name, RefCountedPtr<XdsLocalityName> locality);
absl::string_view lrs_server, absl::string_view cluster_name,
absl::string_view eds_service_name,
RefCountedPtr<XdsLocalityName> locality);
void RemoveClusterLocalityStats(
StringView /*lrs_server*/, StringView cluster_name,
StringView eds_service_name,
absl::string_view /*lrs_server*/, absl::string_view cluster_name,
absl::string_view eds_service_name,
const RefCountedPtr<XdsLocalityName>& locality,
XdsClusterLocalityStats* cluster_locality_stats);
@ -226,7 +227,7 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
void NotifyOnError(grpc_error* error);
grpc_error* CreateServiceConfig(
const std::string& cluster_name,
const XdsApi::RdsUpdate& rds_update,
RefCountedPtr<ServiceConfig>* service_config) const;
XdsApi::ClusterLoadReportMap BuildLoadReportSnapshot(
@ -241,7 +242,9 @@ class XdsClient : public InternallyRefCounted<XdsClient> {
const grpc_millis request_timeout_;
Combiner* combiner_;
const bool xds_routing_enabled_;
std::shared_ptr<WorkSerializer> work_serializer_;
grpc_pollset_set* interested_parties_;
std::unique_ptr<XdsBootstrap> bootstrap_;

@ -34,9 +34,9 @@ namespace grpc_core {
//
XdsClusterDropStats::XdsClusterDropStats(RefCountedPtr<XdsClient> xds_client,
StringView lrs_server_name,
StringView cluster_name,
StringView eds_service_name)
absl::string_view lrs_server_name,
absl::string_view cluster_name,
absl::string_view eds_service_name)
: xds_client_(std::move(xds_client)),
lrs_server_name_(lrs_server_name),
cluster_name_(cluster_name),
@ -64,8 +64,8 @@ void XdsClusterDropStats::AddCallDropped(const std::string& category) {
//
XdsClusterLocalityStats::XdsClusterLocalityStats(
RefCountedPtr<XdsClient> xds_client, StringView lrs_server_name,
StringView cluster_name, StringView eds_service_name,
RefCountedPtr<XdsClient> xds_client, absl::string_view lrs_server_name,
absl::string_view cluster_name, absl::string_view eds_service_name,
RefCountedPtr<XdsLocalityName> name)
: xds_client_(std::move(xds_client)),
lrs_server_name_(lrs_server_name),

@ -24,7 +24,6 @@
#include <grpc/support/string_util.h>
#include "src/core/lib/gprpp/atomic.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/map.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/ref_counted.h"
@ -100,8 +99,9 @@ class XdsClusterDropStats : public RefCounted<XdsClusterDropStats> {
using DroppedRequestsMap = std::map<std::string /* category */, uint64_t>;
XdsClusterDropStats(RefCountedPtr<XdsClient> xds_client,
StringView lrs_server_name, StringView cluster_name,
StringView eds_service_name);
absl::string_view lrs_server_name,
absl::string_view cluster_name,
absl::string_view eds_service_name);
~XdsClusterDropStats();
// Returns a snapshot of this instance and resets all the counters.
@ -111,9 +111,9 @@ class XdsClusterDropStats : public RefCounted<XdsClusterDropStats> {
private:
RefCountedPtr<XdsClient> xds_client_;
StringView lrs_server_name_;
StringView cluster_name_;
StringView eds_service_name_;
absl::string_view lrs_server_name_;
absl::string_view cluster_name_;
absl::string_view eds_service_name_;
// Protects dropped_requests_. A mutex is necessary because the length of
// dropped_requests_ can be accessed by both the picker (from data plane
// mutex) and the load reporting thread (from the control plane combiner).
@ -171,8 +171,9 @@ class XdsClusterLocalityStats : public RefCounted<XdsClusterLocalityStats> {
};
XdsClusterLocalityStats(RefCountedPtr<XdsClient> xds_client,
StringView lrs_server_name, StringView cluster_name,
StringView eds_service_name,
absl::string_view lrs_server_name,
absl::string_view cluster_name,
absl::string_view eds_service_name,
RefCountedPtr<XdsLocalityName> name);
~XdsClusterLocalityStats();
@ -184,9 +185,9 @@ class XdsClusterLocalityStats : public RefCounted<XdsClusterLocalityStats> {
private:
RefCountedPtr<XdsClient> xds_client_;
StringView lrs_server_name_;
StringView cluster_name_;
StringView eds_service_name_;
absl::string_view lrs_server_name_;
absl::string_view cluster_name_;
absl::string_view eds_service_name_;
RefCountedPtr<XdsLocalityName> name_;
Atomic<uint64_t> total_successful_requests_{0};
@ -196,8 +197,8 @@ class XdsClusterLocalityStats : public RefCounted<XdsClusterLocalityStats> {
// 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 combiner) and
// the load reporting thread (from the control plane combiner).
// 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<std::string, BackendMetric> backend_metrics_;
};

@ -538,9 +538,8 @@ static grpc_core::ManagedMemorySlice user_agent_from_args(
}
}
gpr_asprintf(&tmp, "%sgrpc-c/%s (%s; %s; %s)", is_first ? "" : " ",
grpc_version_string(), GPR_PLATFORM_STRING, transport_name,
grpc_g_stands_for());
gpr_asprintf(&tmp, "%sgrpc-c/%s (%s; %s)", is_first ? "" : " ",
grpc_version_string(), GPR_PLATFORM_STRING, transport_name);
is_first = 0;
gpr_strvec_add(&v, tmp);

@ -22,6 +22,7 @@
#include "src/core/ext/filters/http/client/http_client_filter.h"
#include "src/core/ext/filters/http/message_compress/message_compress_filter.h"
#include "src/core/ext/filters/http/message_compress/message_decompress_filter.h"
#include "src/core/ext/filters/http/server/http_server_filter.h"
#include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/surface/call.h"
@ -36,12 +37,16 @@ typedef struct {
static optional_filter compress_filter = {
&grpc_message_compress_filter, GRPC_ARG_ENABLE_PER_MESSAGE_COMPRESSION};
static optional_filter decompress_filter = {
&grpc_message_decompress_filter, GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION};
static bool is_building_http_like_transport(
grpc_channel_stack_builder* builder) {
grpc_transport* t = grpc_channel_stack_builder_get_transport(builder);
return t != nullptr && strstr(t->vtable->name, "http");
}
template <bool enable_in_minimal_stack>
static bool maybe_add_optional_filter(grpc_channel_stack_builder* builder,
void* arg) {
if (!is_building_http_like_transport(builder)) return true;
@ -50,7 +55,8 @@ static bool maybe_add_optional_filter(grpc_channel_stack_builder* builder,
grpc_channel_stack_builder_get_channel_arguments(builder);
bool enable = grpc_channel_arg_get_bool(
grpc_channel_args_find(channel_args, filtarg->control_channel_arg),
!grpc_channel_args_want_minimal_stack(channel_args));
enable_in_minimal_stack ||
!grpc_channel_args_want_minimal_stack(channel_args));
return enable ? grpc_channel_stack_builder_prepend_filter(
builder, filtarg->filter, nullptr, nullptr)
: true;
@ -66,15 +72,24 @@ static bool maybe_add_required_filter(grpc_channel_stack_builder* builder,
}
void grpc_http_filters_init(void) {
grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
maybe_add_optional_filter, &compress_filter);
grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL,
GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
maybe_add_optional_filter, &compress_filter);
grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
maybe_add_optional_filter, &compress_filter);
grpc_channel_init_register_stage(
GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
maybe_add_optional_filter<false>, &compress_filter);
grpc_channel_init_register_stage(
GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
maybe_add_optional_filter<false>, &compress_filter);
grpc_channel_init_register_stage(
GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
maybe_add_optional_filter<false>, &compress_filter);
grpc_channel_init_register_stage(
GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
maybe_add_optional_filter<true>, &decompress_filter);
grpc_channel_init_register_stage(
GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
maybe_add_optional_filter<true>, &decompress_filter);
grpc_channel_init_register_stage(
GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
maybe_add_optional_filter<true>, &decompress_filter);
grpc_channel_init_register_stage(
GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
maybe_add_required_filter, (void*)&grpc_http_client_filter);

@ -0,0 +1,358 @@
//
//
// Copyright 2020 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 <assert.h>
#include <string.h>
#include <grpc/compression.h>
#include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/filters/http/message_compress/message_decompress_filter.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/compression/algorithm_metadata.h"
#include "src/core/lib/compression/compression_args.h"
#include "src/core/lib/compression/compression_internal.h"
#include "src/core/lib/compression/message_compress.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
namespace {
class ChannelData {};
class CallData {
public:
explicit CallData(const grpc_call_element_args& args)
: call_combiner_(args.call_combiner) {
// Initialize state for recv_initial_metadata_ready callback
GRPC_CLOSURE_INIT(&on_recv_initial_metadata_ready_,
OnRecvInitialMetadataReady, this,
grpc_schedule_on_exec_ctx);
// Initialize state for recv_message_ready callback
grpc_slice_buffer_init(&recv_slices_);
GRPC_CLOSURE_INIT(&on_recv_message_next_done_, OnRecvMessageNextDone, this,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&on_recv_message_ready_, OnRecvMessageReady, this,
grpc_schedule_on_exec_ctx);
// Initialize state for recv_trailing_metadata_ready callback
GRPC_CLOSURE_INIT(&on_recv_trailing_metadata_ready_,
OnRecvTrailingMetadataReady, this,
grpc_schedule_on_exec_ctx);
}
~CallData() { grpc_slice_buffer_destroy_internal(&recv_slices_); }
void DecompressStartTransportStreamOpBatch(
grpc_call_element* elem, grpc_transport_stream_op_batch* batch);
private:
static void OnRecvInitialMetadataReady(void* arg, grpc_error* error);
// Methods for processing a receive message event
void MaybeResumeOnRecvMessageReady();
static void OnRecvMessageReady(void* arg, grpc_error* error);
static void OnRecvMessageNextDone(void* arg, grpc_error* error);
grpc_error* PullSliceFromRecvMessage();
void ContinueReadingRecvMessage();
void FinishRecvMessage();
void ContinueRecvMessageReadyCallback(grpc_error* error);
// Methods for processing a recv_trailing_metadata event
void MaybeResumeOnRecvTrailingMetadataReady();
static void OnRecvTrailingMetadataReady(void* arg, grpc_error* error);
grpc_core::CallCombiner* call_combiner_;
// Overall error for the call
grpc_error* error_ = GRPC_ERROR_NONE;
// Fields for handling recv_initial_metadata_ready callback
grpc_closure on_recv_initial_metadata_ready_;
grpc_closure* original_recv_initial_metadata_ready_ = nullptr;
grpc_metadata_batch* recv_initial_metadata_ = nullptr;
// Fields for handling recv_message_ready callback
bool seen_recv_message_ready_ = false;
grpc_message_compression_algorithm algorithm_ = GRPC_MESSAGE_COMPRESS_NONE;
grpc_closure on_recv_message_ready_;
grpc_closure* original_recv_message_ready_ = nullptr;
grpc_closure on_recv_message_next_done_;
grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message_ = nullptr;
// recv_slices_ holds the slices read from the original recv_message stream.
// It is initialized during construction and reset when a new stream is
// created using it.
grpc_slice_buffer recv_slices_;
std::aligned_storage<sizeof(grpc_core::SliceBufferByteStream),
alignof(grpc_core::SliceBufferByteStream)>::type
recv_replacement_stream_;
// Fields for handling recv_trailing_metadata_ready callback
bool seen_recv_trailing_metadata_ready_ = false;
grpc_closure on_recv_trailing_metadata_ready_;
grpc_closure* original_recv_trailing_metadata_ready_ = nullptr;
grpc_error* on_recv_trailing_metadata_ready_error_ = GRPC_ERROR_NONE;
};
grpc_message_compression_algorithm DecodeMessageCompressionAlgorithm(
grpc_mdelem md) {
grpc_message_compression_algorithm algorithm =
grpc_message_compression_algorithm_from_slice(GRPC_MDVALUE(md));
if (algorithm == GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT) {
char* md_c_str = grpc_slice_to_c_string(GRPC_MDVALUE(md));
gpr_log(GPR_ERROR,
"Invalid incoming message compression algorithm: '%s'. "
"Interpreting incoming data as uncompressed.",
md_c_str);
gpr_free(md_c_str);
return GRPC_MESSAGE_COMPRESS_NONE;
}
return algorithm;
}
void CallData::OnRecvInitialMetadataReady(void* arg, grpc_error* error) {
CallData* calld = static_cast<CallData*>(arg);
if (error == GRPC_ERROR_NONE) {
grpc_linked_mdelem* grpc_encoding =
calld->recv_initial_metadata_->idx.named.grpc_encoding;
if (grpc_encoding != nullptr) {
calld->algorithm_ = DecodeMessageCompressionAlgorithm(grpc_encoding->md);
}
}
calld->MaybeResumeOnRecvMessageReady();
calld->MaybeResumeOnRecvTrailingMetadataReady();
grpc_closure* closure = calld->original_recv_initial_metadata_ready_;
calld->original_recv_initial_metadata_ready_ = nullptr;
grpc_core::Closure::Run(DEBUG_LOCATION, closure, GRPC_ERROR_REF(error));
}
void CallData::MaybeResumeOnRecvMessageReady() {
if (seen_recv_message_ready_) {
seen_recv_message_ready_ = false;
GRPC_CALL_COMBINER_START(call_combiner_, &on_recv_message_ready_,
GRPC_ERROR_NONE,
"continue recv_message_ready callback");
}
}
void CallData::OnRecvMessageReady(void* arg, grpc_error* error) {
CallData* calld = static_cast<CallData*>(arg);
if (error == GRPC_ERROR_NONE) {
if (calld->original_recv_initial_metadata_ready_ != nullptr) {
calld->seen_recv_message_ready_ = true;
GRPC_CALL_COMBINER_STOP(calld->call_combiner_,
"Deferring OnRecvMessageReady until after "
"OnRecvInitialMetadataReady");
return;
}
if (calld->algorithm_ != GRPC_MESSAGE_COMPRESS_NONE) {
// recv_message can be NULL if trailing metadata is received instead of
// message, or it's possible that the message was not compressed.
if (*calld->recv_message_ == nullptr ||
(*calld->recv_message_)->length() == 0 ||
((*calld->recv_message_)->flags() & GRPC_WRITE_INTERNAL_COMPRESS) ==
0) {
return calld->ContinueRecvMessageReadyCallback(GRPC_ERROR_NONE);
}
grpc_slice_buffer_destroy_internal(&calld->recv_slices_);
grpc_slice_buffer_init(&calld->recv_slices_);
return calld->ContinueReadingRecvMessage();
}
}
calld->ContinueRecvMessageReadyCallback(GRPC_ERROR_REF(error));
}
void CallData::ContinueReadingRecvMessage() {
while ((*recv_message_)
->Next((*recv_message_)->length() - recv_slices_.length,
&on_recv_message_next_done_)) {
grpc_error* error = PullSliceFromRecvMessage();
if (error != GRPC_ERROR_NONE) {
return ContinueRecvMessageReadyCallback(error);
}
// We have read the entire message.
if (recv_slices_.length == (*recv_message_)->length()) {
return FinishRecvMessage();
}
}
}
grpc_error* CallData::PullSliceFromRecvMessage() {
grpc_slice incoming_slice;
grpc_error* error = (*recv_message_)->Pull(&incoming_slice);
if (error == GRPC_ERROR_NONE) {
grpc_slice_buffer_add(&recv_slices_, incoming_slice);
}
return error;
}
void CallData::OnRecvMessageNextDone(void* arg, grpc_error* error) {
CallData* calld = static_cast<CallData*>(arg);
if (error != GRPC_ERROR_NONE) {
return calld->ContinueRecvMessageReadyCallback(GRPC_ERROR_REF(error));
}
error = calld->PullSliceFromRecvMessage();
if (error != GRPC_ERROR_NONE) {
return calld->ContinueRecvMessageReadyCallback(error);
}
if (calld->recv_slices_.length == (*calld->recv_message_)->length()) {
calld->FinishRecvMessage();
} else {
calld->ContinueReadingRecvMessage();
}
}
void CallData::FinishRecvMessage() {
grpc_slice_buffer decompressed_slices;
grpc_slice_buffer_init(&decompressed_slices);
if (grpc_msg_decompress(algorithm_, &recv_slices_, &decompressed_slices) ==
0) {
char* msg;
gpr_asprintf(
&msg,
"Unexpected error decompressing data for algorithm with enum value %d",
algorithm_);
GPR_DEBUG_ASSERT(error_ == GRPC_ERROR_NONE);
error_ = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
gpr_free(msg);
grpc_slice_buffer_destroy_internal(&decompressed_slices);
} else {
uint32_t recv_flags =
((*recv_message_)->flags() & (~GRPC_WRITE_INTERNAL_COMPRESS)) |
GRPC_WRITE_INTERNAL_TEST_ONLY_WAS_COMPRESSED;
// Swap out the original receive byte stream with our new one and send the
// batch down.
// Initializing recv_replacement_stream_ with decompressed_slices removes
// all the slices from decompressed_slices leaving it empty.
new (&recv_replacement_stream_)
grpc_core::SliceBufferByteStream(&decompressed_slices, recv_flags);
recv_message_->reset(reinterpret_cast<grpc_core::SliceBufferByteStream*>(
&recv_replacement_stream_));
recv_message_ = nullptr;
}
ContinueRecvMessageReadyCallback(GRPC_ERROR_REF(error_));
}
void CallData::ContinueRecvMessageReadyCallback(grpc_error* error) {
MaybeResumeOnRecvTrailingMetadataReady();
// The surface will clean up the receiving stream if there is an error.
grpc_closure* closure = original_recv_message_ready_;
original_recv_message_ready_ = nullptr;
grpc_core::Closure::Run(DEBUG_LOCATION, closure, error);
}
void CallData::MaybeResumeOnRecvTrailingMetadataReady() {
if (seen_recv_trailing_metadata_ready_) {
seen_recv_trailing_metadata_ready_ = false;
grpc_error* error = on_recv_trailing_metadata_ready_error_;
on_recv_trailing_metadata_ready_error_ = GRPC_ERROR_NONE;
GRPC_CALL_COMBINER_START(call_combiner_, &on_recv_trailing_metadata_ready_,
error, "Continuing OnRecvTrailingMetadataReady");
}
}
void CallData::OnRecvTrailingMetadataReady(void* arg, grpc_error* error) {
CallData* calld = static_cast<CallData*>(arg);
if (calld->original_recv_initial_metadata_ready_ != nullptr ||
calld->original_recv_message_ready_ != nullptr) {
calld->seen_recv_trailing_metadata_ready_ = true;
calld->on_recv_trailing_metadata_ready_error_ = GRPC_ERROR_REF(error);
GRPC_CALL_COMBINER_STOP(
calld->call_combiner_,
"Deferring OnRecvTrailingMetadataReady until after "
"OnRecvInitialMetadataReady and OnRecvMessageReady");
return;
}
error = grpc_error_add_child(GRPC_ERROR_REF(error), calld->error_);
calld->error_ = GRPC_ERROR_NONE;
grpc_closure* closure = calld->original_recv_trailing_metadata_ready_;
calld->original_recv_trailing_metadata_ready_ = nullptr;
grpc_core::Closure::Run(DEBUG_LOCATION, closure, error);
}
void CallData::DecompressStartTransportStreamOpBatch(
grpc_call_element* elem, grpc_transport_stream_op_batch* batch) {
// Handle recv_initial_metadata.
if (batch->recv_initial_metadata) {
recv_initial_metadata_ =
batch->payload->recv_initial_metadata.recv_initial_metadata;
original_recv_initial_metadata_ready_ =
batch->payload->recv_initial_metadata.recv_initial_metadata_ready;
batch->payload->recv_initial_metadata.recv_initial_metadata_ready =
&on_recv_initial_metadata_ready_;
}
// Handle recv_message
if (batch->recv_message) {
recv_message_ = batch->payload->recv_message.recv_message;
original_recv_message_ready_ =
batch->payload->recv_message.recv_message_ready;
batch->payload->recv_message.recv_message_ready = &on_recv_message_ready_;
}
// Handle recv_trailing_metadata
if (batch->recv_trailing_metadata) {
original_recv_trailing_metadata_ready_ =
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
&on_recv_trailing_metadata_ready_;
}
// Pass control down the stack.
grpc_call_next_op(elem, batch);
}
void DecompressStartTransportStreamOpBatch(
grpc_call_element* elem, grpc_transport_stream_op_batch* batch) {
GPR_TIMER_SCOPE("decompress_start_transport_stream_op_batch", 0);
CallData* calld = static_cast<CallData*>(elem->call_data);
calld->DecompressStartTransportStreamOpBatch(elem, batch);
}
static grpc_error* DecompressInitCallElem(grpc_call_element* elem,
const grpc_call_element_args* args) {
new (elem->call_data) CallData(*args);
return GRPC_ERROR_NONE;
}
static void DecompressDestroyCallElem(
grpc_call_element* elem, const grpc_call_final_info* /*final_info*/,
grpc_closure* /*ignored*/) {
CallData* calld = static_cast<CallData*>(elem->call_data);
calld->~CallData();
}
static grpc_error* DecompressInitChannelElem(
grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) {
return GRPC_ERROR_NONE;
}
void DecompressDestroyChannelElem(grpc_channel_element* /*elem*/) {}
} // namespace
const grpc_channel_filter grpc_message_decompress_filter = {
DecompressStartTransportStreamOpBatch,
grpc_channel_next_op,
sizeof(CallData),
DecompressInitCallElem,
grpc_call_stack_ignore_set_pollset_or_pollset_set,
DecompressDestroyCallElem,
0, // sizeof(ChannelData)
DecompressInitChannelElem,
DecompressDestroyChannelElem,
grpc_channel_next_get_info,
"message_decompress"};

@ -0,0 +1,29 @@
//
//
// Copyright 2020 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_CORE_EXT_FILTERS_HTTP_MESSAGE_COMPRESS_MESSAGE_DECOMPRESS_FILTER_H
#define GRPC_CORE_EXT_FILTERS_HTTP_MESSAGE_COMPRESS_MESSAGE_DECOMPRESS_FILTER_H
#include <grpc/support/port_platform.h>
#include "src/core/lib/channel/channel_stack.h"
extern const grpc_channel_filter grpc_message_decompress_filter;
#endif /* GRPC_CORE_EXT_FILTERS_HTTP_MESSAGE_COMPRESS_MESSAGE_DECOMPRESS_FILTER_H \
*/

@ -277,6 +277,7 @@ typedef struct {
/* maximum size of a frame */
size_t max_frame_size;
bool use_true_binary_metadata;
bool is_end_of_stream;
} framer_state;
/* fills p (which is expected to be kDataFrameHeaderSize bytes long)
@ -315,17 +316,29 @@ static size_t current_frame_size(framer_state* st) {
}
/* finish a frame - fill in the previously reserved header */
static void finish_frame(framer_state* st, int is_header_boundary,
int is_last_in_stream) {
static void finish_frame(framer_state* st, int is_header_boundary) {
uint8_t type = 0xff;
type = st->is_first_frame ? GRPC_CHTTP2_FRAME_HEADER
: GRPC_CHTTP2_FRAME_CONTINUATION;
fill_header(
GRPC_SLICE_START_PTR(st->output->slices[st->header_idx]), type,
st->stream_id, current_frame_size(st),
static_cast<uint8_t>(
(is_last_in_stream ? GRPC_CHTTP2_DATA_FLAG_END_STREAM : 0) |
(is_header_boundary ? GRPC_CHTTP2_DATA_FLAG_END_HEADERS : 0)));
type =
static_cast<uint8_t>(st->is_first_frame ? GRPC_CHTTP2_FRAME_HEADER
: GRPC_CHTTP2_FRAME_CONTINUATION);
uint8_t flags = 0xff;
/* per the HTTP/2 spec:
A HEADERS frame carries the END_STREAM flag that signals the end of a
stream. However, a HEADERS frame with the END_STREAM flag set can be
followed by CONTINUATION frames on the same stream. Logically, the
CONTINUATION frames are part of the HEADERS frame.
Thus, we add the END_STREAM flag to the HEADER frame (the first frame). */
flags = static_cast<uint8_t>(st->is_first_frame && st->is_end_of_stream
? GRPC_CHTTP2_DATA_FLAG_END_STREAM
: 0);
/* per the HTTP/2 spec:
A HEADERS frame without the END_HEADERS flag set MUST be followed by
a CONTINUATION frame for the same stream.
Thus, we add the END_HEADER flag to the last frame. */
flags |= static_cast<uint8_t>(
is_header_boundary ? GRPC_CHTTP2_DATA_FLAG_END_HEADERS : 0);
fill_header(GRPC_SLICE_START_PTR(st->output->slices[st->header_idx]), type,
st->stream_id, current_frame_size(st), flags);
st->stats->framing_bytes += kDataFrameHeaderSize;
st->is_first_frame = 0;
}
@ -347,7 +360,7 @@ static void ensure_space(framer_state* st, size_t need_bytes) {
if (GPR_LIKELY(current_frame_size(st) + need_bytes <= st->max_frame_size)) {
return;
}
finish_frame(st, 0, 0);
finish_frame(st, 0);
begin_frame(st);
}
@ -362,7 +375,7 @@ static void add_header_data(framer_state* st, grpc_slice slice) {
} else {
st->stats->header_bytes += remaining;
grpc_slice_buffer_add(st->output, grpc_slice_split_head(&slice, remaining));
finish_frame(st, 0, 0);
finish_frame(st, 0);
begin_frame(st);
add_header_data(st, slice);
}
@ -841,6 +854,7 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor* c,
st.stats = options->stats;
st.max_frame_size = options->max_frame_size;
st.use_true_binary_metadata = options->use_true_binary_metadata;
st.is_end_of_stream = options->is_eof;
/* Encode a metadata batch; store the returned values, representing
a metadata element that needs to be unreffed back into the metadata
@ -883,5 +897,5 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor* c,
deadline_enc(c, deadline, &st);
}
finish_frame(&st, 1, options->is_eof);
finish_frame(&st, 1);
}

@ -764,6 +764,7 @@ void op_state_machine_locked(inproc_stream* s, grpc_error* error) {
// Nothing further will try to receive from this stream, so finish off
// any outstanding send_message op
s->send_message_op->payload->send_message.send_message.reset();
s->send_message_op->payload->send_message.stream_write_closed = true;
complete_if_batch_end_locked(
s, new_err, s->send_message_op,
"op_state_machine scheduling send-message-on-complete");

@ -387,15 +387,14 @@ void PopulateSocketAddressJson(Json::Object* json, const char* name,
(strcmp(uri->scheme, "ipv6") == 0))) {
const char* host_port = uri->path;
if (*host_port == '/') ++host_port;
grpc_core::UniquePtr<char> host;
grpc_core::UniquePtr<char> port;
std::string host;
std::string port;
GPR_ASSERT(SplitHostPort(host_port, &host, &port));
int port_num = -1;
if (port != nullptr) {
port_num = atoi(port.get());
if (!port.empty()) {
port_num = atoi(port.data());
}
char* b64_host =
grpc_base64_encode(host.get(), strlen(host.get()), false, false);
char* b64_host = grpc_base64_encode(host.data(), host.size(), false, false);
data["tcpip_address"] = Json::Object{
{"port", port_num},
{"ip_address", b64_host},

@ -25,10 +25,11 @@
#include <string>
#include "absl/container/inlined_vector.h"
#include "src/core/lib/channel/channel_trace.h"
#include "src/core/lib/gpr/time_precise.h"
#include "src/core/lib/gprpp/atomic.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/manual_constructor.h"
#include "src/core/lib/gprpp/map.h"
#include "src/core/lib/gprpp/ref_counted.h"
@ -167,7 +168,7 @@ class CallCountingHelper {
void CollectData(CounterData* out);
// Really zero-sized, but 0-sized arrays are illegal on MSVC.
InlinedVector<AtomicCounterData, 1> per_cpu_counter_data_storage_;
absl::InlinedVector<AtomicCounterData, 1> per_cpu_counter_data_storage_;
size_t num_cores_ = 0;
};

@ -21,6 +21,8 @@
#include <algorithm>
#include <cstring>
#include "absl/container/inlined_vector.h"
#include "src/core/lib/channel/channel_trace.h"
#include "src/core/lib/channel/channelz.h"
#include "src/core/lib/channel/channelz_registry.h"
@ -82,7 +84,7 @@ RefCountedPtr<BaseNode> ChannelzRegistry::InternalGet(intptr_t uuid) {
std::string ChannelzRegistry::InternalGetTopChannels(
intptr_t start_channel_id) {
InlinedVector<RefCountedPtr<BaseNode>, 10> top_level_channels;
absl::InlinedVector<RefCountedPtr<BaseNode>, 10> top_level_channels;
RefCountedPtr<BaseNode> node_after_pagination_limit;
{
MutexLock lock(&mu_);
@ -120,7 +122,7 @@ std::string ChannelzRegistry::InternalGetTopChannels(
}
std::string ChannelzRegistry::InternalGetServers(intptr_t start_server_id) {
InlinedVector<RefCountedPtr<BaseNode>, 10> servers;
absl::InlinedVector<RefCountedPtr<BaseNode>, 10> servers;
RefCountedPtr<BaseNode> node_after_pagination_limit;
{
MutexLock lock(&mu_);
@ -158,7 +160,7 @@ std::string ChannelzRegistry::InternalGetServers(intptr_t start_server_id) {
}
void ChannelzRegistry::InternalLogAllEntities() {
InlinedVector<RefCountedPtr<BaseNode>, 10> nodes;
absl::InlinedVector<RefCountedPtr<BaseNode>, 10> nodes;
{
MutexLock lock(&mu_);
for (auto& p : node_map_) {

@ -91,9 +91,12 @@ static callback_state* get_state_for_batch(
/* We perform a small hack to locate transport data alongside the connected
channel data in call allocations, to allow everything to be pulled in minimal
cache line requests */
#define TRANSPORT_STREAM_FROM_CALL_DATA(calld) ((grpc_stream*)((calld) + 1))
#define TRANSPORT_STREAM_FROM_CALL_DATA(calld) \
((grpc_stream*)(((char*)(calld)) + \
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(call_data))))
#define CALL_DATA_FROM_TRANSPORT_STREAM(transport_stream) \
(((call_data*)(transport_stream)) - 1)
((call_data*)(((char*)(transport_stream)) - \
GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(call_data))))
/* Intercept a call operation and either push it directly up or translate it
into transport stream operations */

@ -21,12 +21,13 @@
#include <grpc/support/port_platform.h>
#include "absl/container/inlined_vector.h"
#include <grpc/support/string_util.h>
#include <grpc/impl/codegen/grpc_types.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/closure.h"
@ -146,7 +147,8 @@ class HandshakeManager : public RefCounted<HandshakeManager> {
gpr_mu mu_;
bool is_shutdown_ = false;
// An array of handshakers added via grpc_handshake_manager_add().
InlinedVector<RefCountedPtr<Handshaker>, HANDSHAKERS_INIT_SIZE> handshakers_;
absl::InlinedVector<RefCountedPtr<Handshaker>, HANDSHAKERS_INIT_SIZE>
handshakers_;
// The index of the handshaker to invoke next and closure to invoke it.
size_t index_ = 0;
grpc_closure call_next_handshaker_;

@ -18,9 +18,10 @@
#include <grpc/support/port_platform.h>
#include "absl/container/inlined_vector.h"
#include "src/core/lib/channel/handshaker_registry.h"
#include "src/core/lib/gpr/alloc.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/memory.h"
#include <string.h>
@ -44,7 +45,7 @@ class HandshakerFactoryList {
HandshakeManager* handshake_mgr);
private:
InlinedVector<std::unique_ptr<HandshakerFactory>, 2> factories_;
absl::InlinedVector<std::unique_ptr<HandshakerFactory>, 2> factories_;
};
HandshakerFactoryList* g_handshaker_factory_lists = nullptr;

@ -22,14 +22,26 @@
#include <string.h>
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/string_view.h"
namespace grpc_core {
std::string JoinHostPort(absl::string_view host, int port) {
if (host[0] != '[' && host.rfind(':') != host.npos) {
// IPv6 literals must be enclosed in brackets.
return absl::StrFormat("[%s]:%d", host, port);
}
// Ordinary non-bracketed host:port.
return absl::StrFormat("%s:%d", host, port);
}
int JoinHostPort(grpc_core::UniquePtr<char>* out, const char* host, int port) {
char* tmp;
int ret;
@ -45,19 +57,19 @@ int JoinHostPort(grpc_core::UniquePtr<char>* out, const char* host, int port) {
}
namespace {
bool DoSplitHostPort(StringView name, StringView* host, StringView* port,
bool* has_port) {
bool DoSplitHostPort(absl::string_view name, absl::string_view* host,
absl::string_view* port, bool* has_port) {
*has_port = false;
if (!name.empty() && name[0] == '[') {
/* Parse a bracketed host, typically an IPv6 literal. */
const size_t rbracket = name.find(']', 1);
if (rbracket == grpc_core::StringView::npos) {
if (rbracket == absl::string_view::npos) {
/* Unmatched [ */
return false;
}
if (rbracket == name.size() - 1) {
/* ]<end> */
*port = StringView();
*port = absl::string_view();
} else if (name[rbracket + 1] == ':') {
/* ]:<port?> */
*port = name.substr(rbracket + 2, name.size() - rbracket - 2);
@ -67,16 +79,16 @@ bool DoSplitHostPort(StringView name, StringView* host, StringView* port,
return false;
}
*host = name.substr(1, rbracket - 1);
if (host->find(':') == grpc_core::StringView::npos) {
if (host->find(':') == absl::string_view::npos) {
/* Require all bracketed hosts to contain a colon, because a hostname or
IPv4 address should never use brackets. */
*host = StringView();
*host = absl::string_view();
return false;
}
} else {
size_t colon = name.find(':');
if (colon != grpc_core::StringView::npos &&
name.find(':', colon + 1) == grpc_core::StringView::npos) {
if (colon != absl::string_view::npos &&
name.find(':', colon + 1) == absl::string_view::npos) {
/* Exactly 1 colon. Split into host:port. */
*host = name.substr(0, colon);
*port = name.substr(colon + 1, name.size() - colon - 1);
@ -84,35 +96,37 @@ bool DoSplitHostPort(StringView name, StringView* host, StringView* port,
} else {
/* 0 or 2+ colons. Bare hostname or IPv6 litearal. */
*host = name;
*port = StringView();
*port = absl::string_view();
}
}
return true;
}
} // namespace
bool SplitHostPort(StringView name, StringView* host, StringView* port) {
bool SplitHostPort(absl::string_view name, absl::string_view* host,
absl::string_view* port) {
bool unused;
return DoSplitHostPort(name, host, port, &unused);
}
bool SplitHostPort(StringView name, grpc_core::UniquePtr<char>* host,
grpc_core::UniquePtr<char>* port) {
GPR_DEBUG_ASSERT(host != nullptr && *host == nullptr);
GPR_DEBUG_ASSERT(port != nullptr && *port == nullptr);
StringView host_view;
StringView port_view;
bool SplitHostPort(absl::string_view name, std::string* host,
std::string* port) {
GPR_DEBUG_ASSERT(host != nullptr && host->empty());
GPR_DEBUG_ASSERT(port != nullptr && port->empty());
absl::string_view host_view;
absl::string_view port_view;
bool has_port;
const bool ret = DoSplitHostPort(name, &host_view, &port_view, &has_port);
if (ret) {
// We always set the host, but port is set only when DoSplitHostPort find a
// port in the string, to remain backward compatible with the old
// gpr_split_host_port API.
*host = StringViewToCString(host_view);
*host = std::string(host_view);
if (has_port) {
*port = StringViewToCString(port_view);
*port = std::string(port_view);
}
}
return ret;
}
} // namespace grpc_core

@ -21,19 +21,21 @@
#include <grpc/support/port_platform.h>
#include "absl/strings/string_view.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/string_view.h"
namespace grpc_core {
/** Given a host and port, creates a newly-allocated string of the form
"host:port" or "[ho:st]:port", depending on whether the host contains colons
like an IPv6 literal. If the host is already bracketed, then additional
brackets will not be added.
Usage is similar to gpr_asprintf: returns the number of bytes written
// Given a host and port, creates a newly-allocated string of the form
// "host:port" or "[ho:st]:port", depending on whether the host contains colons
// like an IPv6 literal. If the host is already bracketed, then additional
// brackets will not be added.
std::string JoinHostPort(absl::string_view host, int port);
// TODO(roth): Change all callers to use the above variant and then
// remove this one.
/* Usage is similar to gpr_asprintf: returns the number of bytes written
(excluding the final '\0'), and *out points to a string.
In the unlikely event of an error, returns -1 and sets *out to NULL. */
int JoinHostPort(grpc_core::UniquePtr<char>* out, const char* host, int port);
@ -41,8 +43,8 @@ int JoinHostPort(grpc_core::UniquePtr<char>* out, const char* host, int port);
and port number.
There are two variants of this method:
1) StringView output: port and host are returned as views on name.
2) char* output: port and host are copied into newly allocated strings.
1) absl::string_view output: port and host are returned as views on name.
2) std::string output: port and host are copied into newly allocated strings.
Prefer variant (1) over (2), because no allocation or copy is performed in
variant (1). Use (2) only when interacting with C API that mandate
@ -50,9 +52,10 @@ int JoinHostPort(grpc_core::UniquePtr<char>* out, const char* host, int port);
Return true on success, false on failure. Guarantees *host and *port are
cleared on failure. */
bool SplitHostPort(StringView name, StringView* host, StringView* port);
bool SplitHostPort(StringView name, grpc_core::UniquePtr<char>* host,
grpc_core::UniquePtr<char>* port);
bool SplitHostPort(absl::string_view name, absl::string_view* host,
absl::string_view* port);
bool SplitHostPort(absl::string_view name, std::string* host,
std::string* port);
} // namespace grpc_core

@ -1,37 +0,0 @@
/*
*
* Copyright 2017 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_CORE_LIB_GPRPP_INLINED_VECTOR_H
#define GRPC_CORE_LIB_GPRPP_INLINED_VECTOR_H
#include <grpc/support/port_platform.h>
#include <cassert>
#include <cstring>
#include "absl/container/inlined_vector.h"
#include "src/core/lib/gprpp/memory.h"
namespace grpc_core {
template <typename T, size_t N, typename A = std::allocator<T>>
using InlinedVector = absl::InlinedVector<T, N, A>;
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_GPRPP_INLINED_VECTOR_H */

@ -25,8 +25,9 @@
#include <map>
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/string_view.h"
#include "absl/strings/string_view.h"
#include "src/core/lib/gprpp/memory.h"
namespace grpc_core {
@ -38,7 +39,8 @@ struct StringLess {
const grpc_core::UniquePtr<char>& b) const {
return strcmp(a.get(), b.get()) < 0;
}
bool operator()(const StringView& a, const StringView& b) const {
bool operator()(const absl::string_view& a,
const absl::string_view& b) const {
const size_t min_size = std::min(a.size(), b.size());
int c = strncmp(a.data(), b.data(), min_size);
if (c != 0) return c < 0;
@ -46,14 +48,6 @@ struct StringLess {
}
};
template <typename T>
struct RefCountedPtrLess {
bool operator()(const RefCountedPtr<T>& p1,
const RefCountedPtr<T>& p2) const {
return p1.get() < p2.get();
}
};
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_GPRPP_MAP_H */

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save