Merge branch 'master' into grpc_namespace_healthserviceinterface

pull/18371/head
Karthik Ravi Shankar 6 years ago
commit e4945761f3
  1. 5
      BUILD
  2. 5
      BUILD.gn
  3. 12
      CMakeLists.txt
  4. 13
      Makefile
  5. 4
      bazel/grpc_deps.bzl
  6. 4
      build.yaml
  7. 2
      config.m4
  8. 2
      config.w32
  9. 5
      doc/environment_variables.md
  10. 3
      gRPC-C++.podspec
  11. 7
      gRPC-Core.podspec
  12. 6
      grpc.gemspec
  13. 8
      grpc.gyp
  14. 5
      include/grpcpp/generic/generic_stub.h
  15. 20
      include/grpcpp/impl/codegen/async_generic_service.h
  16. 118
      include/grpcpp/impl/codegen/client_callback.h
  17. 2
      include/grpcpp/impl/codegen/rpc_service_method.h
  18. 174
      include/grpcpp/impl/codegen/server_callback.h
  19. 4
      include/grpcpp/server_builder.h
  20. 4
      package.xml
  21. 2
      src/c-ares/gen_build_yaml.py
  22. 2
      src/core/README.md
  23. 6
      src/core/ext/filters/client_channel/client_channel.cc
  24. 43
      src/core/ext/filters/client_channel/lb_policy.cc
  25. 32
      src/core/ext/filters/client_channel/lb_policy.h
  26. 116
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  27. 2
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc
  28. 4
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h
  29. 8
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc
  30. 30
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
  31. 24
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
  32. 1
      src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
  33. 72
      src/core/ext/filters/client_channel/lb_policy/xds/xds.cc
  34. 51
      src/core/ext/filters/client_channel/resolver.cc
  35. 31
      src/core/ext/filters/client_channel/resolver.h
  36. 25
      src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
  37. 12
      src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
  38. 83
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
  39. 17
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h
  40. 26
      src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
  41. 1
      src/core/ext/filters/client_channel/resolver_registry.h
  42. 115
      src/core/ext/filters/client_channel/resolver_result_parsing.cc
  43. 10
      src/core/ext/filters/client_channel/resolver_result_parsing.h
  44. 49
      src/core/ext/filters/client_channel/resolving_lb_policy.cc
  45. 14
      src/core/ext/filters/client_channel/resolving_lb_policy.h
  46. 48
      src/core/ext/filters/client_channel/server_address.cc
  47. 10
      src/core/ext/filters/client_channel/server_address.h
  48. 13
      src/core/ext/filters/client_channel/service_config.cc
  49. 16
      src/core/ext/filters/client_channel/service_config.h
  50. 2
      src/core/ext/filters/client_channel/subchannel.cc
  51. 2
      src/core/ext/filters/message_size/message_size_filter.cc
  52. 4
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  53. 2
      src/core/lib/channel/channel_args.cc
  54. 6
      src/core/lib/iomgr/ev_epoll1_linux.cc
  55. 6
      src/core/lib/iomgr/ev_epollex_linux.cc
  56. 6
      src/core/lib/iomgr/ev_poll_posix.cc
  57. 5
      src/core/lib/iomgr/ev_posix.cc
  58. 8
      src/core/lib/iomgr/ev_posix.h
  59. 13
      src/core/lib/iomgr/executor.cc
  60. 3
      src/core/lib/iomgr/executor.h
  61. 5
      src/core/lib/iomgr/iomgr.cc
  62. 7
      src/core/lib/iomgr/iomgr.h
  63. 11
      src/core/lib/iomgr/iomgr_custom.cc
  64. 6
      src/core/lib/iomgr/iomgr_internal.cc
  65. 10
      src/core/lib/iomgr/iomgr_internal.h
  66. 12
      src/core/lib/iomgr/iomgr_posix.cc
  67. 12
      src/core/lib/iomgr/iomgr_posix_cfstream.cc
  68. 12
      src/core/lib/iomgr/iomgr_windows.cc
  69. 5
      src/core/lib/security/credentials/jwt/jwt_verifier.cc
  70. 7
      src/core/lib/transport/transport.h
  71. 2
      src/csharp/Grpc.Core.Api/AuthContext.cs
  72. 7
      src/csharp/Grpc.Core/Version.csproj.include
  73. 10
      src/csharp/Grpc.Tools.Tests/ProtoCompileBasicTest.cs
  74. 81
      src/csharp/Grpc.Tools.Tests/ProtoCompileCommandLineGeneratorTest.cs
  75. 129
      src/csharp/Grpc.Tools/ProtoCompile.cs
  76. 1
      src/csharp/Grpc.Tools/build/_protobuf/Google.Protobuf.Tools.targets
  77. 3
      src/csharp/doc/docfx.json
  78. 2
      src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
  79. 3
      src/objective-c/!ProtoCompiler.podspec
  80. 2
      src/objective-c/BoringSSL-GRPC.podspec
  81. 11
      src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
  82. 2
      src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
  83. 12
      src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
  84. 2
      src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd.pxi
  85. 2
      src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
  86. 3
      src/python/grpcio/grpc_core_dependencies.py
  87. 4
      src/python/grpcio_tests/commands.py
  88. 2
      templates/gRPC-Core.podspec.template
  89. 2
      templates/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec.template
  90. 2
      templates/src/objective-c/BoringSSL-GRPC.podspec.template
  91. 16
      test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc
  92. 15
      test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
  93. 73
      test/core/client_channel/resolvers/fake_resolver_test.cc
  94. 4
      test/core/client_channel/resolvers/sockaddr_resolver_test.cc
  95. 1
      test/core/end2end/connection_refused_test.cc
  96. 1
      test/core/end2end/tests/cancel_after_accept.cc
  97. 1
      test/core/end2end/tests/cancel_after_round_trip.cc
  98. 1
      test/core/end2end/tests/max_message_length.cc
  99. 5
      test/core/util/test_lb_policies.cc
  100. 8
      test/cpp/client/client_channel_stress_test.cc
  101. Some files were not shown because too many files have changed in this diff Show More

@ -840,7 +840,6 @@ grpc_cc_library(
"src/core/lib/transport/metadata.cc", "src/core/lib/transport/metadata.cc",
"src/core/lib/transport/metadata_batch.cc", "src/core/lib/transport/metadata_batch.cc",
"src/core/lib/transport/pid_controller.cc", "src/core/lib/transport/pid_controller.cc",
"src/core/lib/transport/service_config.cc",
"src/core/lib/transport/static_metadata.cc", "src/core/lib/transport/static_metadata.cc",
"src/core/lib/transport/status_conversion.cc", "src/core/lib/transport/status_conversion.cc",
"src/core/lib/transport/status_metadata.cc", "src/core/lib/transport/status_metadata.cc",
@ -975,7 +974,6 @@ grpc_cc_library(
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/status_conversion.h", "src/core/lib/transport/status_conversion.h",
"src/core/lib/transport/status_metadata.h", "src/core/lib/transport/status_metadata.h",
@ -1086,6 +1084,7 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/resolving_lb_policy.cc", "src/core/ext/filters/client_channel/resolving_lb_policy.cc",
"src/core/ext/filters/client_channel/retry_throttle.cc", "src/core/ext/filters/client_channel/retry_throttle.cc",
"src/core/ext/filters/client_channel/server_address.cc", "src/core/ext/filters/client_channel/server_address.cc",
"src/core/ext/filters/client_channel/service_config.cc",
"src/core/ext/filters/client_channel/subchannel.cc", "src/core/ext/filters/client_channel/subchannel.cc",
"src/core/ext/filters/client_channel/subchannel_pool_interface.cc", "src/core/ext/filters/client_channel/subchannel_pool_interface.cc",
], ],
@ -1113,6 +1112,7 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/resolving_lb_policy.h", "src/core/ext/filters/client_channel/resolving_lb_policy.h",
"src/core/ext/filters/client_channel/retry_throttle.h", "src/core/ext/filters/client_channel/retry_throttle.h",
"src/core/ext/filters/client_channel/server_address.h", "src/core/ext/filters/client_channel/server_address.h",
"src/core/ext/filters/client_channel/service_config.h",
"src/core/ext/filters/client_channel/subchannel.h", "src/core/ext/filters/client_channel/subchannel.h",
"src/core/ext/filters/client_channel/subchannel_pool_interface.h", "src/core/ext/filters/client_channel/subchannel_pool_interface.h",
], ],
@ -1183,6 +1183,7 @@ grpc_cc_library(
language = "c++", language = "c++",
deps = [ deps = [
"grpc_base", "grpc_base",
"grpc_client_channel",
], ],
) )

@ -329,6 +329,8 @@ config("grpc_config") {
"src/core/ext/filters/client_channel/retry_throttle.h", "src/core/ext/filters/client_channel/retry_throttle.h",
"src/core/ext/filters/client_channel/server_address.cc", "src/core/ext/filters/client_channel/server_address.cc",
"src/core/ext/filters/client_channel/server_address.h", "src/core/ext/filters/client_channel/server_address.h",
"src/core/ext/filters/client_channel/service_config.cc",
"src/core/ext/filters/client_channel/service_config.h",
"src/core/ext/filters/client_channel/subchannel.cc", "src/core/ext/filters/client_channel/subchannel.cc",
"src/core/ext/filters/client_channel/subchannel.h", "src/core/ext/filters/client_channel/subchannel.h",
"src/core/ext/filters/client_channel/subchannel_pool_interface.cc", "src/core/ext/filters/client_channel/subchannel_pool_interface.cc",
@ -762,8 +764,6 @@ config("grpc_config") {
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/pid_controller.cc", "src/core/lib/transport/pid_controller.cc",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.cc",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.cc", "src/core/lib/transport/static_metadata.cc",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/status_conversion.cc", "src/core/lib/transport/status_conversion.cc",
@ -1251,7 +1251,6 @@ config("grpc_config") {
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/status_conversion.h", "src/core/lib/transport/status_conversion.h",
"src/core/lib/transport/status_metadata.h", "src/core/lib/transport/status_metadata.h",

@ -1109,7 +1109,6 @@ add_library(grpc
src/core/lib/transport/metadata.cc src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata_batch.cc src/core/lib/transport/metadata_batch.cc
src/core/lib/transport/pid_controller.cc src/core/lib/transport/pid_controller.cc
src/core/lib/transport/service_config.cc
src/core/lib/transport/static_metadata.cc src/core/lib/transport/static_metadata.cc
src/core/lib/transport/status_conversion.cc src/core/lib/transport/status_conversion.cc
src/core/lib/transport/status_metadata.cc src/core/lib/transport/status_metadata.cc
@ -1245,6 +1244,7 @@ add_library(grpc
src/core/ext/filters/client_channel/resolving_lb_policy.cc src/core/ext/filters/client_channel/resolving_lb_policy.cc
src/core/ext/filters/client_channel/retry_throttle.cc src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/service_config.cc
src/core/ext/filters/client_channel/subchannel.cc src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/deadline/deadline_filter.cc src/core/ext/filters/deadline/deadline_filter.cc
@ -1535,7 +1535,6 @@ add_library(grpc_cronet
src/core/lib/transport/metadata.cc src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata_batch.cc src/core/lib/transport/metadata_batch.cc
src/core/lib/transport/pid_controller.cc src/core/lib/transport/pid_controller.cc
src/core/lib/transport/service_config.cc
src/core/lib/transport/static_metadata.cc src/core/lib/transport/static_metadata.cc
src/core/lib/transport/status_conversion.cc src/core/lib/transport/status_conversion.cc
src/core/lib/transport/status_metadata.cc src/core/lib/transport/status_metadata.cc
@ -1599,6 +1598,7 @@ add_library(grpc_cronet
src/core/ext/filters/client_channel/resolving_lb_policy.cc src/core/ext/filters/client_channel/resolving_lb_policy.cc
src/core/ext/filters/client_channel/retry_throttle.cc src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/service_config.cc
src/core/ext/filters/client_channel/subchannel.cc src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/deadline/deadline_filter.cc src/core/ext/filters/deadline/deadline_filter.cc
@ -1946,7 +1946,6 @@ add_library(grpc_test_util
src/core/lib/transport/metadata.cc src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata_batch.cc src/core/lib/transport/metadata_batch.cc
src/core/lib/transport/pid_controller.cc src/core/lib/transport/pid_controller.cc
src/core/lib/transport/service_config.cc
src/core/lib/transport/static_metadata.cc src/core/lib/transport/static_metadata.cc
src/core/lib/transport/status_conversion.cc src/core/lib/transport/status_conversion.cc
src/core/lib/transport/status_metadata.cc src/core/lib/transport/status_metadata.cc
@ -1978,6 +1977,7 @@ add_library(grpc_test_util
src/core/ext/filters/client_channel/resolving_lb_policy.cc src/core/ext/filters/client_channel/resolving_lb_policy.cc
src/core/ext/filters/client_channel/retry_throttle.cc src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/service_config.cc
src/core/ext/filters/client_channel/subchannel.cc src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/deadline/deadline_filter.cc src/core/ext/filters/deadline/deadline_filter.cc
@ -2270,7 +2270,6 @@ add_library(grpc_test_util_unsecure
src/core/lib/transport/metadata.cc src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata_batch.cc src/core/lib/transport/metadata_batch.cc
src/core/lib/transport/pid_controller.cc src/core/lib/transport/pid_controller.cc
src/core/lib/transport/service_config.cc
src/core/lib/transport/static_metadata.cc src/core/lib/transport/static_metadata.cc
src/core/lib/transport/status_conversion.cc src/core/lib/transport/status_conversion.cc
src/core/lib/transport/status_metadata.cc src/core/lib/transport/status_metadata.cc
@ -2302,6 +2301,7 @@ add_library(grpc_test_util_unsecure
src/core/ext/filters/client_channel/resolving_lb_policy.cc src/core/ext/filters/client_channel/resolving_lb_policy.cc
src/core/ext/filters/client_channel/retry_throttle.cc src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/service_config.cc
src/core/ext/filters/client_channel/subchannel.cc src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/deadline/deadline_filter.cc src/core/ext/filters/deadline/deadline_filter.cc
@ -2570,7 +2570,6 @@ add_library(grpc_unsecure
src/core/lib/transport/metadata.cc src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata_batch.cc src/core/lib/transport/metadata_batch.cc
src/core/lib/transport/pid_controller.cc src/core/lib/transport/pid_controller.cc
src/core/lib/transport/service_config.cc
src/core/lib/transport/static_metadata.cc src/core/lib/transport/static_metadata.cc
src/core/lib/transport/status_conversion.cc src/core/lib/transport/status_conversion.cc
src/core/lib/transport/status_metadata.cc src/core/lib/transport/status_metadata.cc
@ -2637,6 +2636,7 @@ add_library(grpc_unsecure
src/core/ext/filters/client_channel/resolving_lb_policy.cc src/core/ext/filters/client_channel/resolving_lb_policy.cc
src/core/ext/filters/client_channel/retry_throttle.cc src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/service_config.cc
src/core/ext/filters/client_channel/subchannel.cc src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/deadline/deadline_filter.cc src/core/ext/filters/deadline/deadline_filter.cc
@ -3458,7 +3458,6 @@ add_library(grpc++_cronet
src/core/lib/transport/metadata.cc src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata_batch.cc src/core/lib/transport/metadata_batch.cc
src/core/lib/transport/pid_controller.cc src/core/lib/transport/pid_controller.cc
src/core/lib/transport/service_config.cc
src/core/lib/transport/static_metadata.cc src/core/lib/transport/static_metadata.cc
src/core/lib/transport/status_conversion.cc src/core/lib/transport/status_conversion.cc
src/core/lib/transport/status_metadata.cc src/core/lib/transport/status_metadata.cc
@ -3495,6 +3494,7 @@ add_library(grpc++_cronet
src/core/ext/filters/client_channel/resolving_lb_policy.cc src/core/ext/filters/client_channel/resolving_lb_policy.cc
src/core/ext/filters/client_channel/retry_throttle.cc src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/service_config.cc
src/core/ext/filters/client_channel/subchannel.cc src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/deadline/deadline_filter.cc src/core/ext/filters/deadline/deadline_filter.cc

@ -3556,7 +3556,6 @@ LIBGRPC_SRC = \
src/core/lib/transport/metadata.cc \ src/core/lib/transport/metadata.cc \
src/core/lib/transport/metadata_batch.cc \ src/core/lib/transport/metadata_batch.cc \
src/core/lib/transport/pid_controller.cc \ src/core/lib/transport/pid_controller.cc \
src/core/lib/transport/service_config.cc \
src/core/lib/transport/static_metadata.cc \ src/core/lib/transport/static_metadata.cc \
src/core/lib/transport/status_conversion.cc \ src/core/lib/transport/status_conversion.cc \
src/core/lib/transport/status_metadata.cc \ src/core/lib/transport/status_metadata.cc \
@ -3692,6 +3691,7 @@ LIBGRPC_SRC = \
src/core/ext/filters/client_channel/resolving_lb_policy.cc \ src/core/ext/filters/client_channel/resolving_lb_policy.cc \
src/core/ext/filters/client_channel/retry_throttle.cc \ src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \ src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
src/core/ext/filters/client_channel/subchannel.cc \ src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \ src/core/ext/filters/deadline/deadline_filter.cc \
@ -3976,7 +3976,6 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/transport/metadata.cc \ src/core/lib/transport/metadata.cc \
src/core/lib/transport/metadata_batch.cc \ src/core/lib/transport/metadata_batch.cc \
src/core/lib/transport/pid_controller.cc \ src/core/lib/transport/pid_controller.cc \
src/core/lib/transport/service_config.cc \
src/core/lib/transport/static_metadata.cc \ src/core/lib/transport/static_metadata.cc \
src/core/lib/transport/status_conversion.cc \ src/core/lib/transport/status_conversion.cc \
src/core/lib/transport/status_metadata.cc \ src/core/lib/transport/status_metadata.cc \
@ -4040,6 +4039,7 @@ LIBGRPC_CRONET_SRC = \
src/core/ext/filters/client_channel/resolving_lb_policy.cc \ src/core/ext/filters/client_channel/resolving_lb_policy.cc \
src/core/ext/filters/client_channel/retry_throttle.cc \ src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \ src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
src/core/ext/filters/client_channel/subchannel.cc \ src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \ src/core/ext/filters/deadline/deadline_filter.cc \
@ -4380,7 +4380,6 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/transport/metadata.cc \ src/core/lib/transport/metadata.cc \
src/core/lib/transport/metadata_batch.cc \ src/core/lib/transport/metadata_batch.cc \
src/core/lib/transport/pid_controller.cc \ src/core/lib/transport/pid_controller.cc \
src/core/lib/transport/service_config.cc \
src/core/lib/transport/static_metadata.cc \ src/core/lib/transport/static_metadata.cc \
src/core/lib/transport/status_conversion.cc \ src/core/lib/transport/status_conversion.cc \
src/core/lib/transport/status_metadata.cc \ src/core/lib/transport/status_metadata.cc \
@ -4412,6 +4411,7 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/ext/filters/client_channel/resolving_lb_policy.cc \ src/core/ext/filters/client_channel/resolving_lb_policy.cc \
src/core/ext/filters/client_channel/retry_throttle.cc \ src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \ src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
src/core/ext/filters/client_channel/subchannel.cc \ src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \ src/core/ext/filters/deadline/deadline_filter.cc \
@ -4691,7 +4691,6 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/lib/transport/metadata.cc \ src/core/lib/transport/metadata.cc \
src/core/lib/transport/metadata_batch.cc \ src/core/lib/transport/metadata_batch.cc \
src/core/lib/transport/pid_controller.cc \ src/core/lib/transport/pid_controller.cc \
src/core/lib/transport/service_config.cc \
src/core/lib/transport/static_metadata.cc \ src/core/lib/transport/static_metadata.cc \
src/core/lib/transport/status_conversion.cc \ src/core/lib/transport/status_conversion.cc \
src/core/lib/transport/status_metadata.cc \ src/core/lib/transport/status_metadata.cc \
@ -4723,6 +4722,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/ext/filters/client_channel/resolving_lb_policy.cc \ src/core/ext/filters/client_channel/resolving_lb_policy.cc \
src/core/ext/filters/client_channel/retry_throttle.cc \ src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \ src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
src/core/ext/filters/client_channel/subchannel.cc \ src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \ src/core/ext/filters/deadline/deadline_filter.cc \
@ -4965,7 +4965,6 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/transport/metadata.cc \ src/core/lib/transport/metadata.cc \
src/core/lib/transport/metadata_batch.cc \ src/core/lib/transport/metadata_batch.cc \
src/core/lib/transport/pid_controller.cc \ src/core/lib/transport/pid_controller.cc \
src/core/lib/transport/service_config.cc \
src/core/lib/transport/static_metadata.cc \ src/core/lib/transport/static_metadata.cc \
src/core/lib/transport/status_conversion.cc \ src/core/lib/transport/status_conversion.cc \
src/core/lib/transport/status_metadata.cc \ src/core/lib/transport/status_metadata.cc \
@ -5032,6 +5031,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/filters/client_channel/resolving_lb_policy.cc \ src/core/ext/filters/client_channel/resolving_lb_policy.cc \
src/core/ext/filters/client_channel/retry_throttle.cc \ src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \ src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
src/core/ext/filters/client_channel/subchannel.cc \ src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \ src/core/ext/filters/deadline/deadline_filter.cc \
@ -5829,7 +5829,6 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/transport/metadata.cc \ src/core/lib/transport/metadata.cc \
src/core/lib/transport/metadata_batch.cc \ src/core/lib/transport/metadata_batch.cc \
src/core/lib/transport/pid_controller.cc \ src/core/lib/transport/pid_controller.cc \
src/core/lib/transport/service_config.cc \
src/core/lib/transport/static_metadata.cc \ src/core/lib/transport/static_metadata.cc \
src/core/lib/transport/status_conversion.cc \ src/core/lib/transport/status_conversion.cc \
src/core/lib/transport/status_metadata.cc \ src/core/lib/transport/status_metadata.cc \
@ -5866,6 +5865,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/ext/filters/client_channel/resolving_lb_policy.cc \ src/core/ext/filters/client_channel/resolving_lb_policy.cc \
src/core/ext/filters/client_channel/retry_throttle.cc \ src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \ src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
src/core/ext/filters/client_channel/subchannel.cc \ src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \ src/core/ext/filters/deadline/deadline_filter.cc \
@ -8230,6 +8230,7 @@ LIBARES_SRC = \
third_party/cares/cares/ares_strcasecmp.c \ third_party/cares/cares/ares_strcasecmp.c \
third_party/cares/cares/ares_strdup.c \ third_party/cares/cares/ares_strdup.c \
third_party/cares/cares/ares_strerror.c \ third_party/cares/cares/ares_strerror.c \
third_party/cares/cares/ares_strsplit.c \
third_party/cares/cares/ares_timeout.c \ third_party/cares/cares/ares_timeout.c \
third_party/cares/cares/ares_version.c \ third_party/cares/cares/ares_version.c \
third_party/cares/cares/ares_writev.c \ third_party/cares/cares/ares_writev.c \

@ -162,8 +162,8 @@ def grpc_deps():
http_archive( http_archive(
name = "com_github_cares_cares", name = "com_github_cares_cares",
build_file = "@com_github_grpc_grpc//third_party:cares/cares.BUILD", build_file = "@com_github_grpc_grpc//third_party:cares/cares.BUILD",
strip_prefix = "c-ares-3be1924221e1326df520f8498d704a5c4c8d0cce", strip_prefix = "c-ares-e982924acee7f7313b4baa4ee5ec000c5e373c30",
url = "https://github.com/c-ares/c-ares/archive/3be1924221e1326df520f8498d704a5c4c8d0cce.tar.gz", url = "https://github.com/c-ares/c-ares/archive/e982924acee7f7313b4baa4ee5ec000c5e373c30.tar.gz",
) )
if "com_google_absl" not in native.existing_rules(): if "com_google_absl" not in native.existing_rules():

@ -372,7 +372,6 @@ filegroups:
- src/core/lib/transport/metadata.cc - src/core/lib/transport/metadata.cc
- src/core/lib/transport/metadata_batch.cc - src/core/lib/transport/metadata_batch.cc
- src/core/lib/transport/pid_controller.cc - src/core/lib/transport/pid_controller.cc
- src/core/lib/transport/service_config.cc
- src/core/lib/transport/static_metadata.cc - src/core/lib/transport/static_metadata.cc
- src/core/lib/transport/status_conversion.cc - src/core/lib/transport/status_conversion.cc
- src/core/lib/transport/status_metadata.cc - src/core/lib/transport/status_metadata.cc
@ -530,7 +529,6 @@ filegroups:
- src/core/lib/transport/metadata.h - src/core/lib/transport/metadata.h
- src/core/lib/transport/metadata_batch.h - src/core/lib/transport/metadata_batch.h
- src/core/lib/transport/pid_controller.h - src/core/lib/transport/pid_controller.h
- src/core/lib/transport/service_config.h
- src/core/lib/transport/static_metadata.h - src/core/lib/transport/static_metadata.h
- src/core/lib/transport/status_conversion.h - src/core/lib/transport/status_conversion.h
- src/core/lib/transport/status_metadata.h - src/core/lib/transport/status_metadata.h
@ -590,6 +588,7 @@ filegroups:
- src/core/ext/filters/client_channel/resolving_lb_policy.h - src/core/ext/filters/client_channel/resolving_lb_policy.h
- src/core/ext/filters/client_channel/retry_throttle.h - src/core/ext/filters/client_channel/retry_throttle.h
- src/core/ext/filters/client_channel/server_address.h - src/core/ext/filters/client_channel/server_address.h
- src/core/ext/filters/client_channel/service_config.h
- src/core/ext/filters/client_channel/subchannel.h - src/core/ext/filters/client_channel/subchannel.h
- src/core/ext/filters/client_channel/subchannel_pool_interface.h - src/core/ext/filters/client_channel/subchannel_pool_interface.h
src: src:
@ -616,6 +615,7 @@ filegroups:
- src/core/ext/filters/client_channel/resolving_lb_policy.cc - src/core/ext/filters/client_channel/resolving_lb_policy.cc
- src/core/ext/filters/client_channel/retry_throttle.cc - src/core/ext/filters/client_channel/retry_throttle.cc
- src/core/ext/filters/client_channel/server_address.cc - src/core/ext/filters/client_channel/server_address.cc
- src/core/ext/filters/client_channel/service_config.cc
- src/core/ext/filters/client_channel/subchannel.cc - src/core/ext/filters/client_channel/subchannel.cc
- src/core/ext/filters/client_channel/subchannel_pool_interface.cc - src/core/ext/filters/client_channel/subchannel_pool_interface.cc
plugin: grpc_client_channel plugin: grpc_client_channel

@ -226,7 +226,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/transport/metadata.cc \ src/core/lib/transport/metadata.cc \
src/core/lib/transport/metadata_batch.cc \ src/core/lib/transport/metadata_batch.cc \
src/core/lib/transport/pid_controller.cc \ src/core/lib/transport/pid_controller.cc \
src/core/lib/transport/service_config.cc \
src/core/lib/transport/static_metadata.cc \ src/core/lib/transport/static_metadata.cc \
src/core/lib/transport/status_conversion.cc \ src/core/lib/transport/status_conversion.cc \
src/core/lib/transport/status_metadata.cc \ src/core/lib/transport/status_metadata.cc \
@ -362,6 +361,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/resolving_lb_policy.cc \ src/core/ext/filters/client_channel/resolving_lb_policy.cc \
src/core/ext/filters/client_channel/retry_throttle.cc \ src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \ src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
src/core/ext/filters/client_channel/subchannel.cc \ src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \ src/core/ext/filters/deadline/deadline_filter.cc \

@ -201,7 +201,6 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\transport\\metadata.cc " + "src\\core\\lib\\transport\\metadata.cc " +
"src\\core\\lib\\transport\\metadata_batch.cc " + "src\\core\\lib\\transport\\metadata_batch.cc " +
"src\\core\\lib\\transport\\pid_controller.cc " + "src\\core\\lib\\transport\\pid_controller.cc " +
"src\\core\\lib\\transport\\service_config.cc " +
"src\\core\\lib\\transport\\static_metadata.cc " + "src\\core\\lib\\transport\\static_metadata.cc " +
"src\\core\\lib\\transport\\status_conversion.cc " + "src\\core\\lib\\transport\\status_conversion.cc " +
"src\\core\\lib\\transport\\status_metadata.cc " + "src\\core\\lib\\transport\\status_metadata.cc " +
@ -337,6 +336,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\resolving_lb_policy.cc " + "src\\core\\ext\\filters\\client_channel\\resolving_lb_policy.cc " +
"src\\core\\ext\\filters\\client_channel\\retry_throttle.cc " + "src\\core\\ext\\filters\\client_channel\\retry_throttle.cc " +
"src\\core\\ext\\filters\\client_channel\\server_address.cc " + "src\\core\\ext\\filters\\client_channel\\server_address.cc " +
"src\\core\\ext\\filters\\client_channel\\service_config.cc " +
"src\\core\\ext\\filters\\client_channel\\subchannel.cc " + "src\\core\\ext\\filters\\client_channel\\subchannel.cc " +
"src\\core\\ext\\filters\\client_channel\\subchannel_pool_interface.cc " + "src\\core\\ext\\filters\\client_channel\\subchannel_pool_interface.cc " +
"src\\core\\ext\\filters\\deadline\\deadline_filter.cc " + "src\\core\\ext\\filters\\deadline\\deadline_filter.cc " +

@ -124,9 +124,10 @@ some configuration as environment variables that can be set.
Declares which DNS resolver to use. The default is ares if gRPC is built with Declares which DNS resolver to use. The default is ares if gRPC is built with
c-ares support. Otherwise, the value of this environment variable is ignored. c-ares support. Otherwise, the value of this environment variable is ignored.
Available DNS resolver include: Available DNS resolver include:
- native (default)- a DNS resolver based around getaddrinfo(), creates a new thread to - ares (default on most platforms except iOS, Android or Node)- a DNS
resolver based around the c-ares library
- native - a DNS resolver based around getaddrinfo(), creates a new thread to
perform name resolution perform name resolution
- ares - a DNS resolver based around the c-ares library
* GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS * GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS
Default: 5000 Default: 5000

@ -368,6 +368,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/resolving_lb_policy.h', 'src/core/ext/filters/client_channel/resolving_lb_policy.h',
'src/core/ext/filters/client_channel/retry_throttle.h', 'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.h', 'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/service_config.h',
'src/core/ext/filters/client_channel/subchannel.h', 'src/core/ext/filters/client_channel/subchannel.h',
'src/core/ext/filters/client_channel/subchannel_pool_interface.h', 'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
'src/core/ext/filters/deadline/deadline_filter.h', 'src/core/ext/filters/deadline/deadline_filter.h',
@ -510,7 +511,6 @@ Pod::Spec.new do |s|
'src/core/lib/transport/metadata.h', 'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h', 'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/pid_controller.h', 'src/core/lib/transport/pid_controller.h',
'src/core/lib/transport/service_config.h',
'src/core/lib/transport/static_metadata.h', 'src/core/lib/transport/static_metadata.h',
'src/core/lib/transport/status_conversion.h', 'src/core/lib/transport/status_conversion.h',
'src/core/lib/transport/status_metadata.h', 'src/core/lib/transport/status_metadata.h',
@ -701,7 +701,6 @@ Pod::Spec.new do |s|
'src/core/lib/transport/metadata.h', 'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h', 'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/pid_controller.h', 'src/core/lib/transport/pid_controller.h',
'src/core/lib/transport/service_config.h',
'src/core/lib/transport/static_metadata.h', 'src/core/lib/transport/static_metadata.h',
'src/core/lib/transport/status_conversion.h', 'src/core/lib/transport/status_conversion.h',
'src/core/lib/transport/status_metadata.h', 'src/core/lib/transport/status_metadata.h',

@ -361,6 +361,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/resolving_lb_policy.h', 'src/core/ext/filters/client_channel/resolving_lb_policy.h',
'src/core/ext/filters/client_channel/retry_throttle.h', 'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.h', 'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/service_config.h',
'src/core/ext/filters/client_channel/subchannel.h', 'src/core/ext/filters/client_channel/subchannel.h',
'src/core/ext/filters/client_channel/subchannel_pool_interface.h', 'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
'src/core/ext/filters/deadline/deadline_filter.h', 'src/core/ext/filters/deadline/deadline_filter.h',
@ -503,7 +504,6 @@ Pod::Spec.new do |s|
'src/core/lib/transport/metadata.h', 'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h', 'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/pid_controller.h', 'src/core/lib/transport/pid_controller.h',
'src/core/lib/transport/service_config.h',
'src/core/lib/transport/static_metadata.h', 'src/core/lib/transport/static_metadata.h',
'src/core/lib/transport/status_conversion.h', 'src/core/lib/transport/status_conversion.h',
'src/core/lib/transport/status_metadata.h', 'src/core/lib/transport/status_metadata.h',
@ -674,7 +674,6 @@ Pod::Spec.new do |s|
'src/core/lib/transport/metadata.cc', 'src/core/lib/transport/metadata.cc',
'src/core/lib/transport/metadata_batch.cc', 'src/core/lib/transport/metadata_batch.cc',
'src/core/lib/transport/pid_controller.cc', 'src/core/lib/transport/pid_controller.cc',
'src/core/lib/transport/service_config.cc',
'src/core/lib/transport/static_metadata.cc', 'src/core/lib/transport/static_metadata.cc',
'src/core/lib/transport/status_conversion.cc', 'src/core/lib/transport/status_conversion.cc',
'src/core/lib/transport/status_metadata.cc', 'src/core/lib/transport/status_metadata.cc',
@ -807,6 +806,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/resolving_lb_policy.cc', 'src/core/ext/filters/client_channel/resolving_lb_policy.cc',
'src/core/ext/filters/client_channel/retry_throttle.cc', 'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc', 'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/service_config.cc',
'src/core/ext/filters/client_channel/subchannel.cc', 'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc', 'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/deadline/deadline_filter.cc', 'src/core/ext/filters/deadline/deadline_filter.cc',
@ -991,6 +991,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/resolving_lb_policy.h', 'src/core/ext/filters/client_channel/resolving_lb_policy.h',
'src/core/ext/filters/client_channel/retry_throttle.h', 'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.h', 'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/service_config.h',
'src/core/ext/filters/client_channel/subchannel.h', 'src/core/ext/filters/client_channel/subchannel.h',
'src/core/ext/filters/client_channel/subchannel_pool_interface.h', 'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
'src/core/ext/filters/deadline/deadline_filter.h', 'src/core/ext/filters/deadline/deadline_filter.h',
@ -1133,7 +1134,6 @@ Pod::Spec.new do |s|
'src/core/lib/transport/metadata.h', 'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h', 'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/pid_controller.h', 'src/core/lib/transport/pid_controller.h',
'src/core/lib/transport/service_config.h',
'src/core/lib/transport/static_metadata.h', 'src/core/lib/transport/static_metadata.h',
'src/core/lib/transport/status_conversion.h', 'src/core/lib/transport/status_conversion.h',
'src/core/lib/transport/status_metadata.h', 'src/core/lib/transport/status_metadata.h',
@ -1235,7 +1235,6 @@ Pod::Spec.new do |s|
'test/core/util/port_isolated_runtime_environment.cc', 'test/core/util/port_isolated_runtime_environment.cc',
'test/core/util/port_server_client.cc', 'test/core/util/port_server_client.cc',
'test/core/util/slice_splitter.cc', 'test/core/util/slice_splitter.cc',
'test/core/util/subprocess_posix.cc',
'test/core/util/subprocess_windows.cc', 'test/core/util/subprocess_windows.cc',
'test/core/util/test_config.cc', 'test/core/util/test_config.cc',
'test/core/util/test_lb_policies.cc', 'test/core/util/test_lb_policies.cc',

@ -295,6 +295,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/resolving_lb_policy.h ) s.files += %w( src/core/ext/filters/client_channel/resolving_lb_policy.h )
s.files += %w( src/core/ext/filters/client_channel/retry_throttle.h ) s.files += %w( src/core/ext/filters/client_channel/retry_throttle.h )
s.files += %w( src/core/ext/filters/client_channel/server_address.h ) s.files += %w( src/core/ext/filters/client_channel/server_address.h )
s.files += %w( src/core/ext/filters/client_channel/service_config.h )
s.files += %w( src/core/ext/filters/client_channel/subchannel.h ) s.files += %w( src/core/ext/filters/client_channel/subchannel.h )
s.files += %w( src/core/ext/filters/client_channel/subchannel_pool_interface.h ) s.files += %w( src/core/ext/filters/client_channel/subchannel_pool_interface.h )
s.files += %w( src/core/ext/filters/deadline/deadline_filter.h ) s.files += %w( src/core/ext/filters/deadline/deadline_filter.h )
@ -437,7 +438,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/metadata.h ) s.files += %w( src/core/lib/transport/metadata.h )
s.files += %w( src/core/lib/transport/metadata_batch.h ) s.files += %w( src/core/lib/transport/metadata_batch.h )
s.files += %w( src/core/lib/transport/pid_controller.h ) s.files += %w( src/core/lib/transport/pid_controller.h )
s.files += %w( src/core/lib/transport/service_config.h )
s.files += %w( src/core/lib/transport/static_metadata.h ) s.files += %w( src/core/lib/transport/static_metadata.h )
s.files += %w( src/core/lib/transport/status_conversion.h ) s.files += %w( src/core/lib/transport/status_conversion.h )
s.files += %w( src/core/lib/transport/status_metadata.h ) s.files += %w( src/core/lib/transport/status_metadata.h )
@ -608,7 +608,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/metadata.cc ) s.files += %w( src/core/lib/transport/metadata.cc )
s.files += %w( src/core/lib/transport/metadata_batch.cc ) s.files += %w( src/core/lib/transport/metadata_batch.cc )
s.files += %w( src/core/lib/transport/pid_controller.cc ) s.files += %w( src/core/lib/transport/pid_controller.cc )
s.files += %w( src/core/lib/transport/service_config.cc )
s.files += %w( src/core/lib/transport/static_metadata.cc ) s.files += %w( src/core/lib/transport/static_metadata.cc )
s.files += %w( src/core/lib/transport/status_conversion.cc ) s.files += %w( src/core/lib/transport/status_conversion.cc )
s.files += %w( src/core/lib/transport/status_metadata.cc ) s.files += %w( src/core/lib/transport/status_metadata.cc )
@ -744,6 +743,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/resolving_lb_policy.cc ) s.files += %w( src/core/ext/filters/client_channel/resolving_lb_policy.cc )
s.files += %w( src/core/ext/filters/client_channel/retry_throttle.cc ) s.files += %w( src/core/ext/filters/client_channel/retry_throttle.cc )
s.files += %w( src/core/ext/filters/client_channel/server_address.cc ) s.files += %w( src/core/ext/filters/client_channel/server_address.cc )
s.files += %w( src/core/ext/filters/client_channel/service_config.cc )
s.files += %w( src/core/ext/filters/client_channel/subchannel.cc ) s.files += %w( src/core/ext/filters/client_channel/subchannel.cc )
s.files += %w( src/core/ext/filters/client_channel/subchannel_pool_interface.cc ) s.files += %w( src/core/ext/filters/client_channel/subchannel_pool_interface.cc )
s.files += %w( src/core/ext/filters/deadline/deadline_filter.cc ) s.files += %w( src/core/ext/filters/deadline/deadline_filter.cc )
@ -1266,6 +1266,7 @@ Gem::Specification.new do |s|
s.files += %w( third_party/cares/cares/ares_setup.h ) s.files += %w( third_party/cares/cares/ares_setup.h )
s.files += %w( third_party/cares/cares/ares_strcasecmp.h ) s.files += %w( third_party/cares/cares/ares_strcasecmp.h )
s.files += %w( third_party/cares/cares/ares_strdup.h ) s.files += %w( third_party/cares/cares/ares_strdup.h )
s.files += %w( third_party/cares/cares/ares_strsplit.h )
s.files += %w( third_party/cares/cares/ares_version.h ) s.files += %w( third_party/cares/cares/ares_version.h )
s.files += %w( third_party/cares/cares/bitncmp.h ) s.files += %w( third_party/cares/cares/bitncmp.h )
s.files += %w( third_party/cares/cares/config-win32.h ) s.files += %w( third_party/cares/cares/config-win32.h )
@ -1317,6 +1318,7 @@ Gem::Specification.new do |s|
s.files += %w( third_party/cares/cares/ares_strcasecmp.c ) s.files += %w( third_party/cares/cares/ares_strcasecmp.c )
s.files += %w( third_party/cares/cares/ares_strdup.c ) s.files += %w( third_party/cares/cares/ares_strdup.c )
s.files += %w( third_party/cares/cares/ares_strerror.c ) s.files += %w( third_party/cares/cares/ares_strerror.c )
s.files += %w( third_party/cares/cares/ares_strsplit.c )
s.files += %w( third_party/cares/cares/ares_timeout.c ) s.files += %w( third_party/cares/cares/ares_timeout.c )
s.files += %w( third_party/cares/cares/ares_version.c ) s.files += %w( third_party/cares/cares/ares_version.c )
s.files += %w( third_party/cares/cares/ares_writev.c ) s.files += %w( third_party/cares/cares/ares_writev.c )

@ -408,7 +408,6 @@
'src/core/lib/transport/metadata.cc', 'src/core/lib/transport/metadata.cc',
'src/core/lib/transport/metadata_batch.cc', 'src/core/lib/transport/metadata_batch.cc',
'src/core/lib/transport/pid_controller.cc', 'src/core/lib/transport/pid_controller.cc',
'src/core/lib/transport/service_config.cc',
'src/core/lib/transport/static_metadata.cc', 'src/core/lib/transport/static_metadata.cc',
'src/core/lib/transport/status_conversion.cc', 'src/core/lib/transport/status_conversion.cc',
'src/core/lib/transport/status_metadata.cc', 'src/core/lib/transport/status_metadata.cc',
@ -544,6 +543,7 @@
'src/core/ext/filters/client_channel/resolving_lb_policy.cc', 'src/core/ext/filters/client_channel/resolving_lb_policy.cc',
'src/core/ext/filters/client_channel/retry_throttle.cc', 'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc', 'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/service_config.cc',
'src/core/ext/filters/client_channel/subchannel.cc', 'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc', 'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/deadline/deadline_filter.cc', 'src/core/ext/filters/deadline/deadline_filter.cc',
@ -775,7 +775,6 @@
'src/core/lib/transport/metadata.cc', 'src/core/lib/transport/metadata.cc',
'src/core/lib/transport/metadata_batch.cc', 'src/core/lib/transport/metadata_batch.cc',
'src/core/lib/transport/pid_controller.cc', 'src/core/lib/transport/pid_controller.cc',
'src/core/lib/transport/service_config.cc',
'src/core/lib/transport/static_metadata.cc', 'src/core/lib/transport/static_metadata.cc',
'src/core/lib/transport/status_conversion.cc', 'src/core/lib/transport/status_conversion.cc',
'src/core/lib/transport/status_metadata.cc', 'src/core/lib/transport/status_metadata.cc',
@ -807,6 +806,7 @@
'src/core/ext/filters/client_channel/resolving_lb_policy.cc', 'src/core/ext/filters/client_channel/resolving_lb_policy.cc',
'src/core/ext/filters/client_channel/retry_throttle.cc', 'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc', 'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/service_config.cc',
'src/core/ext/filters/client_channel/subchannel.cc', 'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc', 'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/deadline/deadline_filter.cc', 'src/core/ext/filters/deadline/deadline_filter.cc',
@ -1019,7 +1019,6 @@
'src/core/lib/transport/metadata.cc', 'src/core/lib/transport/metadata.cc',
'src/core/lib/transport/metadata_batch.cc', 'src/core/lib/transport/metadata_batch.cc',
'src/core/lib/transport/pid_controller.cc', 'src/core/lib/transport/pid_controller.cc',
'src/core/lib/transport/service_config.cc',
'src/core/lib/transport/static_metadata.cc', 'src/core/lib/transport/static_metadata.cc',
'src/core/lib/transport/status_conversion.cc', 'src/core/lib/transport/status_conversion.cc',
'src/core/lib/transport/status_metadata.cc', 'src/core/lib/transport/status_metadata.cc',
@ -1051,6 +1050,7 @@
'src/core/ext/filters/client_channel/resolving_lb_policy.cc', 'src/core/ext/filters/client_channel/resolving_lb_policy.cc',
'src/core/ext/filters/client_channel/retry_throttle.cc', 'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc', 'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/service_config.cc',
'src/core/ext/filters/client_channel/subchannel.cc', 'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc', 'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/deadline/deadline_filter.cc', 'src/core/ext/filters/deadline/deadline_filter.cc',
@ -1239,7 +1239,6 @@
'src/core/lib/transport/metadata.cc', 'src/core/lib/transport/metadata.cc',
'src/core/lib/transport/metadata_batch.cc', 'src/core/lib/transport/metadata_batch.cc',
'src/core/lib/transport/pid_controller.cc', 'src/core/lib/transport/pid_controller.cc',
'src/core/lib/transport/service_config.cc',
'src/core/lib/transport/static_metadata.cc', 'src/core/lib/transport/static_metadata.cc',
'src/core/lib/transport/status_conversion.cc', 'src/core/lib/transport/status_conversion.cc',
'src/core/lib/transport/status_metadata.cc', 'src/core/lib/transport/status_metadata.cc',
@ -1306,6 +1305,7 @@
'src/core/ext/filters/client_channel/resolving_lb_policy.cc', 'src/core/ext/filters/client_channel/resolving_lb_policy.cc',
'src/core/ext/filters/client_channel/retry_throttle.cc', 'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc', 'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/service_config.cc',
'src/core/ext/filters/client_channel/subchannel.cc', 'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc', 'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/deadline/deadline_filter.cc', 'src/core/ext/filters/deadline/deadline_filter.cc',

@ -73,10 +73,15 @@ class GenericStub final {
public: public:
explicit experimental_type(GenericStub* stub) : stub_(stub) {} explicit experimental_type(GenericStub* stub) : stub_(stub) {}
/// Setup and start a unary call to a named method \a method using
/// \a context and specifying the \a request and \a response buffers.
void UnaryCall(ClientContext* context, const grpc::string& method, void UnaryCall(ClientContext* context, const grpc::string& method,
const ByteBuffer* request, ByteBuffer* response, const ByteBuffer* request, ByteBuffer* response,
std::function<void(Status)> on_completion); std::function<void(Status)> on_completion);
/// Setup a call to a named method \a method using \a context and tied to
/// \a reactor . Like any other bidi streaming RPC, it will not be activated
/// until StartCall is invoked on its reactor.
void PrepareBidiStreamingCall( void PrepareBidiStreamingCall(
ClientContext* context, const grpc::string& method, ClientContext* context, const grpc::string& method,
experimental::ClientBidiReactor<ByteBuffer, ByteBuffer>* reactor); experimental::ClientBidiReactor<ByteBuffer, ByteBuffer>* reactor);

@ -85,13 +85,23 @@ class AsyncGenericService final {
namespace experimental { namespace experimental {
/// \a ServerGenericBidiReactor is the reactor class for bidi streaming RPCs
/// invoked on a CallbackGenericService. The API difference relative to
/// ServerBidiReactor is that the argument to OnStarted is a
/// GenericServerContext rather than a ServerContext. All other reaction and
/// operation initiation APIs are the same as ServerBidiReactor.
class ServerGenericBidiReactor class ServerGenericBidiReactor
: public ServerBidiReactor<ByteBuffer, ByteBuffer> { : public ServerBidiReactor<ByteBuffer, ByteBuffer> {
public: public:
/// Similar to ServerBidiReactor::OnStarted except for argument type.
///
/// \param[in] context The context object associated with this RPC.
virtual void OnStarted(GenericServerContext* context) {}
private:
void OnStarted(ServerContext* ctx) final { void OnStarted(ServerContext* ctx) final {
OnStarted(static_cast<GenericServerContext*>(ctx)); OnStarted(static_cast<GenericServerContext*>(ctx));
} }
virtual void OnStarted(GenericServerContext* ctx) {}
}; };
} // namespace experimental } // namespace experimental
@ -108,10 +118,18 @@ class UnimplementedGenericBidiReactor
} // namespace internal } // namespace internal
namespace experimental { namespace experimental {
/// \a CallbackGenericService is the base class for generic services implemented
/// using the callback API and registered through the ServerBuilder using
/// RegisterCallbackGenericService.
class CallbackGenericService { class CallbackGenericService {
public: public:
CallbackGenericService() {} CallbackGenericService() {}
virtual ~CallbackGenericService() {} virtual ~CallbackGenericService() {}
/// The "method handler" for the generic API. This function should be
/// overridden to return a ServerGenericBidiReactor that implements the
/// application-level interface for this RPC.
virtual ServerGenericBidiReactor* CreateReactor() { virtual ServerGenericBidiReactor* CreateReactor() {
return new internal::UnimplementedGenericBidiReactor; return new internal::UnimplementedGenericBidiReactor;
} }

@ -157,28 +157,69 @@ class ClientCallbackWriter {
} }
}; };
// The user must implement this reactor interface with reactions to each event // The following classes are the reactor interfaces that are to be implemented
// type that gets called by the library. An empty reaction is provided by // by the user. They are passed in to the library as an argument to a call on a
// default // stub (either a codegen-ed call or a generic call). The streaming RPC is
// activated by calling StartCall, possibly after initiating StartRead,
// StartWrite, or AddHold operations on the streaming object. Note that none of
// the classes are pure; all reactions have a default empty reaction so that the
// user class only needs to override those classes that it cares about.
/// \a ClientBidiReactor is the interface for a bidirectional streaming RPC.
template <class Request, class Response> template <class Request, class Response>
class ClientBidiReactor { class ClientBidiReactor {
public: public:
virtual ~ClientBidiReactor() {} virtual ~ClientBidiReactor() {}
virtual void OnDone(const Status& s) {}
virtual void OnReadInitialMetadataDone(bool ok) {}
virtual void OnReadDone(bool ok) {}
virtual void OnWriteDone(bool ok) {}
virtual void OnWritesDoneDone(bool ok) {}
/// Activate the RPC and initiate any reads or writes that have been Start'ed
/// before this call. All streaming RPCs issued by the client MUST have
/// StartCall invoked on them (even if they are canceled) as this call is the
/// activation of their lifecycle.
void StartCall() { stream_->StartCall(); } void StartCall() { stream_->StartCall(); }
/// Initiate a read operation (or post it for later initiation if StartCall
/// has not yet been invoked).
///
/// \param[out] resp Where to eventually store the read message. Valid when
/// the library calls OnReadDone
void StartRead(Response* resp) { stream_->Read(resp); } void StartRead(Response* resp) { stream_->Read(resp); }
/// Initiate a write operation (or post it for later initiation if StartCall
/// has not yet been invoked).
///
/// \param[in] req The message to be written. The library takes temporary
/// ownership until OnWriteDone, at which point the application
/// regains ownership of msg.
void StartWrite(const Request* req) { StartWrite(req, WriteOptions()); } void StartWrite(const Request* req) { StartWrite(req, WriteOptions()); }
/// Initiate/post a write operation with specified options.
///
/// \param[in] req The message to be written. The library takes temporary
/// ownership until OnWriteDone, at which point the application
/// regains ownership of msg.
/// \param[in] options The WriteOptions to use for writing this message
void StartWrite(const Request* req, WriteOptions options) { void StartWrite(const Request* req, WriteOptions options) {
stream_->Write(req, std::move(options)); stream_->Write(req, std::move(options));
} }
/// Initiate/post a write operation with specified options and an indication
/// that this is the last write (like StartWrite and StartWritesDone, merged).
/// Note that calling this means that no more calls to StartWrite,
/// StartWriteLast, or StartWritesDone are allowed.
///
/// \param[in] req The message to be written. The library takes temporary
/// ownership until OnWriteDone, at which point the application
/// regains ownership of msg.
/// \param[in] options The WriteOptions to use for writing this message
void StartWriteLast(const Request* req, WriteOptions options) { void StartWriteLast(const Request* req, WriteOptions options) {
StartWrite(req, std::move(options.set_last_message())); StartWrite(req, std::move(options.set_last_message()));
} }
/// Indicate that the RPC will have no more write operations. This can only be
/// issued once for a given RPC. This is not required or allowed if
/// StartWriteLast is used since that already has the same implication.
/// Note that calling this means that no more calls to StartWrite,
/// StartWriteLast, or StartWritesDone are allowed.
void StartWritesDone() { stream_->WritesDone(); } void StartWritesDone() { stream_->WritesDone(); }
/// Holds are needed if (and only if) this stream has operations that take /// Holds are needed if (and only if) this stream has operations that take
@ -196,14 +237,51 @@ class ClientBidiReactor {
/// AddHold or AddMultipleHolds before StartCall. If there is going to be, /// AddHold or AddMultipleHolds before StartCall. If there is going to be,
/// for example, a read-flow and a write-flow taking place outside the /// for example, a read-flow and a write-flow taking place outside the
/// reactions, then call AddMultipleHolds(2) before StartCall. When the /// reactions, then call AddMultipleHolds(2) before StartCall. When the
/// application knows that it won't issue any more Read operations (such as /// application knows that it won't issue any more read operations (such as
/// when a read comes back as not ok), it should issue a RemoveHold(). It /// when a read comes back as not ok), it should issue a RemoveHold(). It
/// should also call RemoveHold() again after it does StartWriteLast or /// should also call RemoveHold() again after it does StartWriteLast or
/// StartWritesDone that indicates that there will be no more Write ops. /// StartWritesDone that indicates that there will be no more write ops.
/// The number of RemoveHold calls must match the total number of AddHold
/// calls plus the number of holds added by AddMultipleHolds.
void AddHold() { AddMultipleHolds(1); } void AddHold() { AddMultipleHolds(1); }
void AddMultipleHolds(int holds) { stream_->AddHold(holds); } void AddMultipleHolds(int holds) { stream_->AddHold(holds); }
void RemoveHold() { stream_->RemoveHold(); } void RemoveHold() { stream_->RemoveHold(); }
/// Notifies the application that all operations associated with this RPC
/// have completed and provides the RPC status outcome.
///
/// \param[in] s The status outcome of this RPC
virtual void OnDone(const Status& s) {}
/// Notifies the application that a read of initial metadata from the
/// server is done. If the application chooses not to implement this method,
/// it can assume that the initial metadata has been read before the first
/// call of OnReadDone or OnDone.
///
/// \param[in] ok Was the initial metadata read successfully? If false, no
/// further read-side operation will succeed.
virtual void OnReadInitialMetadataDone(bool ok) {}
/// Notifies the application that a StartRead operation completed.
///
/// \param[in] ok Was it successful? If false, no further read-side operation
/// will succeed.
virtual void OnReadDone(bool ok) {}
/// Notifies the application that a StartWrite operation completed.
///
/// \param[in] ok Was it successful? If false, no further write-side operation
/// will succeed.
virtual void OnWriteDone(bool ok) {}
/// Notifies the application that a StartWritesDone operation completed. Note
/// that this is only used on explicit StartWritesDone operations and not for
/// those that are implicitly invoked as part of a StartWriteLast.
///
/// \param[in] ok Was it successful? If false, the application will later see
/// the failure reflected as a bad status in OnDone.
virtual void OnWritesDoneDone(bool ok) {}
private: private:
friend class ClientCallbackReaderWriter<Request, Response>; friend class ClientCallbackReaderWriter<Request, Response>;
void BindStream(ClientCallbackReaderWriter<Request, Response>* stream) { void BindStream(ClientCallbackReaderWriter<Request, Response>* stream) {
@ -212,13 +290,12 @@ class ClientBidiReactor {
ClientCallbackReaderWriter<Request, Response>* stream_; ClientCallbackReaderWriter<Request, Response>* stream_;
}; };
/// \a ClientReadReactor is the interface for a server-streaming RPC.
/// All public methods behave as in ClientBidiReactor.
template <class Response> template <class Response>
class ClientReadReactor { class ClientReadReactor {
public: public:
virtual ~ClientReadReactor() {} virtual ~ClientReadReactor() {}
virtual void OnDone(const Status& s) {}
virtual void OnReadInitialMetadataDone(bool ok) {}
virtual void OnReadDone(bool ok) {}
void StartCall() { reader_->StartCall(); } void StartCall() { reader_->StartCall(); }
void StartRead(Response* resp) { reader_->Read(resp); } void StartRead(Response* resp) { reader_->Read(resp); }
@ -227,20 +304,22 @@ class ClientReadReactor {
void AddMultipleHolds(int holds) { reader_->AddHold(holds); } void AddMultipleHolds(int holds) { reader_->AddHold(holds); }
void RemoveHold() { reader_->RemoveHold(); } void RemoveHold() { reader_->RemoveHold(); }
virtual void OnDone(const Status& s) {}
virtual void OnReadInitialMetadataDone(bool ok) {}
virtual void OnReadDone(bool ok) {}
private: private:
friend class ClientCallbackReader<Response>; friend class ClientCallbackReader<Response>;
void BindReader(ClientCallbackReader<Response>* reader) { reader_ = reader; } void BindReader(ClientCallbackReader<Response>* reader) { reader_ = reader; }
ClientCallbackReader<Response>* reader_; ClientCallbackReader<Response>* reader_;
}; };
/// \a ClientWriteReactor is the interface for a client-streaming RPC.
/// All public methods behave as in ClientBidiReactor.
template <class Request> template <class Request>
class ClientWriteReactor { class ClientWriteReactor {
public: public:
virtual ~ClientWriteReactor() {} virtual ~ClientWriteReactor() {}
virtual void OnDone(const Status& s) {}
virtual void OnReadInitialMetadataDone(bool ok) {}
virtual void OnWriteDone(bool ok) {}
virtual void OnWritesDoneDone(bool ok) {}
void StartCall() { writer_->StartCall(); } void StartCall() { writer_->StartCall(); }
void StartWrite(const Request* req) { StartWrite(req, WriteOptions()); } void StartWrite(const Request* req) { StartWrite(req, WriteOptions()); }
@ -256,6 +335,11 @@ class ClientWriteReactor {
void AddMultipleHolds(int holds) { writer_->AddHold(holds); } void AddMultipleHolds(int holds) { writer_->AddHold(holds); }
void RemoveHold() { writer_->RemoveHold(); } void RemoveHold() { writer_->RemoveHold(); }
virtual void OnDone(const Status& s) {}
virtual void OnReadInitialMetadataDone(bool ok) {}
virtual void OnWriteDone(bool ok) {}
virtual void OnWritesDoneDone(bool ok) {}
private: private:
friend class ClientCallbackWriter<Request>; friend class ClientCallbackWriter<Request>;
void BindWriter(ClientCallbackWriter<Request>* writer) { writer_ = writer; } void BindWriter(ClientCallbackWriter<Request>* writer) { writer_ = writer; }

@ -46,7 +46,7 @@ class MethodHandler {
/// \param context : the ServerContext structure for this server call /// \param context : the ServerContext structure for this server call
/// \param req : the request payload, if appropriate for this RPC /// \param req : the request payload, if appropriate for this RPC
/// \param req_status : the request status after any interceptors have run /// \param req_status : the request status after any interceptors have run
/// \param rpc_requester : used only by the callback API. It is a function /// \param requester : used only by the callback API. It is a function
/// called by the RPC Controller to request another RPC (and also /// called by the RPC Controller to request another RPC (and also
/// to set up the state required to make that request possible) /// to set up the state required to make that request possible)
HandlerParameter(Call* c, ServerContext* context, void* req, HandlerParameter(Call* c, ServerContext* context, void* req,

@ -40,8 +40,8 @@ namespace internal {
class ServerReactor { class ServerReactor {
public: public:
virtual ~ServerReactor() = default; virtual ~ServerReactor() = default;
virtual void OnDone() {} virtual void OnDone() = 0;
virtual void OnCancel() {} virtual void OnCancel() = 0;
}; };
} // namespace internal } // namespace internal
@ -167,33 +167,120 @@ class ServerCallbackReaderWriter {
} }
}; };
// The following classes are reactors that are to be implemented // The following classes are the reactor interfaces that are to be implemented
// by the user, returned as the result of the method handler for // by the user, returned as the result of the method handler for a callback
// a callback method, and activated by the call to OnStarted // method, and activated by the call to OnStarted. Note that none of the classes
// are pure; all reactions have a default empty reaction so that the user class
// only needs to override those classes that it cares about.
/// \a ServerBidiReactor is the interface for a bidirectional streaming RPC.
template <class Request, class Response> template <class Request, class Response>
class ServerBidiReactor : public internal::ServerReactor { class ServerBidiReactor : public internal::ServerReactor {
public: public:
~ServerBidiReactor() = default; ~ServerBidiReactor() = default;
virtual void OnStarted(ServerContext*) {}
virtual void OnSendInitialMetadataDone(bool ok) {}
virtual void OnReadDone(bool ok) {}
virtual void OnWriteDone(bool ok) {}
/// Send any initial metadata stored in the RPC context. If not invoked,
/// any initial metadata will be passed along with the first Write or the
/// Finish (if there are no writes).
void StartSendInitialMetadata() { stream_->SendInitialMetadata(); } void StartSendInitialMetadata() { stream_->SendInitialMetadata(); }
void StartRead(Request* msg) { stream_->Read(msg); }
void StartWrite(const Response* msg) { StartWrite(msg, WriteOptions()); } /// Initiate a read operation.
void StartWrite(const Response* msg, WriteOptions options) { ///
stream_->Write(msg, std::move(options)); /// \param[out] req Where to eventually store the read message. Valid when
/// the library calls OnReadDone
void StartRead(Request* req) { stream_->Read(req); }
/// Initiate a write operation.
///
/// \param[in] resp The message to be written. The library takes temporary
/// ownership until OnWriteDone, at which point the
/// application regains ownership of resp.
void StartWrite(const Response* resp) { StartWrite(resp, WriteOptions()); }
/// Initiate a write operation with specified options.
///
/// \param[in] resp The message to be written. The library takes temporary
/// ownership until OnWriteDone, at which point the
/// application regains ownership of resp.
/// \param[in] options The WriteOptions to use for writing this message
void StartWrite(const Response* resp, WriteOptions options) {
stream_->Write(resp, std::move(options));
} }
void StartWriteAndFinish(const Response* msg, WriteOptions options,
/// Initiate a write operation with specified options and final RPC Status,
/// which also causes any trailing metadata for this RPC to be sent out.
/// StartWriteAndFinish is like merging StartWriteLast and Finish into a
/// single step. A key difference, though, is that this operation doesn't have
/// an OnWriteDone reaction - it is considered complete only when OnDone is
/// available. An RPC can either have StartWriteAndFinish or Finish, but not
/// both.
///
/// \param[in] resp The message to be written. The library takes temporary
/// ownership until Onone, at which point the application
/// regains ownership of resp.
/// \param[in] options The WriteOptions to use for writing this message
/// \param[in] s The status outcome of this RPC
void StartWriteAndFinish(const Response* resp, WriteOptions options,
Status s) { Status s) {
stream_->WriteAndFinish(msg, std::move(options), std::move(s)); stream_->WriteAndFinish(resp, std::move(options), std::move(s));
} }
void StartWriteLast(const Response* msg, WriteOptions options) {
StartWrite(msg, std::move(options.set_last_message())); /// Inform system of a planned write operation with specified options, but
/// allow the library to schedule the actual write coalesced with the writing
/// of trailing metadata (which takes place on a Finish call).
///
/// \param[in] resp The message to be written. The library takes temporary
/// ownership until OnWriteDone, at which point the
/// application regains ownership of resp.
/// \param[in] options The WriteOptions to use for writing this message
void StartWriteLast(const Response* resp, WriteOptions options) {
StartWrite(resp, std::move(options.set_last_message()));
} }
/// Indicate that the stream is to be finished and the trailing metadata and
/// RPC status are to be sent. Every RPC MUST be finished using either Finish
/// or StartWriteAndFinish (but not both), even if the RPC is already
/// cancelled.
///
/// \param[in] s The status outcome of this RPC
void Finish(Status s) { stream_->Finish(std::move(s)); } void Finish(Status s) { stream_->Finish(std::move(s)); }
/// Notify the application that a streaming RPC has started
///
/// \param[in] context The context object now associated with this RPC
virtual void OnStarted(ServerContext* context) {}
/// Notifies the application that an explicit StartSendInitialMetadata
/// operation completed. Not used when the sending of initial metadata
/// piggybacks onto the first write.
///
/// \param[in] ok Was it successful? If false, no further write-side operation
/// will succeed.
virtual void OnSendInitialMetadataDone(bool ok) {}
/// Notifies the application that a StartRead operation completed.
///
/// \param[in] ok Was it successful? If false, no further read-side operation
/// will succeed.
virtual void OnReadDone(bool ok) {}
/// Notifies the application that a StartWrite (or StartWriteLast) operation
/// completed.
///
/// \param[in] ok Was it successful? If false, no further write-side operation
/// will succeed.
virtual void OnWriteDone(bool ok) {}
/// Notifies the application that all operations associated with this RPC
/// have completed. This is an override (from the internal base class) but not
/// final, so derived classes should override it if they want to take action.
void OnDone() override {}
/// Notifies the application that this RPC has been cancelled. This is an
/// override (from the internal base class) but not final, so derived classes
/// should override it if they want to take action.
void OnCancel() override {}
private: private:
friend class ServerCallbackReaderWriter<Request, Response>; friend class ServerCallbackReaderWriter<Request, Response>;
void BindStream(ServerCallbackReaderWriter<Request, Response>* stream) { void BindStream(ServerCallbackReaderWriter<Request, Response>* stream) {
@ -203,18 +290,31 @@ class ServerBidiReactor : public internal::ServerReactor {
ServerCallbackReaderWriter<Request, Response>* stream_; ServerCallbackReaderWriter<Request, Response>* stream_;
}; };
/// \a ServerReadReactor is the interface for a client-streaming RPC.
template <class Request, class Response> template <class Request, class Response>
class ServerReadReactor : public internal::ServerReactor { class ServerReadReactor : public internal::ServerReactor {
public: public:
~ServerReadReactor() = default; ~ServerReadReactor() = default;
virtual void OnStarted(ServerContext*, Response* resp) {}
virtual void OnSendInitialMetadataDone(bool ok) {}
virtual void OnReadDone(bool ok) {}
/// The following operation initiations are exactly like ServerBidiReactor.
void StartSendInitialMetadata() { reader_->SendInitialMetadata(); } void StartSendInitialMetadata() { reader_->SendInitialMetadata(); }
void StartRead(Request* msg) { reader_->Read(msg); } void StartRead(Request* req) { reader_->Read(req); }
void Finish(Status s) { reader_->Finish(std::move(s)); } void Finish(Status s) { reader_->Finish(std::move(s)); }
/// Similar to ServerBidiReactor::OnStarted, except that this also provides
/// the response object that the stream fills in before calling Finish.
/// (It must be filled in if status is OK, but it may be filled in otherwise.)
///
/// \param[in] context The context object now associated with this RPC
/// \param[in] resp The response object to be used by this RPC
virtual void OnStarted(ServerContext* context, Response* resp) {}
/// The following notifications are exactly like ServerBidiReactor.
virtual void OnSendInitialMetadataDone(bool ok) {}
virtual void OnReadDone(bool ok) {}
void OnDone() override {}
void OnCancel() override {}
private: private:
friend class ServerCallbackReader<Request>; friend class ServerCallbackReader<Request>;
void BindReader(ServerCallbackReader<Request>* reader) { reader_ = reader; } void BindReader(ServerCallbackReader<Request>* reader) { reader_ = reader; }
@ -222,28 +322,40 @@ class ServerReadReactor : public internal::ServerReactor {
ServerCallbackReader<Request>* reader_; ServerCallbackReader<Request>* reader_;
}; };
/// \a ServerReadReactor is the interface for a server-streaming RPC.
template <class Request, class Response> template <class Request, class Response>
class ServerWriteReactor : public internal::ServerReactor { class ServerWriteReactor : public internal::ServerReactor {
public: public:
~ServerWriteReactor() = default; ~ServerWriteReactor() = default;
virtual void OnStarted(ServerContext*, const Request* req) {}
virtual void OnSendInitialMetadataDone(bool ok) {}
virtual void OnWriteDone(bool ok) {}
/// The following operation initiations are exactly like ServerBidiReactor.
void StartSendInitialMetadata() { writer_->SendInitialMetadata(); } void StartSendInitialMetadata() { writer_->SendInitialMetadata(); }
void StartWrite(const Response* msg) { StartWrite(msg, WriteOptions()); } void StartWrite(const Response* resp) { StartWrite(resp, WriteOptions()); }
void StartWrite(const Response* msg, WriteOptions options) { void StartWrite(const Response* resp, WriteOptions options) {
writer_->Write(msg, std::move(options)); writer_->Write(resp, std::move(options));
} }
void StartWriteAndFinish(const Response* msg, WriteOptions options, void StartWriteAndFinish(const Response* resp, WriteOptions options,
Status s) { Status s) {
writer_->WriteAndFinish(msg, std::move(options), std::move(s)); writer_->WriteAndFinish(resp, std::move(options), std::move(s));
} }
void StartWriteLast(const Response* msg, WriteOptions options) { void StartWriteLast(const Response* resp, WriteOptions options) {
StartWrite(msg, std::move(options.set_last_message())); StartWrite(resp, std::move(options.set_last_message()));
} }
void Finish(Status s) { writer_->Finish(std::move(s)); } void Finish(Status s) { writer_->Finish(std::move(s)); }
/// Similar to ServerBidiReactor::OnStarted, except that this also provides
/// the request object sent by the client.
///
/// \param[in] context The context object now associated with this RPC
/// \param[in] req The request object sent by the client
virtual void OnStarted(ServerContext* context, const Request* req) {}
/// The following notifications are exactly like ServerBidiReactor.
virtual void OnSendInitialMetadataDone(bool ok) {}
virtual void OnWriteDone(bool ok) {}
void OnDone() override {}
void OnCancel() override {}
private: private:
friend class ServerCallbackWriter<Response>; friend class ServerCallbackWriter<Response>;
void BindWriter(ServerCallbackWriter<Response>* writer) { writer_ = writer; } void BindWriter(ServerCallbackWriter<Response>* writer) { writer_ = writer; }

@ -231,6 +231,10 @@ class ServerBuilder {
builder_->interceptor_creators_ = std::move(interceptor_creators); builder_->interceptor_creators_ = std::move(interceptor_creators);
} }
/// Register a generic service that uses the callback API.
/// Matches requests with any :authority
/// This is mostly useful for writing generic gRPC Proxies where the exact
/// serialization format is unknown
ServerBuilder& RegisterCallbackGenericService( ServerBuilder& RegisterCallbackGenericService(
experimental::CallbackGenericService* service); experimental::CallbackGenericService* service);

@ -300,6 +300,7 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolving_lb_policy.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolving_lb_policy.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/server_address.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/client_channel/server_address.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_pool_interface.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_pool_interface.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.h" role="src" />
@ -442,7 +443,6 @@
<file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/pid_controller.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/pid_controller.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/service_config.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/static_metadata.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/static_metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/status_conversion.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/status_conversion.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/status_metadata.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/status_metadata.h" role="src" />
@ -613,7 +613,6 @@
<file baseinstalldir="/" name="src/core/lib/transport/metadata.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/metadata.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/pid_controller.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/pid_controller.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/service_config.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/static_metadata.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/static_metadata.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/status_conversion.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/status_conversion.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/status_metadata.cc" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/status_metadata.cc" role="src" />
@ -749,6 +748,7 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolving_lb_policy.cc" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolving_lb_policy.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.cc" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/server_address.cc" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/client_channel/server_address.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.cc" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_pool_interface.cc" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_pool_interface.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.cc" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.cc" role="src" />

@ -97,6 +97,7 @@ try:
"third_party/cares/cares/ares_strcasecmp.c", "third_party/cares/cares/ares_strcasecmp.c",
"third_party/cares/cares/ares_strdup.c", "third_party/cares/cares/ares_strdup.c",
"third_party/cares/cares/ares_strerror.c", "third_party/cares/cares/ares_strerror.c",
"third_party/cares/cares/ares_strsplit.c",
"third_party/cares/cares/ares_timeout.c", "third_party/cares/cares/ares_timeout.c",
"third_party/cares/cares/ares_version.c", "third_party/cares/cares/ares_version.c",
"third_party/cares/cares/ares_writev.c", "third_party/cares/cares/ares_writev.c",
@ -123,6 +124,7 @@ try:
"third_party/cares/cares/ares_setup.h", "third_party/cares/cares/ares_setup.h",
"third_party/cares/cares/ares_strcasecmp.h", "third_party/cares/cares/ares_strcasecmp.h",
"third_party/cares/cares/ares_strdup.h", "third_party/cares/cares/ares_strdup.h",
"third_party/cares/cares/ares_strsplit.h",
"third_party/cares/cares/ares_version.h", "third_party/cares/cares/ares_version.h",
"third_party/cares/cares/bitncmp.h", "third_party/cares/cares/bitncmp.h",
"third_party/cares/cares/config-win32.h", "third_party/cares/cares/config-win32.h",

@ -1,4 +1,4 @@
# Overview # Overview
This directory contains source code for C library (a.k.a the *gRPC C core*) that provides all gRPC's core functionality through a low level API. Libraries in other languages in this repository (C++, Ruby, This directory contains source code for C library (a.k.a the *gRPC C core*) that provides all gRPC's core functionality through a low level API. Libraries in other languages in this repository (C++, C#, Ruby,
Python, PHP, NodeJS, Objective-C) are layered on top of this library. Python, PHP, NodeJS, Objective-C) are layered on top of this library.

@ -41,6 +41,7 @@
#include "src/core/ext/filters/client_channel/resolver_result_parsing.h" #include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
#include "src/core/ext/filters/client_channel/resolving_lb_policy.h" #include "src/core/ext/filters/client_channel/resolving_lb_policy.h"
#include "src/core/ext/filters/client_channel/retry_throttle.h" #include "src/core/ext/filters/client_channel/retry_throttle.h"
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/ext/filters/client_channel/subchannel.h"
#include "src/core/ext/filters/deadline/deadline_filter.h" #include "src/core/ext/filters/deadline/deadline_filter.h"
#include "src/core/lib/backoff/backoff.h" #include "src/core/lib/backoff/backoff.h"
@ -61,7 +62,6 @@
#include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/service_config.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/status_metadata.h" #include "src/core/lib/transport/status_metadata.h"
@ -252,11 +252,11 @@ class ClientChannelControlHelper
// Synchronous callback from chand->resolving_lb_policy to process a resolver // Synchronous callback from chand->resolving_lb_policy to process a resolver
// result update. // result update.
static bool process_resolver_result_locked( static bool process_resolver_result_locked(
void* arg, const grpc_channel_args& args, const char** lb_policy_name, void* arg, grpc_core::Resolver::Result* result, const char** lb_policy_name,
grpc_core::RefCountedPtr<LoadBalancingPolicy::Config>* lb_policy_config) { grpc_core::RefCountedPtr<LoadBalancingPolicy::Config>* lb_policy_config) {
channel_data* chand = static_cast<channel_data*>(arg); channel_data* chand = static_cast<channel_data*>(arg);
chand->have_service_config = true; chand->have_service_config = true;
ProcessedResolverResult resolver_result(args, chand->enable_retries); ProcessedResolverResult resolver_result(result, chand->enable_retries);
grpc_core::UniquePtr<char> service_config_json = grpc_core::UniquePtr<char> service_config_json =
resolver_result.service_config_json(); resolver_result.service_config_json();
if (grpc_client_channel_routing_trace.enabled()) { if (grpc_client_channel_routing_trace.enabled()) {

@ -23,11 +23,10 @@
#include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/combiner.h"
grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount(
false, "lb_policy_refcount");
namespace grpc_core { namespace grpc_core {
DebugOnlyTraceFlag grpc_trace_lb_policy_refcount(false, "lb_policy_refcount");
// //
// LoadBalancingPolicy // LoadBalancingPolicy
// //
@ -89,6 +88,44 @@ grpc_json* LoadBalancingPolicy::ParseLoadBalancingConfig(
return nullptr; return nullptr;
} }
//
// LoadBalancingPolicy::UpdateArgs
//
LoadBalancingPolicy::UpdateArgs::UpdateArgs(const UpdateArgs& other) {
addresses = other.addresses;
config = other.config;
args = grpc_channel_args_copy(other.args);
}
LoadBalancingPolicy::UpdateArgs::UpdateArgs(UpdateArgs&& other) {
addresses = std::move(other.addresses);
config = std::move(other.config);
// TODO(roth): Use std::move() once channel args is converted to C++.
args = other.args;
other.args = nullptr;
}
LoadBalancingPolicy::UpdateArgs& LoadBalancingPolicy::UpdateArgs::operator=(
const UpdateArgs& other) {
addresses = other.addresses;
config = other.config;
grpc_channel_args_destroy(args);
args = grpc_channel_args_copy(other.args);
return *this;
}
LoadBalancingPolicy::UpdateArgs& LoadBalancingPolicy::UpdateArgs::operator=(
UpdateArgs&& other) {
addresses = std::move(other.addresses);
config = std::move(other.config);
// TODO(roth): Use std::move() once channel args is converted to C++.
grpc_channel_args_destroy(args);
args = other.args;
other.args = nullptr;
return *this;
}
// //
// LoadBalancingPolicy::QueuePicker // LoadBalancingPolicy::QueuePicker
// //

@ -22,6 +22,8 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/client_channel_channelz.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.h" #include "src/core/ext/filters/client_channel/subchannel.h"
#include "src/core/lib/gprpp/abstract.h" #include "src/core/lib/gprpp/abstract.h"
#include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/orphanable.h"
@ -29,7 +31,6 @@
#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/service_config.h"
extern grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount; extern grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount;
@ -212,6 +213,23 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
RefCountedPtr<ServiceConfig> service_config_; RefCountedPtr<ServiceConfig> service_config_;
}; };
/// Data passed to the UpdateLocked() method when new addresses and
/// config are available.
struct UpdateArgs {
ServerAddressList addresses;
RefCountedPtr<Config> config;
const grpc_channel_args* args = nullptr;
// TODO(roth): Remove everything below once channel args is
// converted to a copyable and movable C++ object.
UpdateArgs() = default;
~UpdateArgs() { grpc_channel_args_destroy(args); }
UpdateArgs(const UpdateArgs& other);
UpdateArgs(UpdateArgs&& other);
UpdateArgs& operator=(const UpdateArgs& other);
UpdateArgs& operator=(UpdateArgs&& other);
};
/// Args used to instantiate an LB policy. /// Args used to instantiate an LB policy.
struct Args { struct Args {
/// The combiner under which all LB policy calls will be run. /// The combiner under which all LB policy calls will be run.
@ -239,14 +257,10 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
/// Returns the name of the LB policy. /// Returns the name of the LB policy.
virtual const char* name() const GRPC_ABSTRACT; virtual const char* name() const GRPC_ABSTRACT;
/// Updates the policy with a new set of \a args and a new \a lb_config from /// Updates the policy with new data from the resolver. Will be invoked
/// the resolver. Will be invoked immediately after LB policy is constructed, /// immediately after LB policy is constructed, and then again whenever
/// and then again whenever the resolver returns a new result. /// the resolver returns a new result.
/// Note that the LB policy gets the set of addresses from the virtual void UpdateLocked(UpdateArgs) GRPC_ABSTRACT; // NOLINT
/// GRPC_ARG_SERVER_ADDRESS_LIST channel arg.
virtual void UpdateLocked(const grpc_channel_args& args,
RefCountedPtr<Config>) // NOLINT
GRPC_ABSTRACT;
/// Tries to enter a READY connectivity state. /// Tries to enter a READY connectivity state.
/// This is a no-op by default, since most LB policies never go into /// This is a no-op by default, since most LB policies never go into

@ -125,8 +125,7 @@ class GrpcLb : public LoadBalancingPolicy {
const char* name() const override { return kGrpclb; } const char* name() const override { return kGrpclb; }
void UpdateLocked(const grpc_channel_args& args, void UpdateLocked(UpdateArgs args) override;
RefCountedPtr<Config> lb_config) override;
void ResetBackoffLocked() override; void ResetBackoffLocked() override;
void FillChildRefsForChannelz( void FillChildRefsForChannelz(
channelz::ChildRefsList* child_subchannels, channelz::ChildRefsList* child_subchannels,
@ -295,7 +294,8 @@ class GrpcLb : public LoadBalancingPolicy {
void ShutdownLocked() override; void ShutdownLocked() override;
// Helper functions used in UpdateLocked(). // Helper functions used in UpdateLocked().
void ProcessChannelArgsLocked(const grpc_channel_args& args); void ProcessAddressesAndChannelArgsLocked(const ServerAddressList& addresses,
const grpc_channel_args& args);
void ParseLbConfig(Config* grpclb_config); void ParseLbConfig(Config* grpclb_config);
static void OnBalancerChannelConnectivityChangedLocked(void* arg, static void OnBalancerChannelConnectivityChangedLocked(void* arg,
grpc_error* error); grpc_error* error);
@ -311,7 +311,8 @@ class GrpcLb : public LoadBalancingPolicy {
static void OnBalancerCallRetryTimerLocked(void* arg, grpc_error* error); static void OnBalancerCallRetryTimerLocked(void* arg, grpc_error* error);
// Methods for dealing with the child policy. // Methods for dealing with the child policy.
grpc_channel_args* CreateChildPolicyArgsLocked(); grpc_channel_args* CreateChildPolicyArgsLocked(
bool is_backend_from_grpclb_load_balancer);
OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked( OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked(
const char* name, const grpc_channel_args* args); const char* name, const grpc_channel_args* args);
void CreateOrUpdateChildPolicyLocked(); void CreateOrUpdateChildPolicyLocked();
@ -1204,7 +1205,6 @@ grpc_channel_args* BuildBalancerChannelArgs(
const ServerAddressList& addresses, const ServerAddressList& addresses,
FakeResolverResponseGenerator* response_generator, FakeResolverResponseGenerator* response_generator,
const grpc_channel_args* args) { const grpc_channel_args* args) {
ServerAddressList balancer_addresses = ExtractBalancerAddresses(addresses);
// Channel args to remove. // Channel args to remove.
static const char* args_to_remove[] = { static const char* args_to_remove[] = {
// LB policy name, since we want to use the default (pick_first) in // LB policy name, since we want to use the default (pick_first) in
@ -1217,15 +1217,6 @@ grpc_channel_args* BuildBalancerChannelArgs(
// the LB channel than for the parent channel. The client channel // the LB channel than for the parent channel. The client channel
// factory will re-add this arg with the right value. // factory will re-add this arg with the right value.
GRPC_ARG_SERVER_URI, GRPC_ARG_SERVER_URI,
// The resolved addresses, which will be generated by the name resolver
// used in the LB channel. Note that the LB channel will use the fake
// resolver, so this won't actually generate a query to DNS (or some
// other name service). However, the addresses returned by the fake
// resolver will have is_balancer=false, whereas our own addresses have
// is_balancer=true. We need the LB channel to return addresses with
// is_balancer=false so that it does not wind up recursively using the
// grpclb LB policy.
GRPC_ARG_SERVER_ADDRESS_LIST,
// The fake resolver response generator, because we are replacing it // The fake resolver response generator, because we are replacing it
// with the one from the grpclb policy, used to propagate updates to // with the one from the grpclb policy, used to propagate updates to
// the LB channel. // the LB channel.
@ -1241,10 +1232,6 @@ grpc_channel_args* BuildBalancerChannelArgs(
}; };
// Channel args to add. // Channel args to add.
const grpc_arg args_to_add[] = { const grpc_arg args_to_add[] = {
// New address list.
// Note that we pass these in both when creating the LB channel
// and via the fake resolver. The latter is what actually gets used.
CreateServerAddressListChannelArg(&balancer_addresses),
// The fake resolver response generator, which we use to inject // The fake resolver response generator, which we use to inject
// address updates into the LB channel. // address updates into the LB channel.
grpc_core::FakeResolverResponseGenerator::MakeChannelArg( grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
@ -1262,7 +1249,7 @@ grpc_channel_args* BuildBalancerChannelArgs(
args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), args_to_add, args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), args_to_add,
GPR_ARRAY_SIZE(args_to_add)); GPR_ARRAY_SIZE(args_to_add));
// Make any necessary modifications for security. // Make any necessary modifications for security.
return grpc_lb_policy_grpclb_modify_lb_channel_args(new_args); return grpc_lb_policy_grpclb_modify_lb_channel_args(addresses, new_args);
} }
// //
@ -1388,11 +1375,10 @@ void GrpcLb::FillChildRefsForChannelz(
} }
} }
void GrpcLb::UpdateLocked(const grpc_channel_args& args, void GrpcLb::UpdateLocked(UpdateArgs args) {
RefCountedPtr<Config> lb_config) {
const bool is_initial_update = lb_channel_ == nullptr; const bool is_initial_update = lb_channel_ == nullptr;
ParseLbConfig(lb_config.get()); ParseLbConfig(args.config.get());
ProcessChannelArgsLocked(args); ProcessAddressesAndChannelArgsLocked(args.addresses, *args.args);
// Update the existing child policy. // Update the existing child policy.
if (child_policy_ != nullptr) CreateOrUpdateChildPolicyLocked(); if (child_policy_ != nullptr) CreateOrUpdateChildPolicyLocked();
// If this is the initial update, start the fallback-at-startup checks // If this is the initial update, start the fallback-at-startup checks
@ -1442,18 +1428,10 @@ ServerAddressList ExtractBackendAddresses(const ServerAddressList& addresses) {
return backend_addresses; return backend_addresses;
} }
void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) { void GrpcLb::ProcessAddressesAndChannelArgsLocked(
const ServerAddressList* addresses = FindServerAddressListChannelArg(&args); const ServerAddressList& addresses, const grpc_channel_args& args) {
if (addresses == nullptr) {
// Ignore this update.
gpr_log(
GPR_ERROR,
"[grpclb %p] No valid LB addresses channel arg in update, ignoring.",
this);
return;
}
// Update fallback address list. // Update fallback address list.
fallback_backend_addresses_ = ExtractBackendAddresses(*addresses); fallback_backend_addresses_ = ExtractBackendAddresses(addresses);
// Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args, // Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args,
// since we use this to trigger the client_load_reporting filter. // since we use this to trigger the client_load_reporting filter.
static const char* args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME}; static const char* args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME};
@ -1463,8 +1441,9 @@ void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
args_ = grpc_channel_args_copy_and_add_and_remove( args_ = grpc_channel_args_copy_and_add_and_remove(
&args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1); &args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1);
// Construct args for balancer channel. // Construct args for balancer channel.
grpc_channel_args* lb_channel_args = ServerAddressList balancer_addresses = ExtractBalancerAddresses(addresses);
BuildBalancerChannelArgs(*addresses, response_generator_.get(), &args); grpc_channel_args* lb_channel_args = BuildBalancerChannelArgs(
balancer_addresses, response_generator_.get(), &args);
// Create balancer channel if needed. // Create balancer channel if needed.
if (lb_channel_ == nullptr) { if (lb_channel_ == nullptr) {
char* uri_str; char* uri_str;
@ -1481,8 +1460,10 @@ void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
} }
// Propagate updates to the LB channel (pick_first) through the fake // Propagate updates to the LB channel (pick_first) through the fake
// resolver. // resolver.
response_generator_->SetResponse(lb_channel_args); Resolver::Result result;
grpc_channel_args_destroy(lb_channel_args); result.addresses = std::move(balancer_addresses);
result.args = lb_channel_args;
response_generator_->SetResponse(std::move(result));
} }
void GrpcLb::ParseLbConfig(Config* grpclb_config) { void GrpcLb::ParseLbConfig(Config* grpclb_config) {
@ -1649,25 +1630,9 @@ void GrpcLb::OnFallbackTimerLocked(void* arg, grpc_error* error) {
// code for interacting with the child policy // code for interacting with the child policy
// //
grpc_channel_args* GrpcLb::CreateChildPolicyArgsLocked() { grpc_channel_args* GrpcLb::CreateChildPolicyArgsLocked(
ServerAddressList tmp_addresses; bool is_backend_from_grpclb_load_balancer) {
ServerAddressList* addresses = &tmp_addresses; grpc_arg args_to_add[2] = {
bool is_backend_from_grpclb_load_balancer = false;
if (fallback_mode_) {
// Note: If fallback backend address list is empty, the child policy
// will go into state TRANSIENT_FAILURE.
addresses = &fallback_backend_addresses_;
} else {
tmp_addresses = serverlist_->GetServerAddressList(
lb_calld_ == nullptr ? nullptr : lb_calld_->client_stats());
is_backend_from_grpclb_load_balancer = true;
}
GPR_ASSERT(addresses != nullptr);
// Replace the server address list in the channel args that we pass down to
// the subchannel.
static const char* keys_to_remove[] = {GRPC_ARG_SERVER_ADDRESS_LIST};
grpc_arg args_to_add[3] = {
CreateServerAddressListChannelArg(addresses),
// A channel arg indicating if the target is a backend inferred from a // A channel arg indicating if the target is a backend inferred from a
// grpclb load balancer. // grpclb load balancer.
grpc_channel_arg_integer_create( grpc_channel_arg_integer_create(
@ -1675,15 +1640,12 @@ grpc_channel_args* GrpcLb::CreateChildPolicyArgsLocked() {
GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER), GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER),
is_backend_from_grpclb_load_balancer), is_backend_from_grpclb_load_balancer),
}; };
size_t num_args_to_add = 2; size_t num_args_to_add = 1;
if (is_backend_from_grpclb_load_balancer) { if (is_backend_from_grpclb_load_balancer) {
args_to_add[2] = grpc_channel_arg_integer_create( args_to_add[num_args_to_add++] = grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1); const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1);
++num_args_to_add;
} }
return grpc_channel_args_copy_and_add_and_remove( return grpc_channel_args_copy_and_add(args_, args_to_add, num_args_to_add);
args_, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add,
num_args_to_add);
} }
OrphanablePtr<LoadBalancingPolicy> GrpcLb::CreateChildPolicyLocked( OrphanablePtr<LoadBalancingPolicy> GrpcLb::CreateChildPolicyLocked(
@ -1717,8 +1679,25 @@ OrphanablePtr<LoadBalancingPolicy> GrpcLb::CreateChildPolicyLocked(
void GrpcLb::CreateOrUpdateChildPolicyLocked() { void GrpcLb::CreateOrUpdateChildPolicyLocked() {
if (shutting_down_) return; if (shutting_down_) return;
grpc_channel_args* args = CreateChildPolicyArgsLocked(); // Construct update args.
GPR_ASSERT(args != nullptr); UpdateArgs update_args;
bool is_backend_from_grpclb_load_balancer = false;
if (fallback_mode_) {
// If CreateOrUpdateChildPolicyLocked() is invoked when we haven't
// received any serverlist from the balancer, we use the fallback backends
// returned by the resolver. Note that the fallback backend list may be
// empty, in which case the new round_robin policy will keep the requested
// picks pending.
update_args.addresses = fallback_backend_addresses_;
} else {
update_args.addresses = serverlist_->GetServerAddressList(
lb_calld_ == nullptr ? nullptr : lb_calld_->client_stats());
is_backend_from_grpclb_load_balancer = true;
}
update_args.args =
CreateChildPolicyArgsLocked(is_backend_from_grpclb_load_balancer);
GPR_ASSERT(update_args.args != nullptr);
update_args.config = child_policy_config_;
// If the child policy name changes, we need to create a new child // If the child policy name changes, we need to create a new child
// policy. When this happens, we leave child_policy_ as-is and store // policy. When this happens, we leave child_policy_ as-is and store
// the new child policy in pending_child_policy_. Once the new child // the new child policy in pending_child_policy_. Once the new child
@ -1789,7 +1768,8 @@ void GrpcLb::CreateOrUpdateChildPolicyLocked() {
gpr_log(GPR_INFO, "[grpclb %p] Creating new %schild policy %s", this, gpr_log(GPR_INFO, "[grpclb %p] Creating new %schild policy %s", this,
child_policy_ == nullptr ? "" : "pending ", child_policy_name); child_policy_ == nullptr ? "" : "pending ", child_policy_name);
} }
auto new_policy = CreateChildPolicyLocked(child_policy_name, args); auto new_policy =
CreateChildPolicyLocked(child_policy_name, update_args.args);
// Swap the policy into place. // Swap the policy into place.
auto& lb_policy = auto& lb_policy =
child_policy_ == nullptr ? child_policy_ : pending_child_policy_; child_policy_ == nullptr ? child_policy_ : pending_child_policy_;
@ -1813,9 +1793,7 @@ void GrpcLb::CreateOrUpdateChildPolicyLocked() {
policy_to_update == pending_child_policy_.get() ? "pending " : "", policy_to_update == pending_child_policy_.get() ? "pending " : "",
policy_to_update); policy_to_update);
} }
policy_to_update->UpdateLocked(*args, child_policy_config_); policy_to_update->UpdateLocked(std::move(update_args));
// Clean up.
grpc_channel_args_destroy(args);
} }
// //

@ -21,6 +21,6 @@
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h"
grpc_channel_args* grpc_lb_policy_grpclb_modify_lb_channel_args( grpc_channel_args* grpc_lb_policy_grpclb_modify_lb_channel_args(
grpc_channel_args* args) { const grpc_core::ServerAddressList& addresses, grpc_channel_args* args) {
return args; return args;
} }

@ -23,6 +23,8 @@
#include <grpc/impl/codegen/grpc_types.h> #include <grpc/impl/codegen/grpc_types.h>
#include "src/core/ext/filters/client_channel/server_address.h"
/// Makes any necessary modifications to \a args for use in the grpclb /// Makes any necessary modifications to \a args for use in the grpclb
/// balancer channel. /// balancer channel.
/// ///
@ -30,7 +32,7 @@
/// ///
/// Caller takes ownership of the returned args. /// Caller takes ownership of the returned args.
grpc_channel_args* grpc_lb_policy_grpclb_modify_lb_channel_args( grpc_channel_args* grpc_lb_policy_grpclb_modify_lb_channel_args(
grpc_channel_args* args); const grpc_core::ServerAddressList& addresses, grpc_channel_args* args);
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H \ #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_CHANNEL_H \
*/ */

@ -68,18 +68,14 @@ RefCountedPtr<TargetAuthorityTable> CreateTargetAuthorityTable(
} // namespace grpc_core } // namespace grpc_core
grpc_channel_args* grpc_lb_policy_grpclb_modify_lb_channel_args( grpc_channel_args* grpc_lb_policy_grpclb_modify_lb_channel_args(
grpc_channel_args* args) { const grpc_core::ServerAddressList& addresses, grpc_channel_args* args) {
const char* args_to_remove[1]; const char* args_to_remove[1];
size_t num_args_to_remove = 0; size_t num_args_to_remove = 0;
grpc_arg args_to_add[2]; grpc_arg args_to_add[2];
size_t num_args_to_add = 0; size_t num_args_to_add = 0;
// Add arg for targets info table. // Add arg for targets info table.
grpc_core::ServerAddressList* addresses =
grpc_core::FindServerAddressListChannelArg(args);
GPR_ASSERT(addresses != nullptr);
grpc_core::RefCountedPtr<grpc_core::TargetAuthorityTable> grpc_core::RefCountedPtr<grpc_core::TargetAuthorityTable>
target_authority_table = target_authority_table = grpc_core::CreateTargetAuthorityTable(addresses);
grpc_core::CreateTargetAuthorityTable(*addresses);
args_to_add[num_args_to_add++] = args_to_add[num_args_to_add++] =
grpc_core::CreateTargetAuthorityTableChannelArg( grpc_core::CreateTargetAuthorityTableChannelArg(
target_authority_table.get()); target_authority_table.get());

@ -50,8 +50,7 @@ class PickFirst : public LoadBalancingPolicy {
const char* name() const override { return kPickFirst; } const char* name() const override { return kPickFirst; }
void UpdateLocked(const grpc_channel_args& args, void UpdateLocked(UpdateArgs args) override;
RefCountedPtr<Config> lb_config) override;
void ExitIdleLocked() override; void ExitIdleLocked() override;
void ResetBackoffLocked() override; void ResetBackoffLocked() override;
void FillChildRefsForChannelz(channelz::ChildRefsList* child_subchannels, void FillChildRefsForChannelz(channelz::ChildRefsList* child_subchannels,
@ -238,38 +237,19 @@ void PickFirst::UpdateChildRefsLocked() {
child_subchannels_ = std::move(cs); child_subchannels_ = std::move(cs);
} }
void PickFirst::UpdateLocked(const grpc_channel_args& args, void PickFirst::UpdateLocked(UpdateArgs args) {
RefCountedPtr<Config> lb_config) {
AutoChildRefsUpdater guard(this); AutoChildRefsUpdater guard(this);
const ServerAddressList* addresses = FindServerAddressListChannelArg(&args);
if (addresses == nullptr) {
if (subchannel_list_ == nullptr) {
// If we don't have a current subchannel list, go into TRANSIENT FAILURE.
grpc_error* error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing update in args");
channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error),
UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error)));
} else {
// otherwise, keep using the current subchannel list (ignore this update).
gpr_log(GPR_ERROR,
"No valid LB addresses channel arg for Pick First %p update, "
"ignoring.",
this);
}
return;
}
if (grpc_lb_pick_first_trace.enabled()) { if (grpc_lb_pick_first_trace.enabled()) {
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"Pick First %p received update with %" PRIuPTR " addresses", this, "Pick First %p received update with %" PRIuPTR " addresses", this,
addresses->size()); args.addresses.size());
} }
grpc_arg new_arg = grpc_channel_arg_integer_create( grpc_arg new_arg = grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1); const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1);
grpc_channel_args* new_args = grpc_channel_args* new_args =
grpc_channel_args_copy_and_add(&args, &new_arg, 1); grpc_channel_args_copy_and_add(args.args, &new_arg, 1);
auto subchannel_list = MakeOrphanable<PickFirstSubchannelList>( auto subchannel_list = MakeOrphanable<PickFirstSubchannelList>(
this, &grpc_lb_pick_first_trace, *addresses, combiner(), *new_args); this, &grpc_lb_pick_first_trace, args.addresses, combiner(), *new_args);
grpc_channel_args_destroy(new_args); grpc_channel_args_destroy(new_args);
if (subchannel_list->num_subchannels() == 0) { if (subchannel_list->num_subchannels() == 0) {
// Empty update or no valid subchannels. Unsubscribe from all current // Empty update or no valid subchannels. Unsubscribe from all current

@ -61,8 +61,7 @@ class RoundRobin : public LoadBalancingPolicy {
const char* name() const override { return kRoundRobin; } const char* name() const override { return kRoundRobin; }
void UpdateLocked(const grpc_channel_args& args, void UpdateLocked(UpdateArgs args) override;
RefCountedPtr<Config> lb_config) override;
void ResetBackoffLocked() override; void ResetBackoffLocked() override;
void FillChildRefsForChannelz(channelz::ChildRefsList* child_subchannels, void FillChildRefsForChannelz(channelz::ChildRefsList* child_subchannels,
channelz::ChildRefsList* ignored) override; channelz::ChildRefsList* ignored) override;
@ -476,26 +475,11 @@ void RoundRobin::RoundRobinSubchannelData::ProcessConnectivityChangeLocked(
subchannel_list()->UpdateRoundRobinStateFromSubchannelStateCountsLocked(); subchannel_list()->UpdateRoundRobinStateFromSubchannelStateCountsLocked();
} }
void RoundRobin::UpdateLocked(const grpc_channel_args& args, void RoundRobin::UpdateLocked(UpdateArgs args) {
RefCountedPtr<Config> lb_config) {
AutoChildRefsUpdater guard(this); AutoChildRefsUpdater guard(this);
const ServerAddressList* addresses = FindServerAddressListChannelArg(&args);
if (addresses == nullptr) {
gpr_log(GPR_ERROR, "[RR %p] update provided no addresses; ignoring", this);
// If we don't have a current subchannel list, go into TRANSIENT_FAILURE.
// Otherwise, keep using the current subchannel list (ignore this update).
if (subchannel_list_ == nullptr) {
grpc_error* error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing update in args");
channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error),
UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error)));
}
return;
}
if (grpc_lb_round_robin_trace.enabled()) { if (grpc_lb_round_robin_trace.enabled()) {
gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " addresses", gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " addresses",
this, addresses->size()); this, args.addresses.size());
} }
// Replace latest_pending_subchannel_list_. // Replace latest_pending_subchannel_list_.
if (latest_pending_subchannel_list_ != nullptr) { if (latest_pending_subchannel_list_ != nullptr) {
@ -506,7 +490,7 @@ void RoundRobin::UpdateLocked(const grpc_channel_args& args,
} }
} }
latest_pending_subchannel_list_ = MakeOrphanable<RoundRobinSubchannelList>( latest_pending_subchannel_list_ = MakeOrphanable<RoundRobinSubchannelList>(
this, &grpc_lb_round_robin_trace, *addresses, combiner(), args); this, &grpc_lb_round_robin_trace, args.addresses, combiner(), *args.args);
if (latest_pending_subchannel_list_->num_subchannels() == 0) { if (latest_pending_subchannel_list_->num_subchannels() == 0) {
// If the new list is empty, immediately promote the new list to the // If the new list is empty, immediately promote the new list to the
// current list and transition to TRANSIENT_FAILURE. // current list and transition to TRANSIENT_FAILURE.

@ -505,7 +505,6 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
inhibit_health_checking_ = grpc_channel_arg_get_bool( inhibit_health_checking_ = grpc_channel_arg_get_bool(
grpc_channel_args_find(&args, GRPC_ARG_INHIBIT_HEALTH_CHECKING), false); grpc_channel_args_find(&args, GRPC_ARG_INHIBIT_HEALTH_CHECKING), false);
static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS, static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS,
GRPC_ARG_SERVER_ADDRESS_LIST,
GRPC_ARG_INHIBIT_HEALTH_CHECKING}; GRPC_ARG_INHIBIT_HEALTH_CHECKING};
// Create a subchannel for each address. // Create a subchannel for each address.
for (size_t i = 0; i < addresses.size(); i++) { for (size_t i = 0; i < addresses.size(); i++) {

@ -78,6 +78,7 @@
#include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/lib/backoff/backoff.h" #include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack.h"
@ -98,7 +99,6 @@
#include "src/core/lib/surface/call.h" #include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel.h"
#include "src/core/lib/surface/channel_init.h" #include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/transport/service_config.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#define GRPC_XDS_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_XDS_INITIAL_CONNECT_BACKOFF_SECONDS 1
@ -121,8 +121,7 @@ class XdsLb : public LoadBalancingPolicy {
const char* name() const override { return kXds; } const char* name() const override { return kXds; }
void UpdateLocked(const grpc_channel_args& args, void UpdateLocked(UpdateArgs args) override;
RefCountedPtr<Config> lb_config) override;
void ResetBackoffLocked() override; void ResetBackoffLocked() override;
void FillChildRefsForChannelz( void FillChildRefsForChannelz(
channelz::ChildRefsList* child_subchannels, channelz::ChildRefsList* child_subchannels,
@ -293,7 +292,8 @@ class XdsLb : public LoadBalancingPolicy {
void ShutdownLocked() override; void ShutdownLocked() override;
// Helper function used in UpdateLocked(). // Helper function used in UpdateLocked().
void ProcessChannelArgsLocked(const grpc_channel_args& args); void ProcessAddressesAndChannelArgsLocked(const ServerAddressList& addresses,
const grpc_channel_args& args);
// Parses the xds config given the JSON node of the first child of XdsConfig. // Parses the xds config given the JSON node of the first child of XdsConfig.
// If parsing succeeds, updates \a balancer_name, and updates \a // If parsing succeeds, updates \a balancer_name, and updates \a
@ -539,15 +539,14 @@ void ParseServer(const xds_grpclb_server* server, grpc_resolved_address* addr) {
} }
// Returns addresses extracted from \a serverlist. // Returns addresses extracted from \a serverlist.
UniquePtr<ServerAddressList> ProcessServerlist( ServerAddressList ProcessServerlist(const xds_grpclb_serverlist* serverlist) {
const xds_grpclb_serverlist* serverlist) { ServerAddressList addresses;
auto addresses = MakeUnique<ServerAddressList>();
for (size_t i = 0; i < serverlist->num_servers; ++i) { for (size_t i = 0; i < serverlist->num_servers; ++i) {
const xds_grpclb_server* server = serverlist->servers[i]; const xds_grpclb_server* server = serverlist->servers[i];
if (!IsServerValid(serverlist->servers[i], i, false)) continue; if (!IsServerValid(serverlist->servers[i], i, false)) continue;
grpc_resolved_address addr; grpc_resolved_address addr;
ParseServer(server, &addr); ParseServer(server, &addr);
addresses->emplace_back(addr, nullptr); addresses.emplace_back(addr, nullptr);
} }
return addresses; return addresses;
} }
@ -1082,9 +1081,6 @@ grpc_channel_args* BuildBalancerChannelArgs(const grpc_channel_args* args) {
// the LB channel than for the parent channel. The client channel // the LB channel than for the parent channel. The client channel
// factory will re-add this arg with the right value. // factory will re-add this arg with the right value.
GRPC_ARG_SERVER_URI, GRPC_ARG_SERVER_URI,
// The resolved addresses, which will be generated by the name resolver
// used in the LB channel.
GRPC_ARG_SERVER_ADDRESS_LIST,
// The LB channel should use the authority indicated by the target // The LB channel should use the authority indicated by the target
// authority table (see \a grpc_lb_policy_xds_modify_lb_channel_args), // authority table (see \a grpc_lb_policy_xds_modify_lb_channel_args),
// as opposed to the authority from the parent channel. // as opposed to the authority from the parent channel.
@ -1232,17 +1228,10 @@ void XdsLb::FillChildRefsForChannelz(channelz::ChildRefsList* child_subchannels,
} }
} }
void XdsLb::ProcessChannelArgsLocked(const grpc_channel_args& args) { void XdsLb::ProcessAddressesAndChannelArgsLocked(
const ServerAddressList* addresses = FindServerAddressListChannelArg(&args); const ServerAddressList& addresses, const grpc_channel_args& args) {
if (addresses == nullptr) {
// Ignore this update.
gpr_log(GPR_ERROR,
"[xdslb %p] No valid LB addresses channel arg in update, ignoring.",
this);
return;
}
// Update fallback address list. // Update fallback address list.
fallback_backend_addresses_ = ExtractBackendAddresses(*addresses); fallback_backend_addresses_ = ExtractBackendAddresses(addresses);
// Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args, // Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args,
// since we use this to trigger the client_load_reporting filter. // since we use this to trigger the client_load_reporting filter.
static const char* args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME}; static const char* args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME};
@ -1310,17 +1299,16 @@ void XdsLb::ParseLbConfig(Config* xds_config) {
} }
} }
void XdsLb::UpdateLocked(const grpc_channel_args& args, void XdsLb::UpdateLocked(UpdateArgs args) {
RefCountedPtr<Config> lb_config) {
const bool is_initial_update = lb_chand_ == nullptr; const bool is_initial_update = lb_chand_ == nullptr;
ParseLbConfig(lb_config.get()); ParseLbConfig(args.config.get());
// TODO(juanlishen): Pass fallback policy config update after fallback policy // TODO(juanlishen): Pass fallback policy config update after fallback policy
// is added. // is added.
if (balancer_name_ == nullptr) { if (balancer_name_ == nullptr) {
gpr_log(GPR_ERROR, "[xdslb %p] LB config parsing fails.", this); gpr_log(GPR_ERROR, "[xdslb %p] LB config parsing fails.", this);
return; return;
} }
ProcessChannelArgsLocked(args); ProcessAddressesAndChannelArgsLocked(args.addresses, *args.args);
// Update the existing child policy. // Update the existing child policy.
// Note: We have disabled fallback mode in the code, so this child policy must // Note: We have disabled fallback mode in the code, so this child policy must
// have been created from a serverlist. // have been created from a serverlist.
@ -1369,17 +1357,7 @@ void XdsLb::OnFallbackTimerLocked(void* arg, grpc_error* error) {
// //
grpc_channel_args* XdsLb::CreateChildPolicyArgsLocked() { grpc_channel_args* XdsLb::CreateChildPolicyArgsLocked() {
// This should never be invoked if we do not have serverlist_, as fallback
// mode is disabled for xDS plugin.
GPR_ASSERT(serverlist_ != nullptr);
GPR_ASSERT(serverlist_->num_servers > 0);
UniquePtr<ServerAddressList> addresses = ProcessServerlist(serverlist_);
GPR_ASSERT(addresses != nullptr);
// Replace the server address list in the channel args that we pass down to
// the subchannel.
static const char* keys_to_remove[] = {GRPC_ARG_SERVER_ADDRESS_LIST};
const grpc_arg args_to_add[] = { const grpc_arg args_to_add[] = {
CreateServerAddressListChannelArg(addresses.get()),
// A channel arg indicating if the target is a backend inferred from a // A channel arg indicating if the target is a backend inferred from a
// grpclb load balancer. // grpclb load balancer.
grpc_channel_arg_integer_create( grpc_channel_arg_integer_create(
@ -1390,9 +1368,8 @@ grpc_channel_args* XdsLb::CreateChildPolicyArgsLocked() {
grpc_channel_arg_integer_create( grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1), const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1),
}; };
return grpc_channel_args_copy_and_add_and_remove( return grpc_channel_args_copy_and_add(args_, args_to_add,
args_, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add, GPR_ARRAY_SIZE(args_to_add));
GPR_ARRAY_SIZE(args_to_add));
} }
OrphanablePtr<LoadBalancingPolicy> XdsLb::CreateChildPolicyLocked( OrphanablePtr<LoadBalancingPolicy> XdsLb::CreateChildPolicyLocked(
@ -1426,8 +1403,16 @@ OrphanablePtr<LoadBalancingPolicy> XdsLb::CreateChildPolicyLocked(
void XdsLb::CreateOrUpdateChildPolicyLocked() { void XdsLb::CreateOrUpdateChildPolicyLocked() {
if (shutting_down_) return; if (shutting_down_) return;
grpc_channel_args* args = CreateChildPolicyArgsLocked(); // This should never be invoked if we do not have serverlist_, as fallback
GPR_ASSERT(args != nullptr); // mode is disabled for xDS plugin.
// TODO(juanlishen): Change this as part of implementing fallback mode.
GPR_ASSERT(serverlist_ != nullptr);
GPR_ASSERT(serverlist_->num_servers > 0);
// Construct update args.
UpdateArgs update_args;
update_args.addresses = ProcessServerlist(serverlist_);
update_args.config = child_policy_config_;
update_args.args = CreateChildPolicyArgsLocked();
// If the child policy name changes, we need to create a new child // If the child policy name changes, we need to create a new child
// policy. When this happens, we leave child_policy_ as-is and store // policy. When this happens, we leave child_policy_ as-is and store
// the new child policy in pending_child_policy_. Once the new child // the new child policy in pending_child_policy_. Once the new child
@ -1500,7 +1485,8 @@ void XdsLb::CreateOrUpdateChildPolicyLocked() {
gpr_log(GPR_INFO, "[xdslb %p] Creating new %schild policy %s", this, gpr_log(GPR_INFO, "[xdslb %p] Creating new %schild policy %s", this,
child_policy_ == nullptr ? "" : "pending ", child_policy_name); child_policy_ == nullptr ? "" : "pending ", child_policy_name);
} }
auto new_policy = CreateChildPolicyLocked(child_policy_name, args); auto new_policy =
CreateChildPolicyLocked(child_policy_name, update_args.args);
auto& lb_policy = auto& lb_policy =
child_policy_ == nullptr ? child_policy_ : pending_child_policy_; child_policy_ == nullptr ? child_policy_ : pending_child_policy_;
{ {
@ -1523,9 +1509,7 @@ void XdsLb::CreateOrUpdateChildPolicyLocked() {
policy_to_update == pending_child_policy_.get() ? "pending " : "", policy_to_update == pending_child_policy_.get() ? "pending " : "",
policy_to_update); policy_to_update);
} }
policy_to_update->UpdateLocked(*args, child_policy_config_); policy_to_update->UpdateLocked(std::move(update_args));
// Clean up.
grpc_channel_args_destroy(args);
} }
// //

@ -26,6 +26,10 @@ grpc_core::DebugOnlyTraceFlag grpc_trace_resolver_refcount(false,
namespace grpc_core { namespace grpc_core {
//
// Resolver
//
Resolver::Resolver(grpc_combiner* combiner, Resolver::Resolver(grpc_combiner* combiner,
UniquePtr<ResultHandler> result_handler) UniquePtr<ResultHandler> result_handler)
: InternallyRefCounted(&grpc_trace_resolver_refcount), : InternallyRefCounted(&grpc_trace_resolver_refcount),
@ -34,4 +38,51 @@ Resolver::Resolver(grpc_combiner* combiner,
Resolver::~Resolver() { GRPC_COMBINER_UNREF(combiner_, "resolver"); } Resolver::~Resolver() { GRPC_COMBINER_UNREF(combiner_, "resolver"); }
//
// Resolver::Result
//
Resolver::Result::~Result() {
GRPC_ERROR_UNREF(service_config_error);
grpc_channel_args_destroy(args);
}
Resolver::Result::Result(const Result& other) {
addresses = other.addresses;
service_config = other.service_config;
service_config_error = GRPC_ERROR_REF(other.service_config_error);
args = grpc_channel_args_copy(other.args);
}
Resolver::Result::Result(Result&& other) {
addresses = std::move(other.addresses);
service_config = std::move(other.service_config);
service_config_error = other.service_config_error;
other.service_config_error = GRPC_ERROR_NONE;
args = other.args;
other.args = nullptr;
}
Resolver::Result& Resolver::Result::operator=(const Result& other) {
addresses = other.addresses;
service_config = other.service_config;
GRPC_ERROR_UNREF(service_config_error);
service_config_error = GRPC_ERROR_REF(other.service_config_error);
grpc_channel_args_destroy(args);
args = grpc_channel_args_copy(other.args);
return *this;
}
Resolver::Result& Resolver::Result::operator=(Result&& other) {
addresses = std::move(other.addresses);
service_config = std::move(other.service_config);
GRPC_ERROR_UNREF(service_config_error);
service_config_error = other.service_config_error;
other.service_config_error = GRPC_ERROR_NONE;
grpc_channel_args_destroy(args);
args = other.args;
other.args = nullptr;
return *this;
}
} // namespace grpc_core } // namespace grpc_core

@ -23,8 +23,11 @@
#include <grpc/impl/codegen/grpc_types.h> #include <grpc/impl/codegen/grpc_types.h>
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/lib/gprpp/abstract.h" #include "src/core/lib/gprpp/abstract.h"
#include "src/core/lib/gprpp/orphanable.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/combiner.h"
#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/iomgr.h"
@ -46,6 +49,23 @@ namespace grpc_core {
/// combiner passed to the constructor. /// combiner passed to the constructor.
class Resolver : public InternallyRefCounted<Resolver> { class Resolver : public InternallyRefCounted<Resolver> {
public: public:
/// Results returned by the resolver.
struct Result {
ServerAddressList addresses;
RefCountedPtr<ServiceConfig> service_config;
grpc_error* service_config_error = GRPC_ERROR_NONE;
const grpc_channel_args* args = nullptr;
// TODO(roth): Remove everything below once grpc_error and
// grpc_channel_args are convert to copyable and movable C++ objects.
Result() = default;
~Result();
Result(const Result& other);
Result(Result&& other);
Result& operator=(const Result& other);
Result& operator=(Result&& other);
};
/// A proxy object used by the resolver to return results to the /// A proxy object used by the resolver to return results to the
/// client channel. /// client channel.
class ResultHandler { class ResultHandler {
@ -53,18 +73,17 @@ class Resolver : public InternallyRefCounted<Resolver> {
virtual ~ResultHandler() {} virtual ~ResultHandler() {}
/// Returns a result to the channel. /// Returns a result to the channel.
/// The list of addresses will be in GRPC_ARG_SERVER_ADDRESS_LIST. /// Takes ownership of \a result.args.
/// The service config (if any) will be in GRPC_ARG_SERVICE_CONFIG. virtual void ReturnResult(Result result) GRPC_ABSTRACT; // NOLINT
/// Takes ownership of \a result.
// TODO(roth): Change this API so that addresses and service config are
// passed explicitly instead of being in channel args.
virtual void ReturnResult(const grpc_channel_args* result) GRPC_ABSTRACT;
/// Returns a transient error to the channel. /// Returns a transient error to the channel.
/// If the resolver does not set the GRPC_ERROR_INT_GRPC_STATUS /// If the resolver does not set the GRPC_ERROR_INT_GRPC_STATUS
/// attribute on the error, calls will be failed with status UNKNOWN. /// attribute on the error, calls will be failed with status UNKNOWN.
virtual void ReturnError(grpc_error* error) GRPC_ABSTRACT; virtual void ReturnError(grpc_error* error) GRPC_ABSTRACT;
// TODO(yashkt): As part of the service config error handling
// changes, add a method to parse the service config JSON string.
GRPC_ABSTRACT_BASE_CLASS GRPC_ABSTRACT_BASE_CLASS
}; };

@ -34,6 +34,7 @@
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
#include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/resolver_registry.h"
#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/lib/backoff/backoff.h" #include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/env.h"
@ -45,7 +46,6 @@
#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/json/json.h" #include "src/core/lib/json/json.h"
#include "src/core/lib/transport/service_config.h"
#define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1
#define GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER 1.6 #define GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER 1.6
@ -299,28 +299,21 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
return; return;
} }
if (r->addresses_ != nullptr) { if (r->addresses_ != nullptr) {
static const char* args_to_remove[1]; Result result;
size_t num_args_to_remove = 0; result.addresses = std::move(*r->addresses_);
grpc_arg args_to_add[2];
size_t num_args_to_add = 0;
args_to_add[num_args_to_add++] =
CreateServerAddressListChannelArg(r->addresses_.get());
char* service_config_string = nullptr;
if (r->service_config_json_ != nullptr) { if (r->service_config_json_ != nullptr) {
service_config_string = ChooseServiceConfig(r->service_config_json_); char* service_config_string =
ChooseServiceConfig(r->service_config_json_);
gpr_free(r->service_config_json_); gpr_free(r->service_config_json_);
if (service_config_string != nullptr) { if (service_config_string != nullptr) {
GRPC_CARES_TRACE_LOG("resolver:%p selected service config choice: %s", GRPC_CARES_TRACE_LOG("resolver:%p selected service config choice: %s",
r, service_config_string); r, service_config_string);
args_to_remove[num_args_to_remove++] = GRPC_ARG_SERVICE_CONFIG; result.service_config = ServiceConfig::Create(service_config_string);
args_to_add[num_args_to_add++] = grpc_channel_arg_string_create(
(char*)GRPC_ARG_SERVICE_CONFIG, service_config_string);
} }
gpr_free(service_config_string);
} }
r->result_handler()->ReturnResult(grpc_channel_args_copy_and_add_and_remove( result.args = grpc_channel_args_copy(r->channel_args_);
r->channel_args_, args_to_remove, num_args_to_remove, args_to_add, r->result_handler()->ReturnResult(std::move(result));
num_args_to_add));
gpr_free(service_config_string);
r->addresses_.reset(); r->addresses_.reset();
// Reset backoff state so that we start from the beginning when the // Reset backoff state so that we start from the beginning when the
// next request gets triggered. // next request gets triggered.

@ -169,15 +169,15 @@ void NativeDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
return; return;
} }
if (r->addresses_ != nullptr) { if (r->addresses_ != nullptr) {
ServerAddressList addresses; Result result;
for (size_t i = 0; i < r->addresses_->naddrs; ++i) { for (size_t i = 0; i < r->addresses_->naddrs; ++i) {
addresses.emplace_back(&r->addresses_->addrs[i].addr, result.addresses.emplace_back(&r->addresses_->addrs[i].addr,
r->addresses_->addrs[i].len, nullptr /* args */); r->addresses_->addrs[i].len,
nullptr /* args */);
} }
grpc_resolved_addresses_destroy(r->addresses_); grpc_resolved_addresses_destroy(r->addresses_);
grpc_arg new_arg = CreateServerAddressListChannelArg(&addresses); result.args = grpc_channel_args_copy(r->channel_args_);
r->result_handler()->ReturnResult( r->result_handler()->ReturnResult(std::move(result));
grpc_channel_args_copy_and_add(r->channel_args_, &new_arg, 1));
// Reset backoff state so that we start from the beginning when the // Reset backoff state so that we start from the beginning when the
// next request gets triggered. // next request gets triggered.
r->backoff_.Reset(); r->backoff_.Reset();

@ -69,11 +69,14 @@ class FakeResolver : public Resolver {
// passed-in parameters // passed-in parameters
grpc_channel_args* channel_args_ = nullptr; grpc_channel_args* channel_args_ = nullptr;
// If not NULL, the next set of resolution results to be returned. // If has_next_result_ is true, next_result_ is the next resolution result
grpc_channel_args* next_results_ = nullptr; // to be returned.
// Results to use for the pretended re-resolution in bool has_next_result_ = false;
Result next_result_;
// Result to use for the pretended re-resolution in
// RequestReresolutionLocked(). // RequestReresolutionLocked().
grpc_channel_args* reresolution_results_ = nullptr; bool has_reresolution_result_ = false;
Result reresolution_result_;
// True between the calls to StartLocked() ShutdownLocked(). // True between the calls to StartLocked() ShutdownLocked().
bool active_ = false; bool active_ = false;
// if true, return failure // if true, return failure
@ -92,19 +95,14 @@ FakeResolver::FakeResolver(ResolverArgs args)
FakeResolverResponseGenerator::GetFromArgs(args.args); FakeResolverResponseGenerator::GetFromArgs(args.args);
if (response_generator != nullptr) { if (response_generator != nullptr) {
response_generator->resolver_ = this; response_generator->resolver_ = this;
if (response_generator->response_ != nullptr) { if (response_generator->has_result_) {
response_generator->SetResponse(response_generator->response_); response_generator->SetResponse(std::move(response_generator->result_));
grpc_channel_args_destroy(response_generator->response_); response_generator->has_result_ = false;
response_generator->response_ = nullptr;
} }
} }
} }
FakeResolver::~FakeResolver() { FakeResolver::~FakeResolver() { grpc_channel_args_destroy(channel_args_); }
grpc_channel_args_destroy(next_results_);
grpc_channel_args_destroy(reresolution_results_);
grpc_channel_args_destroy(channel_args_);
}
void FakeResolver::StartLocked() { void FakeResolver::StartLocked() {
active_ = true; active_ = true;
@ -112,9 +110,9 @@ void FakeResolver::StartLocked() {
} }
void FakeResolver::RequestReresolutionLocked() { void FakeResolver::RequestReresolutionLocked() {
if (reresolution_results_ != nullptr || return_failure_) { if (has_reresolution_result_ || return_failure_) {
grpc_channel_args_destroy(next_results_); next_result_ = reresolution_result_;
next_results_ = grpc_channel_args_copy(reresolution_results_); has_next_result_ = true;
// Return the result in a different closure, so that we don't call // Return the result in a different closure, so that we don't call
// back into the LB policy while it's still processing the previous // back into the LB policy while it's still processing the previous
// update. // update.
@ -135,14 +133,19 @@ void FakeResolver::MaybeSendResultLocked() {
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver transient failure"), GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver transient failure"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE)); GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
return_failure_ = false; return_failure_ = false;
} else if (next_results_ != nullptr) { } else if (has_next_result_) {
Result result;
result.addresses = std::move(next_result_.addresses);
result.service_config = std::move(next_result_.service_config);
// TODO(roth): Use std::move() once grpc_error is converted to C++.
result.service_config_error = next_result_.service_config_error;
next_result_.service_config_error = GRPC_ERROR_NONE;
// When both next_results_ and channel_args_ contain an arg with the same // When both next_results_ and channel_args_ contain an arg with the same
// name, only the one in next_results_ will be kept since next_results_ is // name, only the one in next_results_ will be kept since next_results_ is
// before channel_args_. // before channel_args_.
result_handler()->ReturnResult( result.args = grpc_channel_args_union(next_result_.args, channel_args_);
grpc_channel_args_union(next_results_, channel_args_)); result_handler()->ReturnResult(std::move(result));
grpc_channel_args_destroy(next_results_); has_next_result_ = false;
next_results_ = nullptr;
} }
} }
@ -160,7 +163,8 @@ void FakeResolver::ReturnReresolutionResult(void* arg, grpc_error* error) {
struct SetResponseClosureArg { struct SetResponseClosureArg {
grpc_closure set_response_closure; grpc_closure set_response_closure;
FakeResolverResponseGenerator* generator; FakeResolverResponseGenerator* generator;
grpc_channel_args* response; Resolver::Result result;
bool has_result = false;
bool immediate = true; bool immediate = true;
}; };
@ -168,26 +172,26 @@ void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
grpc_error* error) { grpc_error* error) {
SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg); SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
FakeResolver* resolver = closure_arg->generator->resolver_; FakeResolver* resolver = closure_arg->generator->resolver_;
grpc_channel_args_destroy(resolver->next_results_); resolver->next_result_ = std::move(closure_arg->result);
resolver->next_results_ = closure_arg->response; resolver->has_next_result_ = true;
resolver->MaybeSendResultLocked(); resolver->MaybeSendResultLocked();
Delete(closure_arg); Delete(closure_arg);
} }
void FakeResolverResponseGenerator::SetResponse(grpc_channel_args* response) { void FakeResolverResponseGenerator::SetResponse(Resolver::Result result) {
GPR_ASSERT(response != nullptr);
if (resolver_ != nullptr) { if (resolver_ != nullptr) {
SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>(); SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
closure_arg->generator = this; closure_arg->generator = this;
closure_arg->response = grpc_channel_args_copy(response); closure_arg->result = std::move(result);
GRPC_CLOSURE_SCHED( GRPC_CLOSURE_SCHED(
GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked, GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetResponseLocked,
closure_arg, closure_arg,
grpc_combiner_scheduler(resolver_->combiner())), grpc_combiner_scheduler(resolver_->combiner())),
GRPC_ERROR_NONE); GRPC_ERROR_NONE);
} else { } else {
GPR_ASSERT(response_ == nullptr); GPR_ASSERT(!has_result_);
response_ = grpc_channel_args_copy(response); has_result_ = true;
result_ = std::move(result);
} }
} }
@ -195,18 +199,29 @@ void FakeResolverResponseGenerator::SetReresolutionResponseLocked(
void* arg, grpc_error* error) { void* arg, grpc_error* error) {
SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg); SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
FakeResolver* resolver = closure_arg->generator->resolver_; FakeResolver* resolver = closure_arg->generator->resolver_;
grpc_channel_args_destroy(resolver->reresolution_results_); resolver->reresolution_result_ = std::move(closure_arg->result);
resolver->reresolution_results_ = closure_arg->response; resolver->has_reresolution_result_ = closure_arg->has_result;
Delete(closure_arg); Delete(closure_arg);
} }
void FakeResolverResponseGenerator::SetReresolutionResponse( void FakeResolverResponseGenerator::SetReresolutionResponse(
grpc_channel_args* response) { Resolver::Result result) {
GPR_ASSERT(resolver_ != nullptr);
SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
closure_arg->generator = this;
closure_arg->result = std::move(result);
closure_arg->has_result = true;
GRPC_CLOSURE_SCHED(
GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
SetReresolutionResponseLocked, closure_arg,
grpc_combiner_scheduler(resolver_->combiner())),
GRPC_ERROR_NONE);
}
void FakeResolverResponseGenerator::UnsetReresolutionResponse() {
GPR_ASSERT(resolver_ != nullptr); GPR_ASSERT(resolver_ != nullptr);
SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>(); SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
closure_arg->generator = this; closure_arg->generator = this;
closure_arg->response =
response != nullptr ? grpc_channel_args_copy(response) : nullptr;
GRPC_CLOSURE_SCHED( GRPC_CLOSURE_SCHED(
GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, GRPC_CLOSURE_INIT(&closure_arg->set_response_closure,
SetReresolutionResponseLocked, closure_arg, SetReresolutionResponseLocked, closure_arg,

@ -19,6 +19,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/resolver.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/error.h"
@ -44,19 +45,20 @@ class FakeResolverResponseGenerator
FakeResolverResponseGenerator() {} FakeResolverResponseGenerator() {}
// Instructs the fake resolver associated with the response generator // Instructs the fake resolver associated with the response generator
// instance to trigger a new resolution with the specified response. If the // instance to trigger a new resolution with the specified result. If the
// resolver is not available yet, delays response setting until it is. This // resolver is not available yet, delays response setting until it is. This
// can be called at most once before the resolver is available. // can be called at most once before the resolver is available.
void SetResponse(grpc_channel_args* next_response); void SetResponse(Resolver::Result result);
// Sets the re-resolution response, which is returned by the fake resolver // Sets the re-resolution response, which is returned by the fake resolver
// when re-resolution is requested (via \a RequestReresolutionLocked()). // when re-resolution is requested (via \a RequestReresolutionLocked()).
// The new re-resolution response replaces any previous re-resolution // The new re-resolution response replaces any previous re-resolution
// response that may have been set by a previous call. // response that may have been set by a previous call.
// If the re-resolution response is set to NULL, then the fake void SetReresolutionResponse(Resolver::Result result);
// resolver will not return anything when \a RequestReresolutionLocked()
// is called. // Unsets the re-resolution response. After this, the fake resolver will
void SetReresolutionResponse(grpc_channel_args* response); // not return anything when \a RequestReresolutionLocked() is called.
void UnsetReresolutionResponse();
// Tells the resolver to return a transient failure. // Tells the resolver to return a transient failure.
void SetFailure(); void SetFailure();
@ -80,7 +82,8 @@ class FakeResolverResponseGenerator
static void SetFailureLocked(void* arg, grpc_error* error); static void SetFailureLocked(void* arg, grpc_error* error);
FakeResolver* resolver_ = nullptr; // Do not own. FakeResolver* resolver_ = nullptr; // Do not own.
grpc_channel_args* response_ = nullptr; Resolver::Result result_;
bool has_result_ = false;
}; };
} // namespace grpc_core } // namespace grpc_core

@ -44,8 +44,7 @@ namespace {
class SockaddrResolver : public Resolver { class SockaddrResolver : public Resolver {
public: public:
/// Takes ownership of \a addresses. SockaddrResolver(ServerAddressList addresses, ResolverArgs args);
explicit SockaddrResolver(ResolverArgs args);
~SockaddrResolver() override; ~SockaddrResolver() override;
void StartLocked() override; void StartLocked() override;
@ -53,21 +52,27 @@ class SockaddrResolver : public Resolver {
void ShutdownLocked() override {} void ShutdownLocked() override {}
private: private:
/// channel args ServerAddressList addresses_;
const grpc_channel_args* channel_args_ = nullptr; const grpc_channel_args* channel_args_ = nullptr;
}; };
SockaddrResolver::SockaddrResolver(ResolverArgs args) SockaddrResolver::SockaddrResolver(ServerAddressList addresses,
ResolverArgs args)
: Resolver(args.combiner, std::move(args.result_handler)), : Resolver(args.combiner, std::move(args.result_handler)),
channel_args_(args.args) {} addresses_(std::move(addresses)),
channel_args_(grpc_channel_args_copy(args.args)) {}
SockaddrResolver::~SockaddrResolver() { SockaddrResolver::~SockaddrResolver() {
grpc_channel_args_destroy(channel_args_); grpc_channel_args_destroy(channel_args_);
} }
void SockaddrResolver::StartLocked() { void SockaddrResolver::StartLocked() {
result_handler()->ReturnResult(channel_args_); Result result;
result.addresses = std::move(addresses_);
// TODO(roth): Use std::move() once channel args is converted to C++.
result.args = channel_args_;
channel_args_ = nullptr; channel_args_ = nullptr;
result_handler()->ReturnResult(std::move(result));
} }
// //
@ -82,7 +87,7 @@ OrphanablePtr<Resolver> CreateSockaddrResolver(
if (0 != strcmp(args.uri->authority, "")) { if (0 != strcmp(args.uri->authority, "")) {
gpr_log(GPR_ERROR, "authority-based URIs not supported by the %s scheme", gpr_log(GPR_ERROR, "authority-based URIs not supported by the %s scheme",
args.uri->scheme); args.uri->scheme);
return OrphanablePtr<Resolver>(nullptr); return nullptr;
} }
// Construct addresses. // Construct addresses.
grpc_slice path_slice = grpc_slice path_slice =
@ -108,12 +113,9 @@ OrphanablePtr<Resolver> CreateSockaddrResolver(
if (errors_found) { if (errors_found) {
return OrphanablePtr<Resolver>(nullptr); return OrphanablePtr<Resolver>(nullptr);
} }
// Add addresses to channel args.
// Note: SockaddrResolver takes ownership of channel args.
grpc_arg arg = CreateServerAddressListChannelArg(&addresses);
args.args = grpc_channel_args_copy_and_add(args.args, &arg, 1);
// Instantiate resolver. // Instantiate resolver.
return OrphanablePtr<Resolver>(New<SockaddrResolver>(std::move(args))); return OrphanablePtr<Resolver>(
New<SockaddrResolver>(std::move(addresses), std::move(args)));
} }
class IPv4ResolverFactory : public ResolverFactory { class IPv4ResolverFactory : public ResolverFactory {

@ -62,6 +62,7 @@ class ResolverRegistry {
/// \a args are the channel args to be included in resolver results. /// \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 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 combiner is the combiner under which all resolver calls will be run.
/// \a result_handler is used to return results from the resolver.
static OrphanablePtr<Resolver> CreateResolver( static OrphanablePtr<Resolver> CreateResolver(
const char* target, const grpc_channel_args* args, const char* target, const grpc_channel_args* args,
grpc_pollset_set* pollset_set, grpc_combiner* combiner, grpc_pollset_set* pollset_set, grpc_combiner* combiner,

@ -31,6 +31,7 @@
#include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/client_channel.h"
#include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/status_util.h" #include "src/core/lib/channel/status_util.h"
#include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/memory.h"
@ -43,42 +44,64 @@ namespace grpc_core {
namespace internal { namespace internal {
ProcessedResolverResult::ProcessedResolverResult( ProcessedResolverResult::ProcessedResolverResult(
const grpc_channel_args& resolver_result, bool parse_retry) { Resolver::Result* resolver_result, bool parse_retry)
ProcessServiceConfig(resolver_result, parse_retry); : service_config_(resolver_result->service_config) {
// If resolver did not return a service config, use the default
// specified via the client API.
if (service_config_ == nullptr) {
const char* service_config_json = grpc_channel_arg_get_string(
grpc_channel_args_find(resolver_result->args, GRPC_ARG_SERVICE_CONFIG));
if (service_config_json != nullptr) {
service_config_ = ServiceConfig::Create(service_config_json);
}
} else {
// Add the service config JSON to channel args so that it's
// accessible in the subchannel.
// TODO(roth): Consider whether there's a better way to pass the
// service config down into the subchannel stack, such as maybe via
// call context or metadata. This would avoid the problem of having
// to recreate all subchannels whenever the service config changes.
// It would also avoid the need to pass in the resolver result in
// mutable form, both here and in
// ResolvingLoadBalancingPolicy::ProcessResolverResultCallback().
grpc_arg arg = grpc_channel_arg_string_create(
const_cast<char*>(GRPC_ARG_SERVICE_CONFIG),
const_cast<char*>(service_config_->service_config_json()));
grpc_channel_args* new_args =
grpc_channel_args_copy_and_add(resolver_result->args, &arg, 1);
grpc_channel_args_destroy(resolver_result->args);
resolver_result->args = new_args;
}
// Process service config.
ProcessServiceConfig(*resolver_result, parse_retry);
// If no LB config was found above, just find the LB policy name then. // If no LB config was found above, just find the LB policy name then.
if (lb_policy_name_ == nullptr) ProcessLbPolicyName(resolver_result); if (lb_policy_name_ == nullptr) ProcessLbPolicyName(*resolver_result);
} }
void ProcessedResolverResult::ProcessServiceConfig( void ProcessedResolverResult::ProcessServiceConfig(
const grpc_channel_args& resolver_result, bool parse_retry) { const Resolver::Result& resolver_result, bool parse_retry) {
const grpc_arg* channel_arg = if (service_config_ == nullptr) return;
grpc_channel_args_find(&resolver_result, GRPC_ARG_SERVICE_CONFIG); service_config_json_ =
const char* service_config_json = grpc_channel_arg_get_string(channel_arg); UniquePtr<char>(gpr_strdup(service_config_->service_config_json()));
if (service_config_json != nullptr) { if (parse_retry) {
service_config_json_.reset(gpr_strdup(service_config_json)); const grpc_arg* channel_arg =
service_config_ = grpc_core::ServiceConfig::Create(service_config_json); grpc_channel_args_find(resolver_result.args, GRPC_ARG_SERVER_URI);
if (service_config_ != nullptr) { const char* server_uri = grpc_channel_arg_get_string(channel_arg);
if (parse_retry) { GPR_ASSERT(server_uri != nullptr);
channel_arg = grpc_uri* uri = grpc_uri_parse(server_uri, true);
grpc_channel_args_find(&resolver_result, GRPC_ARG_SERVER_URI); GPR_ASSERT(uri->path[0] != '\0');
const char* server_uri = grpc_channel_arg_get_string(channel_arg); server_name_ = uri->path[0] == '/' ? uri->path + 1 : uri->path;
GPR_ASSERT(server_uri != nullptr); service_config_->ParseGlobalParams(ParseServiceConfig, this);
grpc_uri* uri = grpc_uri_parse(server_uri, true); grpc_uri_destroy(uri);
GPR_ASSERT(uri->path[0] != '\0'); } else {
server_name_ = uri->path[0] == '/' ? uri->path + 1 : uri->path; service_config_->ParseGlobalParams(ParseServiceConfig, this);
service_config_->ParseGlobalParams(ParseServiceConfig, this);
grpc_uri_destroy(uri);
} else {
service_config_->ParseGlobalParams(ParseServiceConfig, this);
}
method_params_table_ = service_config_->CreateMethodConfigTable(
ClientChannelMethodParams::CreateFromJson);
}
} }
method_params_table_ = service_config_->CreateMethodConfigTable(
ClientChannelMethodParams::CreateFromJson);
} }
void ProcessedResolverResult::ProcessLbPolicyName( void ProcessedResolverResult::ProcessLbPolicyName(
const grpc_channel_args& resolver_result) { const Resolver::Result& resolver_result) {
// Prefer the LB policy name found in the service config. Note that this is // Prefer the LB policy name found in the service config. Note that this is
// checking the deprecated loadBalancingPolicy field, rather than the new // checking the deprecated loadBalancingPolicy field, rather than the new
// loadBalancingConfig field. // loadBalancingConfig field.
@ -96,32 +119,28 @@ void ProcessedResolverResult::ProcessLbPolicyName(
// Otherwise, find the LB policy name set by the client API. // Otherwise, find the LB policy name set by the client API.
if (lb_policy_name_ == nullptr) { if (lb_policy_name_ == nullptr) {
const grpc_arg* channel_arg = const grpc_arg* channel_arg =
grpc_channel_args_find(&resolver_result, GRPC_ARG_LB_POLICY_NAME); grpc_channel_args_find(resolver_result.args, GRPC_ARG_LB_POLICY_NAME);
lb_policy_name_.reset(gpr_strdup(grpc_channel_arg_get_string(channel_arg))); lb_policy_name_.reset(gpr_strdup(grpc_channel_arg_get_string(channel_arg)));
} }
// Special case: If at least one balancer address is present, we use // Special case: If at least one balancer address is present, we use
// the grpclb policy, regardless of what the resolver has returned. // the grpclb policy, regardless of what the resolver has returned.
const ServerAddressList* addresses = bool found_balancer_address = false;
FindServerAddressListChannelArg(&resolver_result); for (size_t i = 0; i < resolver_result.addresses.size(); ++i) {
if (addresses != nullptr) { const ServerAddress& address = resolver_result.addresses[i];
bool found_balancer_address = false; if (address.IsBalancer()) {
for (size_t i = 0; i < addresses->size(); ++i) { found_balancer_address = true;
const ServerAddress& address = (*addresses)[i]; break;
if (address.IsBalancer()) {
found_balancer_address = true;
break;
}
} }
if (found_balancer_address) { }
if (lb_policy_name_ != nullptr && if (found_balancer_address) {
strcmp(lb_policy_name_.get(), "grpclb") != 0) { if (lb_policy_name_ != nullptr &&
gpr_log(GPR_INFO, strcmp(lb_policy_name_.get(), "grpclb") != 0) {
"resolver requested LB policy %s but provided at least one " gpr_log(GPR_INFO,
"balancer address -- forcing use of grpclb LB policy", "resolver requested LB policy %s but provided at least one "
lb_policy_name_.get()); "balancer address -- forcing use of grpclb LB policy",
} lb_policy_name_.get());
lb_policy_name_.reset(gpr_strdup("grpclb"));
} }
lb_policy_name_.reset(gpr_strdup("grpclb"));
} }
// Use pick_first if nothing was specified and we didn't select grpclb // Use pick_first if nothing was specified and we didn't select grpclb
// above. // above.

@ -22,14 +22,15 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/lb_policy.h" #include "src/core/ext/filters/client_channel/lb_policy.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/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/channel/status_util.h"
#include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/exec_ctx.h" // for grpc_millis #include "src/core/lib/iomgr/exec_ctx.h" // for grpc_millis
#include "src/core/lib/json/json.h" #include "src/core/lib/json/json.h"
#include "src/core/lib/slice/slice_hash_table.h" #include "src/core/lib/slice/slice_hash_table.h"
#include "src/core/lib/transport/service_config.h"
namespace grpc_core { namespace grpc_core {
namespace internal { namespace internal {
@ -47,8 +48,7 @@ class ProcessedResolverResult {
// Processes the resolver result and populates the relative members // Processes the resolver result and populates the relative members
// for later consumption. Tries to parse retry parameters only if parse_retry // for later consumption. Tries to parse retry parameters only if parse_retry
// is true. // is true.
ProcessedResolverResult(const grpc_channel_args& resolver_result, ProcessedResolverResult(Resolver::Result* resolver_result, bool parse_retry);
bool parse_retry);
// Getters. Any managed object's ownership is transferred. // Getters. Any managed object's ownership is transferred.
UniquePtr<char> service_config_json() { UniquePtr<char> service_config_json() {
@ -68,11 +68,11 @@ class ProcessedResolverResult {
private: private:
// Finds the service config; extracts LB config and (maybe) retry throttle // Finds the service config; extracts LB config and (maybe) retry throttle
// params from it. // params from it.
void ProcessServiceConfig(const grpc_channel_args& resolver_result, void ProcessServiceConfig(const Resolver::Result& resolver_result,
bool parse_retry); bool parse_retry);
// Finds the LB policy name (when no LB config was found). // Finds the LB policy name (when no LB config was found).
void ProcessLbPolicyName(const grpc_channel_args& resolver_result); void ProcessLbPolicyName(const Resolver::Result& resolver_result);
// Parses the service config. Intended to be used by // Parses the service config. Intended to be used by
// ServiceConfig::ParseGlobalParams. // ServiceConfig::ParseGlobalParams.

@ -38,6 +38,7 @@
#include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/resolver_registry.h"
#include "src/core/ext/filters/client_channel/retry_throttle.h" #include "src/core/ext/filters/client_channel/retry_throttle.h"
#include "src/core/ext/filters/client_channel/server_address.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.h" #include "src/core/ext/filters/client_channel/subchannel.h"
#include "src/core/ext/filters/deadline/deadline_filter.h" #include "src/core/ext/filters/deadline/deadline_filter.h"
#include "src/core/lib/backoff/backoff.h" #include "src/core/lib/backoff/backoff.h"
@ -59,7 +60,6 @@
#include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/service_config.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/status_metadata.h" #include "src/core/lib/transport/status_metadata.h"
@ -83,8 +83,8 @@ class ResolvingLoadBalancingPolicy::ResolverResultHandler
} }
} }
void ReturnResult(const grpc_channel_args* result) override { void ReturnResult(Resolver::Result result) override {
parent_->OnResolverResultChangedLocked(result); parent_->OnResolverResultChangedLocked(std::move(result));
} }
void ReturnError(grpc_error* error) override { void ReturnError(grpc_error* error) override {
@ -342,7 +342,7 @@ void ResolvingLoadBalancingPolicy::OnResolverError(grpc_error* error) {
void ResolvingLoadBalancingPolicy::CreateOrUpdateLbPolicyLocked( void ResolvingLoadBalancingPolicy::CreateOrUpdateLbPolicyLocked(
const char* lb_policy_name, RefCountedPtr<Config> lb_policy_config, const char* lb_policy_name, RefCountedPtr<Config> lb_policy_config,
const grpc_channel_args& args, TraceStringVector* trace_strings) { Resolver::Result result, TraceStringVector* trace_strings) {
// If the child policy name changes, we need to create a new child // If the child policy name changes, we need to create a new child
// policy. When this happens, we leave child_policy_ as-is and store // policy. When this happens, we leave child_policy_ as-is and store
// the new child policy in pending_child_policy_. Once the new child // the new child policy in pending_child_policy_. Once the new child
@ -410,7 +410,8 @@ void ResolvingLoadBalancingPolicy::CreateOrUpdateLbPolicyLocked(
gpr_log(GPR_INFO, "resolving_lb=%p: Creating new %schild policy %s", this, gpr_log(GPR_INFO, "resolving_lb=%p: Creating new %schild policy %s", this,
lb_policy_ == nullptr ? "" : "pending ", lb_policy_name); lb_policy_ == nullptr ? "" : "pending ", lb_policy_name);
} }
auto new_policy = CreateLbPolicyLocked(lb_policy_name, args, trace_strings); auto new_policy =
CreateLbPolicyLocked(lb_policy_name, *result.args, trace_strings);
auto& lb_policy = lb_policy_ == nullptr ? lb_policy_ : pending_lb_policy_; auto& lb_policy = lb_policy_ == nullptr ? lb_policy_ : pending_lb_policy_;
{ {
MutexLock lock(&lb_policy_mu_); MutexLock lock(&lb_policy_mu_);
@ -431,7 +432,13 @@ void ResolvingLoadBalancingPolicy::CreateOrUpdateLbPolicyLocked(
policy_to_update == pending_lb_policy_.get() ? "pending " : "", policy_to_update == pending_lb_policy_.get() ? "pending " : "",
policy_to_update); policy_to_update);
} }
policy_to_update->UpdateLocked(args, std::move(lb_policy_config)); UpdateArgs update_args;
update_args.addresses = std::move(result.addresses);
update_args.config = std::move(lb_policy_config);
// TODO(roth): Once channel args is converted to C++, use std::move() here.
update_args.args = result.args;
result.args = nullptr;
policy_to_update->UpdateLocked(std::move(update_args));
} }
// Creates a new LB policy. // Creates a new LB policy.
@ -479,12 +486,7 @@ ResolvingLoadBalancingPolicy::CreateLbPolicyLocked(
} }
void ResolvingLoadBalancingPolicy::MaybeAddTraceMessagesForAddressChangesLocked( void ResolvingLoadBalancingPolicy::MaybeAddTraceMessagesForAddressChangesLocked(
const grpc_channel_args& resolver_result, bool resolution_contains_addresses, TraceStringVector* trace_strings) {
TraceStringVector* trace_strings) {
const ServerAddressList* addresses =
FindServerAddressListChannelArg(&resolver_result);
const bool resolution_contains_addresses =
addresses != nullptr && addresses->size() > 0;
if (!resolution_contains_addresses && if (!resolution_contains_addresses &&
previous_resolution_contained_addresses_) { previous_resolution_contained_addresses_) {
trace_strings->push_back(gpr_strdup("Address list became empty")); trace_strings->push_back(gpr_strdup("Address list became empty"));
@ -517,14 +519,11 @@ void ResolvingLoadBalancingPolicy::ConcatenateAndAddChannelTraceLocked(
} }
void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked( void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
const grpc_channel_args* result) { Resolver::Result result) {
// Handle race conditions. // Handle race conditions.
if (resolver_ == nullptr) { if (resolver_ == nullptr) return;
grpc_channel_args_destroy(result);
return;
}
if (tracer_->enabled()) { if (tracer_->enabled()) {
gpr_log(GPR_INFO, "resolving_lb=%p: got resolver result %p", this, result); gpr_log(GPR_INFO, "resolving_lb=%p: got resolver result", this);
} }
// We only want to trace the address resolution in the follow cases: // We only want to trace the address resolution in the follow cases:
// (a) Address resolution resulted in service config change. // (a) Address resolution resulted in service config change.
@ -534,15 +533,16 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
// non-zero to zero. // non-zero to zero.
// (d) Address resolution that causes a new LB policy to be created. // (d) Address resolution that causes a new LB policy to be created.
// //
// we track a list of strings to eventually be concatenated and traced. // We track a list of strings to eventually be concatenated and traced.
TraceStringVector trace_strings; TraceStringVector trace_strings;
// Parse the resolver result. const bool resolution_contains_addresses = result.addresses.size() > 0;
// Process the resolver result.
const char* lb_policy_name = nullptr; const char* lb_policy_name = nullptr;
RefCountedPtr<Config> lb_policy_config; RefCountedPtr<Config> lb_policy_config;
bool service_config_changed = false; bool service_config_changed = false;
if (process_resolver_result_ != nullptr) { if (process_resolver_result_ != nullptr) {
service_config_changed = service_config_changed =
process_resolver_result_(process_resolver_result_user_data_, *result, process_resolver_result_(process_resolver_result_user_data_, &result,
&lb_policy_name, &lb_policy_config); &lb_policy_name, &lb_policy_config);
} else { } else {
lb_policy_name = child_policy_name_.get(); lb_policy_name = child_policy_name_.get();
@ -551,7 +551,7 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
GPR_ASSERT(lb_policy_name != nullptr); GPR_ASSERT(lb_policy_name != nullptr);
// Create or update LB policy, as needed. // Create or update LB policy, as needed.
CreateOrUpdateLbPolicyLocked(lb_policy_name, std::move(lb_policy_config), CreateOrUpdateLbPolicyLocked(lb_policy_name, std::move(lb_policy_config),
*result, &trace_strings); std::move(result), &trace_strings);
// Add channel trace event. // Add channel trace event.
if (channelz_node() != nullptr) { if (channelz_node() != nullptr) {
if (service_config_changed) { if (service_config_changed) {
@ -559,11 +559,10 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
// config in the trace, at the risk of bloating the trace logs. // config in the trace, at the risk of bloating the trace logs.
trace_strings.push_back(gpr_strdup("Service config changed")); trace_strings.push_back(gpr_strdup("Service config changed"));
} }
MaybeAddTraceMessagesForAddressChangesLocked(*result, &trace_strings); MaybeAddTraceMessagesForAddressChangesLocked(resolution_contains_addresses,
&trace_strings);
ConcatenateAndAddChannelTraceLocked(&trace_strings); ConcatenateAndAddChannelTraceLocked(&trace_strings);
} }
// Clean up.
grpc_channel_args_destroy(result);
} }
} // namespace grpc_core } // namespace grpc_core

@ -65,8 +65,8 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
// lb_policy_name and lb_policy_config to point to the right data. // lb_policy_name and lb_policy_config to point to the right data.
// Returns true if the service config has changed since the last result. // Returns true if the service config has changed since the last result.
typedef bool (*ProcessResolverResultCallback)( typedef bool (*ProcessResolverResultCallback)(
void* user_data, const grpc_channel_args& args, void* user_data, Resolver::Result* result, const char** lb_policy_name,
const char** lb_policy_name, RefCountedPtr<Config>* lb_policy_config); RefCountedPtr<Config>* lb_policy_config);
// If error is set when this returns, then construction failed, and // If error is set when this returns, then construction failed, and
// the caller may not use the new object. // the caller may not use the new object.
ResolvingLoadBalancingPolicy( ResolvingLoadBalancingPolicy(
@ -79,8 +79,7 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
// No-op -- should never get updates from the channel. // No-op -- should never get updates from the channel.
// TODO(roth): Need to support updating child LB policy's config for xds // TODO(roth): Need to support updating child LB policy's config for xds
// use case. // use case.
void UpdateLocked(const grpc_channel_args& args, void UpdateLocked(UpdateArgs args) override {}
RefCountedPtr<Config> lb_config) override {}
void ExitIdleLocked() override; void ExitIdleLocked() override;
@ -105,17 +104,16 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
void OnResolverError(grpc_error* error); void OnResolverError(grpc_error* error);
void CreateOrUpdateLbPolicyLocked(const char* lb_policy_name, void CreateOrUpdateLbPolicyLocked(const char* lb_policy_name,
RefCountedPtr<Config> lb_policy_config, RefCountedPtr<Config> lb_policy_config,
const grpc_channel_args& args, Resolver::Result result,
TraceStringVector* trace_strings); TraceStringVector* trace_strings);
OrphanablePtr<LoadBalancingPolicy> CreateLbPolicyLocked( OrphanablePtr<LoadBalancingPolicy> CreateLbPolicyLocked(
const char* lb_policy_name, const grpc_channel_args& args, const char* lb_policy_name, const grpc_channel_args& args,
TraceStringVector* trace_strings); TraceStringVector* trace_strings);
void MaybeAddTraceMessagesForAddressChangesLocked( void MaybeAddTraceMessagesForAddressChangesLocked(
const grpc_channel_args& resolver_result, bool resolution_contains_addresses, TraceStringVector* trace_strings);
TraceStringVector* trace_strings);
void ConcatenateAndAddChannelTraceLocked( void ConcatenateAndAddChannelTraceLocked(
TraceStringVector* trace_strings) const; TraceStringVector* trace_strings) const;
void OnResolverResultChangedLocked(const grpc_channel_args* result); void OnResolverResultChangedLocked(Resolver::Result result);
// Passed in from caller at construction time. // Passed in from caller at construction time.
TraceFlag* tracer_; TraceFlag* tracer_;

@ -52,52 +52,4 @@ bool ServerAddress::IsBalancer() const {
grpc_channel_args_find(args_, GRPC_ARG_ADDRESS_IS_BALANCER), false); grpc_channel_args_find(args_, GRPC_ARG_ADDRESS_IS_BALANCER), false);
} }
//
// ServerAddressList
//
namespace {
void* ServerAddressListCopy(void* addresses) {
ServerAddressList* a = static_cast<ServerAddressList*>(addresses);
return New<ServerAddressList>(*a);
}
void ServerAddressListDestroy(void* addresses) {
ServerAddressList* a = static_cast<ServerAddressList*>(addresses);
Delete(a);
}
int ServerAddressListCompare(void* addresses1, void* addresses2) {
ServerAddressList* a1 = static_cast<ServerAddressList*>(addresses1);
ServerAddressList* a2 = static_cast<ServerAddressList*>(addresses2);
if (a1->size() > a2->size()) return 1;
if (a1->size() < a2->size()) return -1;
for (size_t i = 0; i < a1->size(); ++i) {
int retval = (*a1)[i].Cmp((*a2)[i]);
if (retval != 0) return retval;
}
return 0;
}
const grpc_arg_pointer_vtable server_addresses_arg_vtable = {
ServerAddressListCopy, ServerAddressListDestroy, ServerAddressListCompare};
} // namespace
grpc_arg CreateServerAddressListChannelArg(const ServerAddressList* addresses) {
return grpc_channel_arg_pointer_create(
const_cast<char*>(GRPC_ARG_SERVER_ADDRESS_LIST),
const_cast<ServerAddressList*>(addresses), &server_addresses_arg_vtable);
}
ServerAddressList* FindServerAddressListChannelArg(
const grpc_channel_args* channel_args) {
const grpc_arg* lb_addresses_arg =
grpc_channel_args_find(channel_args, GRPC_ARG_SERVER_ADDRESS_LIST);
if (lb_addresses_arg == nullptr || lb_addresses_arg->type != GRPC_ARG_POINTER)
return nullptr;
return static_cast<ServerAddressList*>(lb_addresses_arg->value.pointer.p);
}
} // namespace grpc_core } // namespace grpc_core

@ -26,9 +26,6 @@
#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/uri/uri_parser.h" #include "src/core/lib/uri/uri_parser.h"
// Channel arg key for ServerAddressList.
#define GRPC_ARG_SERVER_ADDRESS_LIST "grpc.server_address_list"
// Channel arg key for a bool indicating whether an address is a grpclb // Channel arg key for a bool indicating whether an address is a grpclb
// load balancer (as opposed to a backend). // load balancer (as opposed to a backend).
#define GRPC_ARG_ADDRESS_IS_BALANCER "grpc.address_is_balancer" #define GRPC_ARG_ADDRESS_IS_BALANCER "grpc.address_is_balancer"
@ -96,13 +93,6 @@ class ServerAddress {
typedef InlinedVector<ServerAddress, 1> ServerAddressList; typedef InlinedVector<ServerAddress, 1> ServerAddressList;
// Returns a channel arg containing \a addresses.
grpc_arg CreateServerAddressListChannelArg(const ServerAddressList* addresses);
// Returns the ServerListAddress instance in channel_args or NULL.
ServerAddressList* FindServerAddressListChannelArg(
const grpc_channel_args* channel_args);
} // namespace grpc_core } // namespace grpc_core
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVER_ADDRESS_H */ #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVER_ADDRESS_H */

@ -16,7 +16,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "src/core/lib/transport/service_config.h" #include "src/core/ext/filters/client_channel/service_config.h"
#include <string.h> #include <string.h>
@ -34,17 +34,22 @@
namespace grpc_core { namespace grpc_core {
RefCountedPtr<ServiceConfig> ServiceConfig::Create(const char* json) { RefCountedPtr<ServiceConfig> ServiceConfig::Create(const char* json) {
UniquePtr<char> service_config_json(gpr_strdup(json));
UniquePtr<char> json_string(gpr_strdup(json)); UniquePtr<char> json_string(gpr_strdup(json));
grpc_json* json_tree = grpc_json_parse_string(json_string.get()); grpc_json* json_tree = grpc_json_parse_string(json_string.get());
if (json_tree == nullptr) { if (json_tree == nullptr) {
gpr_log(GPR_INFO, "failed to parse JSON for service config"); gpr_log(GPR_INFO, "failed to parse JSON for service config");
return nullptr; return nullptr;
} }
return MakeRefCounted<ServiceConfig>(std::move(json_string), json_tree); return MakeRefCounted<ServiceConfig>(std::move(service_config_json),
std::move(json_string), json_tree);
} }
ServiceConfig::ServiceConfig(UniquePtr<char> json_string, grpc_json* json_tree) ServiceConfig::ServiceConfig(UniquePtr<char> service_config_json,
: json_string_(std::move(json_string)), json_tree_(json_tree) {} UniquePtr<char> json_string, grpc_json* json_tree)
: service_config_json_(std::move(service_config_json)),
json_string_(std::move(json_string)),
json_tree_(json_tree) {}
ServiceConfig::~ServiceConfig() { grpc_json_destroy(json_tree_); } ServiceConfig::~ServiceConfig() { grpc_json_destroy(json_tree_); }

@ -14,8 +14,8 @@
// limitations under the License. // limitations under the License.
// //
#ifndef GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_H
#define GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_H
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
@ -62,6 +62,8 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
~ServiceConfig(); ~ServiceConfig();
const char* service_config_json() const { return service_config_json_.get(); }
/// Invokes \a process_json() for each global parameter in the service /// Invokes \a process_json() for each global parameter in the service
/// config. \a arg is passed as the second argument to \a process_json(). /// config. \a arg is passed as the second argument to \a process_json().
template <typename T> template <typename T>
@ -82,7 +84,7 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
using CreateValue = RefCountedPtr<T> (*)(const grpc_json* method_config_json); using CreateValue = RefCountedPtr<T> (*)(const grpc_json* method_config_json);
template <typename T> template <typename T>
RefCountedPtr<SliceHashTable<RefCountedPtr<T>>> CreateMethodConfigTable( RefCountedPtr<SliceHashTable<RefCountedPtr<T>>> CreateMethodConfigTable(
CreateValue<T> create_value); CreateValue<T> create_value) const;
/// A helper function for looking up values in the table returned by /// A helper function for looking up values in the table returned by
/// \a CreateMethodConfigTable(). /// \a CreateMethodConfigTable().
@ -100,7 +102,8 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
friend T* New(Args&&... args); friend T* New(Args&&... args);
// Takes ownership of \a json_tree. // Takes ownership of \a json_tree.
ServiceConfig(UniquePtr<char> json_string, grpc_json* json_tree); ServiceConfig(UniquePtr<char> service_config_json,
UniquePtr<char> json_string, grpc_json* json_tree);
// Returns the number of names specified in the method config \a json. // Returns the number of names specified in the method config \a json.
static int CountNamesInMethodConfig(grpc_json* json); static int CountNamesInMethodConfig(grpc_json* json);
@ -117,6 +120,7 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
grpc_json* json, CreateValue<T> create_value, grpc_json* json, CreateValue<T> create_value,
typename SliceHashTable<RefCountedPtr<T>>::Entry* entries, size_t* idx); typename SliceHashTable<RefCountedPtr<T>>::Entry* entries, size_t* idx);
UniquePtr<char> service_config_json_;
UniquePtr<char> json_string_; // Underlying storage for json_tree. UniquePtr<char> json_string_; // Underlying storage for json_tree.
grpc_json* json_tree_; grpc_json* json_tree_;
}; };
@ -172,7 +176,7 @@ bool ServiceConfig::ParseJsonMethodConfig(
template <typename T> template <typename T>
RefCountedPtr<SliceHashTable<RefCountedPtr<T>>> RefCountedPtr<SliceHashTable<RefCountedPtr<T>>>
ServiceConfig::CreateMethodConfigTable(CreateValue<T> create_value) { ServiceConfig::CreateMethodConfigTable(CreateValue<T> create_value) const {
// Traverse parsed JSON tree. // Traverse parsed JSON tree.
if (json_tree_->type != GRPC_JSON_OBJECT || json_tree_->key != nullptr) { if (json_tree_->type != GRPC_JSON_OBJECT || json_tree_->key != nullptr) {
return nullptr; return nullptr;
@ -247,4 +251,4 @@ RefCountedPtr<T> ServiceConfig::MethodConfigTableLookup(
} // namespace grpc_core } // namespace grpc_core
#endif /* GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H */ #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_H */

@ -33,6 +33,7 @@
#include "src/core/ext/filters/client_channel/health/health_check_client.h" #include "src/core/ext/filters/client_channel/health/health_check_client.h"
#include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
#include "src/core/lib/backoff/backoff.h" #include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
@ -50,7 +51,6 @@
#include "src/core/lib/surface/channel_init.h" #include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/service_config.h"
#include "src/core/lib/transport/status_metadata.h" #include "src/core/lib/transport/status_metadata.h"
#include "src/core/lib/uri/uri_parser.h" #include "src/core/lib/uri/uri_parser.h"

@ -26,13 +26,13 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/surface/channel_init.h" #include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/transport/service_config.h"
typedef struct { typedef struct {
int max_send_size; int max_send_size;

@ -1268,7 +1268,9 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) { if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) {
if ((t->write_state == GRPC_CHTTP2_WRITE_STATE_IDLE) || if ((t->write_state == GRPC_CHTTP2_WRITE_STATE_IDLE) ||
!(closure->next_data.scratch & CLOSURE_BARRIER_MAY_COVER_WRITE)) { !(closure->next_data.scratch & CLOSURE_BARRIER_MAY_COVER_WRITE)) {
GRPC_CLOSURE_RUN(closure, closure->error_data.error); // Using GRPC_CLOSURE_SCHED instead of GRPC_CLOSURE_RUN to avoid running
// closures earlier than when it is safe to do so.
GRPC_CLOSURE_SCHED(closure, closure->error_data.error);
} else { } else {
grpc_closure_list_append(&t->run_after_write, closure, grpc_closure_list_append(&t->run_after_write, closure,
closure->error_data.error); closure->error_data.error);

@ -118,6 +118,8 @@ grpc_channel_args* grpc_channel_args_copy(const grpc_channel_args* src) {
grpc_channel_args* grpc_channel_args_union(const grpc_channel_args* a, grpc_channel_args* grpc_channel_args_union(const grpc_channel_args* a,
const grpc_channel_args* b) { const grpc_channel_args* b) {
if (a == nullptr) return grpc_channel_args_copy(b);
if (b == nullptr) return grpc_channel_args_copy(a);
const size_t max_out = (a->num_args + b->num_args); const size_t max_out = (a->num_args + b->num_args);
grpc_arg* uniques = grpc_arg* uniques =
static_cast<grpc_arg*>(gpr_malloc(sizeof(*uniques) * max_out)); static_cast<grpc_arg*>(gpr_malloc(sizeof(*uniques) * max_out));

@ -1246,6 +1246,11 @@ static bool is_any_background_poller_thread(void) { return false; }
static void shutdown_background_closure(void) {} static void shutdown_background_closure(void) {}
static bool add_closure_to_background_poller(grpc_closure* closure,
grpc_error* error) {
return false;
}
static void shutdown_engine(void) { static void shutdown_engine(void) {
fd_global_shutdown(); fd_global_shutdown();
pollset_global_shutdown(); pollset_global_shutdown();
@ -1292,6 +1297,7 @@ static const grpc_event_engine_vtable vtable = {
is_any_background_poller_thread, is_any_background_poller_thread,
shutdown_background_closure, shutdown_background_closure,
shutdown_engine, shutdown_engine,
add_closure_to_background_poller,
}; };
/* Called by the child process's post-fork handler to close open fds, including /* Called by the child process's post-fork handler to close open fds, including

@ -1578,6 +1578,11 @@ static bool is_any_background_poller_thread(void) { return false; }
static void shutdown_background_closure(void) {} static void shutdown_background_closure(void) {}
static bool add_closure_to_background_poller(grpc_closure* closure,
grpc_error* error) {
return false;
}
static void shutdown_engine(void) { static void shutdown_engine(void) {
fd_global_shutdown(); fd_global_shutdown();
pollset_global_shutdown(); pollset_global_shutdown();
@ -1619,6 +1624,7 @@ static const grpc_event_engine_vtable vtable = {
is_any_background_poller_thread, is_any_background_poller_thread,
shutdown_background_closure, shutdown_background_closure,
shutdown_engine, shutdown_engine,
add_closure_to_background_poller,
}; };
const grpc_event_engine_vtable* grpc_init_epollex_linux( const grpc_event_engine_vtable* grpc_init_epollex_linux(

@ -1320,6 +1320,11 @@ static bool is_any_background_poller_thread(void) { return false; }
static void shutdown_background_closure(void) {} static void shutdown_background_closure(void) {}
static bool add_closure_to_background_poller(grpc_closure* closure,
grpc_error* error) {
return false;
}
static void shutdown_engine(void) { static void shutdown_engine(void) {
pollset_global_shutdown(); pollset_global_shutdown();
if (track_fds_for_fork) { if (track_fds_for_fork) {
@ -1364,6 +1369,7 @@ static const grpc_event_engine_vtable vtable = {
is_any_background_poller_thread, is_any_background_poller_thread,
shutdown_background_closure, shutdown_background_closure,
shutdown_engine, shutdown_engine,
add_closure_to_background_poller,
}; };
/* Called by the child process's post-fork handler to close open fds, including /* Called by the child process's post-fork handler to close open fds, including

@ -402,6 +402,11 @@ bool grpc_is_any_background_poller_thread(void) {
return g_event_engine->is_any_background_poller_thread(); return g_event_engine->is_any_background_poller_thread();
} }
bool grpc_add_closure_to_background_poller(grpc_closure* closure,
grpc_error* error) {
return g_event_engine->add_closure_to_background_poller(closure, error);
}
void grpc_shutdown_background_closure(void) { void grpc_shutdown_background_closure(void) {
g_event_engine->shutdown_background_closure(); g_event_engine->shutdown_background_closure();
} }

@ -83,6 +83,8 @@ typedef struct grpc_event_engine_vtable {
bool (*is_any_background_poller_thread)(void); bool (*is_any_background_poller_thread)(void);
void (*shutdown_background_closure)(void); void (*shutdown_background_closure)(void);
void (*shutdown_engine)(void); void (*shutdown_engine)(void);
bool (*add_closure_to_background_poller)(grpc_closure* closure,
grpc_error* error);
} grpc_event_engine_vtable; } grpc_event_engine_vtable;
/* register a new event engine factory */ /* register a new event engine factory */
@ -185,6 +187,12 @@ void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd);
/* Returns true if the caller is a worker thread for any background poller. */ /* Returns true if the caller is a worker thread for any background poller. */
bool grpc_is_any_background_poller_thread(); bool grpc_is_any_background_poller_thread();
/* Returns true if the closure is registered into the background poller. Note
* that the closure may or may not run yet when this function returns, and the
* closure should not be blocking or long-running. */
bool grpc_add_closure_to_background_poller(grpc_closure* closure,
grpc_error* error);
/* Shut down all the closures registered in the background poller. */ /* Shut down all the closures registered in the background poller. */
void grpc_shutdown_background_closure(); void grpc_shutdown_background_closure();

@ -32,6 +32,7 @@
#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/iomgr.h"
#define MAX_DEPTH 2 #define MAX_DEPTH 2
@ -206,6 +207,14 @@ void Executor::SetThreading(bool threading) {
gpr_free(thd_state_); gpr_free(thd_state_);
gpr_tls_destroy(&g_this_thread_state); gpr_tls_destroy(&g_this_thread_state);
// grpc_iomgr_shutdown_background_closure() will close all the registered
// fds in the background poller, and wait for all pending closures to
// finish. Thus, never call Executor::SetThreading(false) in the middle of
// an application.
// TODO(guantaol): create another method to finish all the pending closures
// registered in the background poller by grpc_core::Executor.
grpc_iomgr_shutdown_background_closure();
} }
EXECUTOR_TRACE("(%s) SetThreading(%d) done", name_, threading); EXECUTOR_TRACE("(%s) SetThreading(%d) done", name_, threading);
@ -278,6 +287,10 @@ void Executor::Enqueue(grpc_closure* closure, grpc_error* error,
return; return;
} }
if (grpc_iomgr_add_closure_to_background_poller(closure, error)) {
return;
}
ThreadState* ts = (ThreadState*)gpr_tls_get(&g_this_thread_state); ThreadState* ts = (ThreadState*)gpr_tls_get(&g_this_thread_state);
if (ts == nullptr) { if (ts == nullptr) {
ts = &thd_state_[GPR_HASH_POINTER(grpc_core::ExecCtx::Get(), ts = &thd_state_[GPR_HASH_POINTER(grpc_core::ExecCtx::Get(),

@ -61,7 +61,8 @@ class Executor {
/** Is the executor multi-threaded? */ /** Is the executor multi-threaded? */
bool IsThreaded() const; bool IsThreaded() const;
/* Enable/disable threading - must be called after Init and Shutdown() */ /* Enable/disable threading - must be called after Init and Shutdown(). Never
* call SetThreading(false) in the middle of an application */
void SetThreading(bool threading); void SetThreading(bool threading);
/** Shutdown the executor, running all pending work as part of the call */ /** Shutdown the executor, running all pending work as part of the call */

@ -162,6 +162,11 @@ bool grpc_iomgr_is_any_background_poller_thread() {
return grpc_iomgr_platform_is_any_background_poller_thread(); return grpc_iomgr_platform_is_any_background_poller_thread();
} }
bool grpc_iomgr_add_closure_to_background_poller(grpc_closure* closure,
grpc_error* error) {
return grpc_iomgr_platform_add_closure_to_background_poller(closure, error);
}
void grpc_iomgr_register_object(grpc_iomgr_object* obj, const char* name) { void grpc_iomgr_register_object(grpc_iomgr_object* obj, const char* name) {
obj->name = gpr_strdup(name); obj->name = gpr_strdup(name);
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);

@ -21,6 +21,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/port.h"
#include <stdlib.h> #include <stdlib.h>
@ -47,6 +48,12 @@ bool grpc_iomgr_run_in_background();
/** Returns true if the caller is a worker thread for any background poller. */ /** Returns true if the caller is a worker thread for any background poller. */
bool grpc_iomgr_is_any_background_poller_thread(); bool grpc_iomgr_is_any_background_poller_thread();
/** Returns true if the closure is registered into the background poller. Note
* that the closure may or may not run yet when this function returns, and the
* closure should not be blocking or long-running. */
bool grpc_iomgr_add_closure_to_background_poller(grpc_closure* closure,
grpc_error* error);
/* Exposed only for testing */ /* Exposed only for testing */
size_t grpc_iomgr_count_objects_for_testing(); size_t grpc_iomgr_count_objects_for_testing();

@ -44,11 +44,18 @@ static void iomgr_platform_shutdown_background_closure(void) {}
static bool iomgr_platform_is_any_background_poller_thread(void) { static bool iomgr_platform_is_any_background_poller_thread(void) {
return false; return false;
} }
static bool iomgr_platform_add_closure_to_background_poller(
grpc_closure* closure, grpc_error* error) {
return false;
}
static grpc_iomgr_platform_vtable vtable = { static grpc_iomgr_platform_vtable vtable = {
iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, iomgr_platform_init,
iomgr_platform_flush,
iomgr_platform_shutdown,
iomgr_platform_shutdown_background_closure, iomgr_platform_shutdown_background_closure,
iomgr_platform_is_any_background_poller_thread}; iomgr_platform_is_any_background_poller_thread,
iomgr_platform_add_closure_to_background_poller};
void grpc_custom_iomgr_init(grpc_socket_vtable* socket, void grpc_custom_iomgr_init(grpc_socket_vtable* socket,
grpc_custom_resolver_vtable* resolver, grpc_custom_resolver_vtable* resolver,

@ -49,3 +49,9 @@ void grpc_iomgr_platform_shutdown_background_closure() {
bool grpc_iomgr_platform_is_any_background_poller_thread() { bool grpc_iomgr_platform_is_any_background_poller_thread() {
return iomgr_platform_vtable->is_any_background_poller_thread(); return iomgr_platform_vtable->is_any_background_poller_thread();
} }
bool grpc_iomgr_platform_add_closure_to_background_poller(grpc_closure* closure,
grpc_error* error) {
return iomgr_platform_vtable->add_closure_to_background_poller(closure,
error);
}

@ -37,6 +37,8 @@ typedef struct grpc_iomgr_platform_vtable {
void (*shutdown)(void); void (*shutdown)(void);
void (*shutdown_background_closure)(void); void (*shutdown_background_closure)(void);
bool (*is_any_background_poller_thread)(void); bool (*is_any_background_poller_thread)(void);
bool (*add_closure_to_background_poller)(grpc_closure* closure,
grpc_error* error);
} grpc_iomgr_platform_vtable; } grpc_iomgr_platform_vtable;
void grpc_iomgr_register_object(grpc_iomgr_object* obj, const char* name); void grpc_iomgr_register_object(grpc_iomgr_object* obj, const char* name);
@ -57,9 +59,15 @@ void grpc_iomgr_platform_shutdown(void);
/** shut down all the closures registered in the background poller */ /** shut down all the closures registered in the background poller */
void grpc_iomgr_platform_shutdown_background_closure(void); void grpc_iomgr_platform_shutdown_background_closure(void);
/** return true is the caller is a worker thread for any background poller */ /** return true if the caller is a worker thread for any background poller */
bool grpc_iomgr_platform_is_any_background_poller_thread(void); bool grpc_iomgr_platform_is_any_background_poller_thread(void);
/** Return true if the closure is registered into the background poller. Note
* that the closure may or may not run yet when this function returns, and the
* closure should not be blocking or long-running. */
bool grpc_iomgr_platform_add_closure_to_background_poller(grpc_closure* closure,
grpc_error* error);
bool grpc_iomgr_abort_on_leaks(void); bool grpc_iomgr_abort_on_leaks(void);
#endif /* GRPC_CORE_LIB_IOMGR_IOMGR_INTERNAL_H */ #endif /* GRPC_CORE_LIB_IOMGR_IOMGR_INTERNAL_H */

@ -59,10 +59,18 @@ static bool iomgr_platform_is_any_background_poller_thread(void) {
return grpc_is_any_background_poller_thread(); return grpc_is_any_background_poller_thread();
} }
static bool iomgr_platform_add_closure_to_background_poller(
grpc_closure* closure, grpc_error* error) {
return grpc_add_closure_to_background_poller(closure, error);
}
static grpc_iomgr_platform_vtable vtable = { static grpc_iomgr_platform_vtable vtable = {
iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, iomgr_platform_init,
iomgr_platform_flush,
iomgr_platform_shutdown,
iomgr_platform_shutdown_background_closure, iomgr_platform_shutdown_background_closure,
iomgr_platform_is_any_background_poller_thread}; iomgr_platform_is_any_background_poller_thread,
iomgr_platform_add_closure_to_background_poller};
void grpc_set_default_iomgr_platform() { void grpc_set_default_iomgr_platform() {
grpc_set_tcp_client_impl(&grpc_posix_tcp_client_vtable); grpc_set_tcp_client_impl(&grpc_posix_tcp_client_vtable);

@ -62,10 +62,18 @@ static bool iomgr_platform_is_any_background_poller_thread(void) {
return grpc_is_any_background_poller_thread(); return grpc_is_any_background_poller_thread();
} }
static bool iomgr_platform_add_closure_to_background_poller(
grpc_closure* closure, grpc_error* error) {
return grpc_add_closure_to_background_poller(closure, error);
}
static grpc_iomgr_platform_vtable vtable = { static grpc_iomgr_platform_vtable vtable = {
iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, iomgr_platform_init,
iomgr_platform_flush,
iomgr_platform_shutdown,
iomgr_platform_shutdown_background_closure, iomgr_platform_shutdown_background_closure,
iomgr_platform_is_any_background_poller_thread}; iomgr_platform_is_any_background_poller_thread,
iomgr_platform_add_closure_to_background_poller};
void grpc_set_default_iomgr_platform() { void grpc_set_default_iomgr_platform() {
char* enable_cfstream = getenv(grpc_cfstream_env_var); char* enable_cfstream = getenv(grpc_cfstream_env_var);

@ -77,10 +77,18 @@ static bool iomgr_platform_is_any_background_poller_thread(void) {
return false; return false;
} }
static bool iomgr_platform_add_closure_to_background_poller(
grpc_closure* closure, grpc_error* error) {
return false;
}
static grpc_iomgr_platform_vtable vtable = { static grpc_iomgr_platform_vtable vtable = {
iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, iomgr_platform_init,
iomgr_platform_flush,
iomgr_platform_shutdown,
iomgr_platform_shutdown_background_closure, iomgr_platform_shutdown_background_closure,
iomgr_platform_is_any_background_poller_thread}; iomgr_platform_is_any_background_poller_thread,
iomgr_platform_add_closure_to_background_poller};
void grpc_set_default_iomgr_platform() { void grpc_set_default_iomgr_platform() {
grpc_set_tcp_client_impl(&grpc_windows_tcp_client_vtable); grpc_set_tcp_client_impl(&grpc_windows_tcp_client_vtable);

@ -624,8 +624,9 @@ static int verify_jwt_signature(EVP_PKEY* key, const char* alg,
gpr_log(GPR_ERROR, "EVP_DigestVerifyUpdate failed."); gpr_log(GPR_ERROR, "EVP_DigestVerifyUpdate failed.");
goto end; goto end;
} }
if (EVP_DigestVerifyFinal(md_ctx, GRPC_SLICE_START_PTR(signature), if (EVP_DigestVerifyFinal(
GRPC_SLICE_LENGTH(signature)) != 1) { md_ctx, const_cast<uint8_t*>(GRPC_SLICE_START_PTR(signature)),
GRPC_SLICE_LENGTH(signature)) != 1) {
gpr_log(GPR_ERROR, "JWT signature verification failed."); gpr_log(GPR_ERROR, "JWT signature verification failed.");
goto end; goto end;
} }

@ -111,10 +111,11 @@ void grpc_transport_move_stats(grpc_transport_stream_stats* from,
// currently handling the batch). Once a filter or transport passes control // currently handling the batch). Once a filter or transport passes control
// of the batch to the next handler, it cannot depend on the contents of // of the batch to the next handler, it cannot depend on the contents of
// this struct anymore, because the next handler may reuse it. // this struct anymore, because the next handler may reuse it.
typedef struct { struct grpc_handler_private_op_data {
void* extra_arg; void* extra_arg = nullptr;
grpc_closure closure; grpc_closure closure;
} grpc_handler_private_op_data; grpc_handler_private_op_data() { memset(&closure, 0, sizeof(closure)); }
};
typedef struct grpc_transport_stream_op_batch_payload typedef struct grpc_transport_stream_op_batch_payload
grpc_transport_stream_op_batch_payload; grpc_transport_stream_op_batch_payload;

@ -39,7 +39,7 @@ namespace Grpc.Core
/// </summary> /// </summary>
/// <param name="peerIdentityPropertyName">Peer identity property name.</param> /// <param name="peerIdentityPropertyName">Peer identity property name.</param>
/// <param name="properties">Multimap of auth properties by name.</param> /// <param name="properties">Multimap of auth properties by name.</param>
internal AuthContext(string peerIdentityPropertyName, Dictionary<string, List<AuthProperty>> properties) public AuthContext(string peerIdentityPropertyName, Dictionary<string, List<AuthProperty>> properties)
{ {
this.peerIdentityPropertyName = peerIdentityPropertyName; this.peerIdentityPropertyName = peerIdentityPropertyName;
this.properties = GrpcPreconditions.CheckNotNull(properties); this.properties = GrpcPreconditions.CheckNotNull(properties);

@ -0,0 +1,7 @@
<!-- This file is generated -->
<Project>
<PropertyGroup>
<GrpcCsharpVersion>1.19.1</GrpcCsharpVersion>
<GoogleProtobufVersion>3.6.1</GoogleProtobufVersion>
</PropertyGroup>
</Project>

@ -16,6 +16,8 @@
#endregion #endregion
using System.Collections.Generic;
using System.Linq;
using System.Reflection; // UWYU: Object.GetType() extension. using System.Reflection; // UWYU: Object.GetType() extension.
using Microsoft.Build.Framework; using Microsoft.Build.Framework;
using Moq; using Moq;
@ -30,6 +32,7 @@ namespace Grpc.Tools.Tests
{ {
public string LastPathToTool { get; private set; } public string LastPathToTool { get; private set; }
public string[] LastResponseFile { get; private set; } public string[] LastResponseFile { get; private set; }
public List<string> StdErrMessages { get; } = new List<string>();
protected override int ExecuteTool(string pathToTool, protected override int ExecuteTool(string pathToTool,
string response, string response,
@ -45,8 +48,13 @@ namespace Grpc.Tools.Tests
LastPathToTool = pathToTool; LastPathToTool = pathToTool;
LastResponseFile = response.Remove(response.Length - 1).Split('\n'); LastResponseFile = response.Remove(response.Length - 1).Split('\n');
foreach (string message in StdErrMessages)
{
LogEventsFromTextOutput(message, MessageImportance.High);
}
// Do not run the tool, but pretend it ran successfully. // Do not run the tool, but pretend it ran successfully.
return 0; return StdErrMessages.Any() ? -1 : 0;
} }
}; };

@ -175,5 +175,86 @@ namespace Grpc.Tools.Tests
Assert.That(_task.LastResponseFile, Assert.That(_task.LastResponseFile,
Does.Contain("--csharp_out=" + expect)); Does.Contain("--csharp_out=" + expect));
} }
[TestCase(
"../Protos/greet.proto(19) : warning in column=5 : warning : When enum name is stripped and label is PascalCased (Zero) this value label conflicts with Zero.",
"../Protos/greet.proto",
19,
5,
"warning : When enum name is stripped and label is PascalCased (Zero) this value label conflicts with Zero.")]
[TestCase(
"../Protos/greet.proto: warning: Import google/protobuf/empty.proto but not used.",
"../Protos/greet.proto",
0,
0,
"Import google/protobuf/empty.proto but not used.")]
[TestCase("../Protos/greet.proto(14) : error in column=10: \"name\" is already defined in \"Greet.HelloRequest\".", null, 0, 0, null)]
[TestCase("../Protos/greet.proto: Import \"google / protobuf / empty.proto\" was listed twice.", null, 0, 0, null)]
public void WarningsParsed(string stderr, string file, int line, int col, string message)
{
_task.StdErrMessages.Add(stderr);
_mockEngine
.Setup(me => me.LogWarningEvent(It.IsAny<BuildWarningEventArgs>()))
.Callback((BuildWarningEventArgs e) => {
if (file != null)
{
Assert.AreEqual(file, e.File);
Assert.AreEqual(line, e.LineNumber);
Assert.AreEqual(col, e.ColumnNumber);
Assert.AreEqual(message, e.Message);
}
else
{
Assert.Fail($"Error logged by build engine:\n{e.Message}");
}
});
bool result = _task.Execute();
Assert.IsFalse(result);
}
[TestCase(
"../Protos/greet.proto(14) : error in column=10: \"name\" is already defined in \"Greet.HelloRequest\".",
"../Protos/greet.proto",
14,
10,
"\"name\" is already defined in \"Greet.HelloRequest\".")]
[TestCase(
"../Protos/greet.proto: Import \"google / protobuf / empty.proto\" was listed twice.",
"../Protos/greet.proto",
0,
0,
"Import \"google / protobuf / empty.proto\" was listed twice.")]
[TestCase("../Protos/greet.proto(19) : warning in column=5 : warning : When enum name is stripped and label is PascalCased (Zero) this value label conflicts with Zero.", null, 0, 0, null)]
[TestCase("../Protos/greet.proto: warning: Import google/protobuf/empty.proto but not used.", null, 0, 0, null)]
public void ErrorsParsed(string stderr, string file, int line, int col, string message)
{
_task.StdErrMessages.Add(stderr);
_mockEngine
.Setup(me => me.LogErrorEvent(It.IsAny<BuildErrorEventArgs>()))
.Callback((BuildErrorEventArgs e) => {
if (file != null)
{
Assert.AreEqual(file, e.File);
Assert.AreEqual(line, e.LineNumber);
Assert.AreEqual(col, e.ColumnNumber);
Assert.AreEqual(message, e.Message);
}
else
{
// Ignore expected error
// "protoc/protoc.exe" existed with code -1.
if (!e.Message.EndsWith("exited with code -1."))
{
Assert.Fail($"Error logged by build engine:\n{e.Message}");
}
}
});
bool result = _task.Execute();
Assert.IsFalse(result);
}
}; };
} }

@ -16,7 +16,10 @@
#endregion #endregion
using System;
using System.Collections.Generic;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Build.Framework; using Microsoft.Build.Framework;
using Microsoft.Build.Utilities; using Microsoft.Build.Utilities;
@ -123,6 +126,110 @@ namespace Grpc.Tools
"javanano", "js", "objc", "javanano", "js", "objc",
"php", "python", "ruby" }; "php", "python", "ruby" };
static readonly TimeSpan s_regexTimeout = TimeSpan.FromMilliseconds(100);
static readonly List<ErrorListFilter> s_errorListFilters = new List<ErrorListFilter>()
{
// Example warning with location
//../Protos/greet.proto(19) : warning in column=5 : warning : When enum name is stripped and label is PascalCased (Zero),
// this value label conflicts with Zero. This will make the proto fail to compile for some languages, such as C#.
new ErrorListFilter
{
Pattern = new Regex(
pattern: "(?'FILENAME'.+)\\((?'LINE'\\d+)\\) ?: ?warning in column=(?'COLUMN'\\d+) ?: ?(?'TEXT'.*)",
options: RegexOptions.Compiled | RegexOptions.IgnoreCase,
matchTimeout: s_regexTimeout),
LogAction = (log, match) =>
{
int.TryParse(match.Groups["LINE"].Value, out var line);
int.TryParse(match.Groups["COLUMN"].Value, out var column);
log.LogWarning(
subcategory: null,
warningCode: null,
helpKeyword: null,
file: match.Groups["FILENAME"].Value,
lineNumber: line,
columnNumber: column,
endLineNumber: 0,
endColumnNumber: 0,
message: match.Groups["TEXT"].Value);
}
},
// Example error with location
//../Protos/greet.proto(14) : error in column=10: "name" is already defined in "Greet.HelloRequest".
new ErrorListFilter
{
Pattern = new Regex(
pattern: "(?'FILENAME'.+)\\((?'LINE'\\d+)\\) ?: ?error in column=(?'COLUMN'\\d+) ?: ?(?'TEXT'.*)",
options: RegexOptions.Compiled | RegexOptions.IgnoreCase,
matchTimeout: s_regexTimeout),
LogAction = (log, match) =>
{
int.TryParse(match.Groups["LINE"].Value, out var line);
int.TryParse(match.Groups["COLUMN"].Value, out var column);
log.LogError(
subcategory: null,
errorCode: null,
helpKeyword: null,
file: match.Groups["FILENAME"].Value,
lineNumber: line,
columnNumber: column,
endLineNumber: 0,
endColumnNumber: 0,
message: match.Groups["TEXT"].Value);
}
},
// Example warning without location
//../Protos/greet.proto: warning: Import google/protobuf/empty.proto but not used.
new ErrorListFilter
{
Pattern = new Regex(
pattern: "(?'FILENAME'.+): ?warning: ?(?'TEXT'.*)",
options: RegexOptions.Compiled | RegexOptions.IgnoreCase,
matchTimeout: s_regexTimeout),
LogAction = (log, match) =>
{
log.LogWarning(
subcategory: null,
warningCode: null,
helpKeyword: null,
file: match.Groups["FILENAME"].Value,
lineNumber: 0,
columnNumber: 0,
endLineNumber: 0,
endColumnNumber: 0,
message: match.Groups["TEXT"].Value);
}
},
// Example error without location
//../Protos/greet.proto: Import "google/protobuf/empty.proto" was listed twice.
new ErrorListFilter
{
Pattern = new Regex(
pattern: "(?'FILENAME'.+): ?(?'TEXT'.*)",
options: RegexOptions.Compiled | RegexOptions.IgnoreCase,
matchTimeout: s_regexTimeout),
LogAction = (log, match) =>
{
log.LogError(
subcategory: null,
errorCode: null,
helpKeyword: null,
file: match.Groups["FILENAME"].Value,
lineNumber: 0,
columnNumber: 0,
endLineNumber: 0,
endColumnNumber: 0,
message: match.Groups["TEXT"].Value);
}
}
};
/// <summary> /// <summary>
/// Code generator. /// Code generator.
/// </summary> /// </summary>
@ -406,6 +513,22 @@ namespace Grpc.Tools
base.LogToolCommand(printer.ToString()); base.LogToolCommand(printer.ToString());
} }
protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance)
{
foreach (ErrorListFilter filter in s_errorListFilters)
{
Match match = filter.Pattern.Match(singleLine);
if (match.Success)
{
filter.LogAction(Log, match);
return;
}
}
base.LogEventsFromTextOutput(singleLine, messageImportance);
}
// Main task entry point. // Main task entry point.
public override bool Execute() public override bool Execute()
{ {
@ -438,5 +561,11 @@ namespace Grpc.Tools
return true; return true;
} }
class ErrorListFilter
{
public Regex Pattern { get; set; }
public Action<TaskLoggingHelper, Match> LogAction { get; set; }
}
}; };
} }

@ -271,7 +271,6 @@
GrpcPluginExe="%(_Protobuf_OutOfDateProto.GrpcPluginExe)" GrpcPluginExe="%(_Protobuf_OutOfDateProto.GrpcPluginExe)"
GrpcOutputDir="%(_Protobuf_OutOfDateProto.GrpcOutputDir)" GrpcOutputDir="%(_Protobuf_OutOfDateProto.GrpcOutputDir)"
GrpcOutputOptions="%(_Protobuf_OutOfDateProto._GrpcOutputOptions)" GrpcOutputOptions="%(_Protobuf_OutOfDateProto._GrpcOutputOptions)"
LogStandardErrorAsError="true"
> >
<Output TaskParameter="GeneratedFiles" ItemName="_Protobuf_GeneratedFiles"/> <Output TaskParameter="GeneratedFiles" ItemName="_Protobuf_GeneratedFiles"/>
</ProtoCompile> </ProtoCompile>

@ -3,7 +3,8 @@
{ {
"src": [ "src": [
{ {
"files": ["Grpc.Core/Grpc.Core.csproj", "files": ["Grpc.Core.Api/Grpc.Core.Api.csproj",
"Grpc.Core/Grpc.Core.csproj",
"Grpc.Auth/Grpc.Auth.csproj", "Grpc.Auth/Grpc.Auth.csproj",
"Grpc.Core.Testing/Grpc.Core.Testing.csproj", "Grpc.Core.Testing/Grpc.Core.Testing.csproj",
"Grpc.HealthCheck/Grpc.HealthCheck.csproj", "Grpc.HealthCheck/Grpc.HealthCheck.csproj",

@ -101,7 +101,7 @@ Pod::Spec.new do |s|
s.preserve_paths = plugin s.preserve_paths = plugin
# Restrict the protoc version to the one supported by this plugin. # Restrict the protoc version to the one supported by this plugin.
s.dependency '!ProtoCompiler', '3.6.0' s.dependency '!ProtoCompiler', '3.6.1'
# For the Protobuf dependency not to complain: # For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.0' s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9' s.osx.deployment_target = '10.9'

@ -36,7 +36,7 @@ Pod::Spec.new do |s|
# exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
# before them. # before them.
s.name = '!ProtoCompiler' s.name = '!ProtoCompiler'
v = '3.6.0' v = '3.6.1'
s.version = v s.version = v
s.summary = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files' s.summary = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files'
s.description = <<-DESC s.description = <<-DESC
@ -112,6 +112,7 @@ Pod::Spec.new do |s|
# For the Protobuf dependency not to complain: # For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.0' s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9' s.osx.deployment_target = '10.9'
s.tvos.deployment_target = '10.0'
# This is only for local development of protoc: If the Podfile brings this pod from a local # This is only for local development of protoc: If the Podfile brings this pod from a local
# directory using `:path`, CocoaPods won't download the zip file and so the compiler won't be # directory using `:path`, CocoaPods won't download the zip file and so the compiler won't be

@ -79,7 +79,7 @@ Pod::Spec.new do |s|
:commit => "b29b21a81b32ec273f118f589f46d56ad3332420", :commit => "b29b21a81b32ec273f118f589f46d56ad3332420",
} }
s.ios.deployment_target = '5.0' s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.7' s.osx.deployment_target = '10.7'
s.tvos.deployment_target = '10.0' s.tvos.deployment_target = '10.0'

@ -30,19 +30,20 @@ cdef grpc_event _next(grpc_completion_queue *c_completion_queue, deadline):
else: else:
c_deadline = _timespec_from_time(deadline) c_deadline = _timespec_from_time(deadline)
with nogil: while True:
while True: with nogil:
c_timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c_increment) c_timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c_increment)
if gpr_time_cmp(c_timeout, c_deadline) > 0: if gpr_time_cmp(c_timeout, c_deadline) > 0:
c_timeout = c_deadline c_timeout = c_deadline
c_event = grpc_completion_queue_next(c_completion_queue, c_timeout, NULL) c_event = grpc_completion_queue_next(c_completion_queue, c_timeout, NULL)
if (c_event.type != GRPC_QUEUE_TIMEOUT or if (c_event.type != GRPC_QUEUE_TIMEOUT or
gpr_time_cmp(c_timeout, c_deadline) == 0): gpr_time_cmp(c_timeout, c_deadline) == 0):
break break
# Handle any signals # Handle any signals
with gil: cpython.PyErr_CheckSignals()
cpython.PyErr_CheckSignals()
return c_event return c_event

@ -17,8 +17,6 @@ cimport cpython
import grpc import grpc
import threading import threading
from libc.stdint cimport uintptr_t
def _spawn_callback_in_thread(cb_func, args): def _spawn_callback_in_thread(cb_func, args):
ForkManagedThread(target=cb_func, args=args).start() ForkManagedThread(target=cb_func, args=args).start()

@ -13,7 +13,17 @@
# limitations under the License. # limitations under the License.
cimport libc.time cimport libc.time
from libc.stdint cimport intptr_t, uint8_t, int32_t, uint32_t, int64_t
ctypedef ssize_t intptr_t
ctypedef size_t uintptr_t
ctypedef signed char int8_t
ctypedef signed short int16_t
ctypedef signed int int32_t
ctypedef signed long long int64_t
ctypedef unsigned char uint8_t
ctypedef unsigned short uint16_t
ctypedef unsigned int uint32_t
ctypedef unsigned long long uint64_t
cdef extern from "grpc/support/alloc.h": cdef extern from "grpc/support/alloc.h":

@ -13,8 +13,6 @@
# limitations under the License. # limitations under the License.
# distutils: language=c++ # distutils: language=c++
from libc.stdint cimport uint32_t
cdef extern from "grpc/impl/codegen/slice.h": cdef extern from "grpc/impl/codegen/slice.h":
struct grpc_slice_buffer: struct grpc_slice_buffer:
int count int count

@ -12,8 +12,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from libc.stdint cimport intptr_t
cdef bytes _slice_bytes(grpc_slice slice): cdef bytes _slice_bytes(grpc_slice slice):
cdef void *start = grpc_slice_start_ptr(slice) cdef void *start = grpc_slice_start_ptr(slice)

@ -200,7 +200,6 @@ CORE_SOURCE_FILES = [
'src/core/lib/transport/metadata.cc', 'src/core/lib/transport/metadata.cc',
'src/core/lib/transport/metadata_batch.cc', 'src/core/lib/transport/metadata_batch.cc',
'src/core/lib/transport/pid_controller.cc', 'src/core/lib/transport/pid_controller.cc',
'src/core/lib/transport/service_config.cc',
'src/core/lib/transport/static_metadata.cc', 'src/core/lib/transport/static_metadata.cc',
'src/core/lib/transport/status_conversion.cc', 'src/core/lib/transport/status_conversion.cc',
'src/core/lib/transport/status_metadata.cc', 'src/core/lib/transport/status_metadata.cc',
@ -336,6 +335,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/client_channel/resolving_lb_policy.cc', 'src/core/ext/filters/client_channel/resolving_lb_policy.cc',
'src/core/ext/filters/client_channel/retry_throttle.cc', 'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc', 'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/service_config.cc',
'src/core/ext/filters/client_channel/subchannel.cc', 'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc', 'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/deadline/deadline_filter.cc', 'src/core/ext/filters/deadline/deadline_filter.cc',
@ -699,6 +699,7 @@ CORE_SOURCE_FILES = [
'third_party/cares/cares/ares_strcasecmp.c', 'third_party/cares/cares/ares_strcasecmp.c',
'third_party/cares/cares/ares_strdup.c', 'third_party/cares/cares/ares_strdup.c',
'third_party/cares/cares/ares_strerror.c', 'third_party/cares/cares/ares_strerror.c',
'third_party/cares/cares/ares_strsplit.c',
'third_party/cares/cares/ares_timeout.c', 'third_party/cares/cares/ares_timeout.c',
'third_party/cares/cares/ares_version.c', 'third_party/cares/cares/ares_version.c',
'third_party/cares/cares/ares_writev.c', 'third_party/cares/cares/ares_writev.c',

@ -135,7 +135,8 @@ class TestGevent(setuptools.Command):
# This test will stuck while running higher version of gevent # This test will stuck while running higher version of gevent
'unit._auth_context_test.AuthContextTest.testSessionResumption', 'unit._auth_context_test.AuthContextTest.testSessionResumption',
# TODO(https://github.com/grpc/grpc/issues/15411) enable these tests # TODO(https://github.com/grpc/grpc/issues/15411) enable these tests
'unit._metadata_flags_test', 'unit._channel_ready_future_test.ChannelReadyFutureTest.test_immediately_connectable_channel_connectivity',
"unit._cython._channel_test.ChannelTest.test_single_channel_lonely_connectivity",
'unit._exit_test.ExitTest.test_in_flight_unary_unary_call', 'unit._exit_test.ExitTest.test_in_flight_unary_unary_call',
'unit._exit_test.ExitTest.test_in_flight_unary_stream_call', 'unit._exit_test.ExitTest.test_in_flight_unary_stream_call',
'unit._exit_test.ExitTest.test_in_flight_stream_unary_call', 'unit._exit_test.ExitTest.test_in_flight_stream_unary_call',
@ -143,6 +144,7 @@ class TestGevent(setuptools.Command):
'unit._exit_test.ExitTest.test_in_flight_partial_unary_stream_call', 'unit._exit_test.ExitTest.test_in_flight_partial_unary_stream_call',
'unit._exit_test.ExitTest.test_in_flight_partial_stream_unary_call', 'unit._exit_test.ExitTest.test_in_flight_partial_stream_unary_call',
'unit._exit_test.ExitTest.test_in_flight_partial_stream_stream_call', 'unit._exit_test.ExitTest.test_in_flight_partial_stream_stream_call',
'unit._metadata_flags_test',
'health_check._health_servicer_test.HealthServicerTest.test_cancelled_watch_removed_from_watch_list', 'health_check._health_servicer_test.HealthServicerTest.test_cancelled_watch_removed_from_watch_list',
# TODO(https://github.com/grpc/grpc/issues/17330) enable these three tests # TODO(https://github.com/grpc/grpc/issues/17330) enable these three tests
'channelz._channelz_servicer_test.ChannelzServicerTest.test_many_subchannels', 'channelz._channelz_servicer_test.ChannelzServicerTest.test_many_subchannels',

@ -61,6 +61,8 @@
def grpc_test_util_files(libs): def grpc_test_util_files(libs):
out = grpc_lib_files(libs, ("grpc_test_util",), ("src", "headers")) out = grpc_lib_files(libs, ("grpc_test_util",), ("src", "headers"))
excl = grpc_private_files(libs) excl = grpc_private_files(libs)
# Subprocess is not supported in tvOS and not needed by our tests.
excl += ["test/core/util/subprocess_posix.cc"]
return [file for file in out if not file in excl] return [file for file in out if not file in excl]
def end2end_tests_files(libs): def end2end_tests_files(libs):

@ -103,7 +103,7 @@
s.preserve_paths = plugin s.preserve_paths = plugin
# Restrict the protoc version to the one supported by this plugin. # Restrict the protoc version to the one supported by this plugin.
s.dependency '!ProtoCompiler', '3.6.0' s.dependency '!ProtoCompiler', '3.6.1'
# For the Protobuf dependency not to complain: # For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.0' s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9' s.osx.deployment_target = '10.9'

@ -84,7 +84,7 @@
:commit => "b29b21a81b32ec273f118f589f46d56ad3332420", :commit => "b29b21a81b32ec273f118f589f46d56ad3332420",
} }
s.ios.deployment_target = '5.0' s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.7' s.osx.deployment_target = '10.7'
s.tvos.deployment_target = '10.0' s.tvos.deployment_target = '10.0'

@ -109,26 +109,23 @@ static grpc_core::OrphanablePtr<grpc_core::Resolver> create_resolver(
class ResultHandler : public grpc_core::Resolver::ResultHandler { class ResultHandler : public grpc_core::Resolver::ResultHandler {
public: public:
struct ResolverOutput { struct ResolverOutput {
const grpc_channel_args* result = nullptr; grpc_core::Resolver::Result result;
grpc_error* error = nullptr; grpc_error* error = nullptr;
gpr_event ev; gpr_event ev;
ResolverOutput() { gpr_event_init(&ev); } ResolverOutput() { gpr_event_init(&ev); }
~ResolverOutput() { ~ResolverOutput() { GRPC_ERROR_UNREF(error); }
grpc_channel_args_destroy(result);
GRPC_ERROR_UNREF(error);
}
}; };
void SetOutput(ResolverOutput* output) { void SetOutput(ResolverOutput* output) {
gpr_atm_rel_store(&output_, reinterpret_cast<gpr_atm>(output)); gpr_atm_rel_store(&output_, reinterpret_cast<gpr_atm>(output));
} }
void ReturnResult(const grpc_channel_args* args) override { void ReturnResult(grpc_core::Resolver::Result result) override {
ResolverOutput* output = ResolverOutput* output =
reinterpret_cast<ResolverOutput*>(gpr_atm_acq_load(&output_)); reinterpret_cast<ResolverOutput*>(gpr_atm_acq_load(&output_));
GPR_ASSERT(output != nullptr); GPR_ASSERT(output != nullptr);
output->result = args; output->result = std::move(result);
output->error = GRPC_ERROR_NONE; output->error = GRPC_ERROR_NONE;
gpr_event_set(&output->ev, (void*)1); gpr_event_set(&output->ev, (void*)1);
} }
@ -137,7 +134,6 @@ class ResultHandler : public grpc_core::Resolver::ResultHandler {
ResolverOutput* output = ResolverOutput* output =
reinterpret_cast<ResolverOutput*>(gpr_atm_acq_load(&output_)); reinterpret_cast<ResolverOutput*>(gpr_atm_acq_load(&output_));
GPR_ASSERT(output != nullptr); GPR_ASSERT(output != nullptr);
output->result = nullptr;
output->error = error; output->error = error;
gpr_event_set(&output->ev, (void*)1); gpr_event_set(&output->ev, (void*)1);
} }
@ -180,14 +176,14 @@ int main(int argc, char** argv) {
resolver->StartLocked(); resolver->StartLocked();
grpc_core::ExecCtx::Get()->Flush(); grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(wait_loop(5, &output1.ev)); GPR_ASSERT(wait_loop(5, &output1.ev));
GPR_ASSERT(output1.result == nullptr); GPR_ASSERT(output1.result.addresses.empty());
GPR_ASSERT(output1.error != GRPC_ERROR_NONE); GPR_ASSERT(output1.error != GRPC_ERROR_NONE);
ResultHandler::ResolverOutput output2; ResultHandler::ResolverOutput output2;
result_handler->SetOutput(&output2); result_handler->SetOutput(&output2);
grpc_core::ExecCtx::Get()->Flush(); grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(wait_loop(30, &output2.ev)); GPR_ASSERT(wait_loop(30, &output2.ev));
GPR_ASSERT(output2.result != nullptr); GPR_ASSERT(!output2.result.addresses.empty());
GPR_ASSERT(output2.error == GRPC_ERROR_NONE); GPR_ASSERT(output2.error == GRPC_ERROR_NONE);
GRPC_COMBINER_UNREF(g_combiner, "test"); GRPC_COMBINER_UNREF(g_combiner, "test");

@ -174,8 +174,7 @@ struct OnResolutionCallbackArg;
class ResultHandler : public grpc_core::Resolver::ResultHandler { class ResultHandler : public grpc_core::Resolver::ResultHandler {
public: public:
using ResultCallback = void (*)(const grpc_channel_args* result, using ResultCallback = void (*)(OnResolutionCallbackArg* state);
OnResolutionCallbackArg* state);
void SetCallback(ResultCallback result_cb, OnResolutionCallbackArg* state) { void SetCallback(ResultCallback result_cb, OnResolutionCallbackArg* state) {
GPR_ASSERT(result_cb_ == nullptr); GPR_ASSERT(result_cb_ == nullptr);
@ -184,14 +183,14 @@ class ResultHandler : public grpc_core::Resolver::ResultHandler {
state_ = state; state_ = state;
} }
void ReturnResult(const grpc_channel_args* args) override { void ReturnResult(grpc_core::Resolver::Result result) override {
GPR_ASSERT(result_cb_ != nullptr); GPR_ASSERT(result_cb_ != nullptr);
GPR_ASSERT(state_ != nullptr); GPR_ASSERT(state_ != nullptr);
ResultCallback cb = result_cb_; ResultCallback cb = result_cb_;
OnResolutionCallbackArg* state = state_; OnResolutionCallbackArg* state = state_;
result_cb_ = nullptr; result_cb_ = nullptr;
state_ = nullptr; state_ = nullptr;
cb(args, state); cb(state);
} }
void ReturnError(grpc_error* error) override { void ReturnError(grpc_error* error) override {
@ -213,9 +212,7 @@ struct OnResolutionCallbackArg {
// Set to true by the last callback in the resolution chain. // Set to true by the last callback in the resolution chain.
static bool g_all_callbacks_invoked; static bool g_all_callbacks_invoked;
static void on_second_resolution(const grpc_channel_args* result, static void on_second_resolution(OnResolutionCallbackArg* cb_arg) {
OnResolutionCallbackArg* cb_arg) {
grpc_channel_args_destroy(result);
gpr_log(GPR_INFO, "2nd: g_resolution_count: %d", g_resolution_count); gpr_log(GPR_INFO, "2nd: g_resolution_count: %d", g_resolution_count);
// The resolution callback was not invoked until new data was // The resolution callback was not invoked until new data was
// available, which was delayed until after the cooldown period. // available, which was delayed until after the cooldown period.
@ -230,9 +227,7 @@ static void on_second_resolution(const grpc_channel_args* result,
g_all_callbacks_invoked = true; g_all_callbacks_invoked = true;
} }
static void on_first_resolution(const grpc_channel_args* result, static void on_first_resolution(OnResolutionCallbackArg* cb_arg) {
OnResolutionCallbackArg* cb_arg) {
grpc_channel_args_destroy(result);
gpr_log(GPR_INFO, "1st: g_resolution_count: %d", g_resolution_count); gpr_log(GPR_INFO, "1st: g_resolution_count: %d", g_resolution_count);
// There's one initial system-level resolution and one invocation of a // There's one initial system-level resolution and one invocation of a
// notification callback (the current function). // notification callback (the current function).

@ -35,32 +35,22 @@
class ResultHandler : public grpc_core::Resolver::ResultHandler { class ResultHandler : public grpc_core::Resolver::ResultHandler {
public: public:
~ResultHandler() override { grpc_channel_args_destroy(expected_); } void SetExpectedAndEvent(grpc_core::Resolver::Result expected,
gpr_event* ev) {
void SetExpectedAndEvent(grpc_channel_args* expected, gpr_event* ev) {
GPR_ASSERT(expected_ == nullptr);
GPR_ASSERT(ev_ == nullptr); GPR_ASSERT(ev_ == nullptr);
expected_ = grpc_channel_args_copy(expected); expected_ = std::move(expected);
ev_ = ev; ev_ = ev;
} }
void ReturnResult(const grpc_channel_args* args) override { void ReturnResult(grpc_core::Resolver::Result actual) override {
GPR_ASSERT(expected_ != nullptr);
GPR_ASSERT(ev_ != nullptr); GPR_ASSERT(ev_ != nullptr);
// We only check the addresses channel arg because that's the only one // We only check the addresses, because that's the only thing
// explicitly set by the test via // explicitly set by the test via
// FakeResolverResponseGenerator::SetResponse(). // FakeResolverResponseGenerator::SetResponse().
const grpc_core::ServerAddressList* actual_addresses = GPR_ASSERT(actual.addresses.size() == expected_.addresses.size());
grpc_core::FindServerAddressListChannelArg(args); for (size_t i = 0; i < expected_.addresses.size(); ++i) {
const grpc_core::ServerAddressList* expected_addresses = GPR_ASSERT(actual.addresses[i] == expected_.addresses[i]);
grpc_core::FindServerAddressListChannelArg(expected_);
GPR_ASSERT(actual_addresses->size() == expected_addresses->size());
for (size_t i = 0; i < expected_addresses->size(); ++i) {
GPR_ASSERT((*actual_addresses)[i] == (*expected_addresses)[i]);
} }
grpc_channel_args_destroy(args);
grpc_channel_args_destroy(expected_);
expected_ = nullptr;
gpr_event_set(ev_, (void*)1); gpr_event_set(ev_, (void*)1);
ev_ = nullptr; ev_ = nullptr;
} }
@ -68,7 +58,7 @@ class ResultHandler : public grpc_core::Resolver::ResultHandler {
void ReturnError(grpc_error* error) override {} void ReturnError(grpc_error* error) override {}
private: private:
grpc_channel_args* expected_ = nullptr; grpc_core::Resolver::Result expected_;
gpr_event* ev_ = nullptr; gpr_event* ev_ = nullptr;
}; };
@ -92,13 +82,13 @@ static grpc_core::OrphanablePtr<grpc_core::Resolver> build_fake_resolver(
} }
// Create a new resolution containing 2 addresses. // Create a new resolution containing 2 addresses.
static grpc_channel_args* create_new_resolver_result() { static grpc_core::Resolver::Result create_new_resolver_result() {
static size_t test_counter = 0; static size_t test_counter = 0;
const size_t num_addresses = 2; const size_t num_addresses = 2;
char* uri_string; char* uri_string;
char* balancer_name; char* balancer_name;
// Create address list. // Create address list.
grpc_core::ServerAddressList addresses; grpc_core::Resolver::Result result;
for (size_t i = 0; i < num_addresses; ++i) { for (size_t i = 0; i < num_addresses; ++i) {
gpr_asprintf(&uri_string, "ipv4:127.0.0.1:100%" PRIuPTR, gpr_asprintf(&uri_string, "ipv4:127.0.0.1:100%" PRIuPTR,
test_counter * num_addresses + i); test_counter * num_addresses + i);
@ -117,17 +107,13 @@ static grpc_channel_args* create_new_resolver_result() {
} }
grpc_channel_args* args = grpc_channel_args_copy_and_add( grpc_channel_args* args = grpc_channel_args_copy_and_add(
nullptr, args_to_add.data(), args_to_add.size()); nullptr, args_to_add.data(), args_to_add.size());
addresses.emplace_back(address.addr, address.len, args); result.addresses.emplace_back(address.addr, address.len, args);
gpr_free(balancer_name); gpr_free(balancer_name);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
gpr_free(uri_string); gpr_free(uri_string);
} }
// Embed the address list in channel args.
const grpc_arg addresses_arg = CreateServerAddressListChannelArg(&addresses);
grpc_channel_args* results =
grpc_channel_args_copy_and_add(nullptr, &addresses_arg, 1);
++test_counter; ++test_counter;
return results; return result;
} }
static void test_fake_resolver() { static void test_fake_resolver() {
@ -147,39 +133,38 @@ static void test_fake_resolver() {
// next_results != NULL, reresolution_results == NULL. // next_results != NULL, reresolution_results == NULL.
// Expected response is next_results. // Expected response is next_results.
gpr_log(GPR_INFO, "TEST 1"); gpr_log(GPR_INFO, "TEST 1");
grpc_channel_args* results = create_new_resolver_result(); grpc_core::Resolver::Result result = create_new_resolver_result();
gpr_event ev1; gpr_event ev1;
gpr_event_init(&ev1); gpr_event_init(&ev1);
result_handler->SetExpectedAndEvent(results, &ev1); result_handler->SetExpectedAndEvent(result, &ev1);
response_generator->SetResponse(results); response_generator->SetResponse(std::move(result));
grpc_core::ExecCtx::Get()->Flush(); grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(gpr_event_wait(&ev1, grpc_timeout_seconds_to_deadline(5)) != GPR_ASSERT(gpr_event_wait(&ev1, grpc_timeout_seconds_to_deadline(5)) !=
nullptr); nullptr);
grpc_channel_args_destroy(results);
// Test 2: update resolution. // Test 2: update resolution.
// next_results != NULL, reresolution_results == NULL. // next_results != NULL, reresolution_results == NULL.
// Expected response is next_results. // Expected response is next_results.
gpr_log(GPR_INFO, "TEST 2"); gpr_log(GPR_INFO, "TEST 2");
results = create_new_resolver_result(); result = create_new_resolver_result();
gpr_event ev2; gpr_event ev2;
gpr_event_init(&ev2); gpr_event_init(&ev2);
result_handler->SetExpectedAndEvent(results, &ev2); result_handler->SetExpectedAndEvent(result, &ev2);
response_generator->SetResponse(results); response_generator->SetResponse(std::move(result));
grpc_core::ExecCtx::Get()->Flush(); grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(gpr_event_wait(&ev2, grpc_timeout_seconds_to_deadline(5)) != GPR_ASSERT(gpr_event_wait(&ev2, grpc_timeout_seconds_to_deadline(5)) !=
nullptr); nullptr);
grpc_channel_args_destroy(results);
// Test 3: normal re-resolution. // Test 3: normal re-resolution.
// next_results == NULL, reresolution_results != NULL. // next_results == NULL, reresolution_results != NULL.
// Expected response is reresolution_results. // Expected response is reresolution_results.
gpr_log(GPR_INFO, "TEST 3"); gpr_log(GPR_INFO, "TEST 3");
grpc_channel_args* reresolution_results = create_new_resolver_result(); grpc_core::Resolver::Result reresolution_result =
create_new_resolver_result();
gpr_event ev3; gpr_event ev3;
gpr_event_init(&ev3); gpr_event_init(&ev3);
result_handler->SetExpectedAndEvent(reresolution_results, &ev3); result_handler->SetExpectedAndEvent(reresolution_result, &ev3);
// Set reresolution_results. // Set reresolution_results.
// No result will be returned until re-resolution is requested. // No result will be returned until re-resolution is requested.
response_generator->SetReresolutionResponse(reresolution_results); response_generator->SetReresolutionResponse(reresolution_result);
grpc_core::ExecCtx::Get()->Flush(); grpc_core::ExecCtx::Get()->Flush();
// Trigger a re-resolution. // Trigger a re-resolution.
resolver->RequestReresolutionLocked(); resolver->RequestReresolutionLocked();
@ -192,33 +177,31 @@ static void test_fake_resolver() {
gpr_log(GPR_INFO, "TEST 4"); gpr_log(GPR_INFO, "TEST 4");
gpr_event ev4; gpr_event ev4;
gpr_event_init(&ev4); gpr_event_init(&ev4);
result_handler->SetExpectedAndEvent(reresolution_results, &ev4); result_handler->SetExpectedAndEvent(std::move(reresolution_result), &ev4);
// Trigger a re-resolution. // Trigger a re-resolution.
resolver->RequestReresolutionLocked(); resolver->RequestReresolutionLocked();
grpc_core::ExecCtx::Get()->Flush(); grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(gpr_event_wait(&ev4, grpc_timeout_seconds_to_deadline(5)) != GPR_ASSERT(gpr_event_wait(&ev4, grpc_timeout_seconds_to_deadline(5)) !=
nullptr); nullptr);
grpc_channel_args_destroy(reresolution_results);
// Test 5: normal resolution. // Test 5: normal resolution.
// next_results != NULL, reresolution_results != NULL. // next_results != NULL, reresolution_results != NULL.
// Expected response is next_results. // Expected response is next_results.
gpr_log(GPR_INFO, "TEST 5"); gpr_log(GPR_INFO, "TEST 5");
results = create_new_resolver_result(); result = create_new_resolver_result();
gpr_event ev5; gpr_event ev5;
gpr_event_init(&ev5); gpr_event_init(&ev5);
result_handler->SetExpectedAndEvent(results, &ev5); result_handler->SetExpectedAndEvent(result, &ev5);
response_generator->SetResponse(results); response_generator->SetResponse(std::move(result));
grpc_core::ExecCtx::Get()->Flush(); grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(gpr_event_wait(&ev5, grpc_timeout_seconds_to_deadline(5)) != GPR_ASSERT(gpr_event_wait(&ev5, grpc_timeout_seconds_to_deadline(5)) !=
nullptr); nullptr);
grpc_channel_args_destroy(results);
// Test 6: no-op. // Test 6: no-op.
// Requesting a new resolution without setting the response shouldn't trigger // Requesting a new resolution without setting the response shouldn't trigger
// the resolution callback. // the resolution callback.
gpr_log(GPR_INFO, "TEST 6"); gpr_log(GPR_INFO, "TEST 6");
gpr_event ev6; gpr_event ev6;
gpr_event_init(&ev6); gpr_event_init(&ev6);
result_handler->SetExpectedAndEvent(nullptr, &ev6); result_handler->SetExpectedAndEvent(grpc_core::Resolver::Result(), &ev6);
GPR_ASSERT(gpr_event_wait(&ev6, grpc_timeout_milliseconds_to_deadline(100)) == GPR_ASSERT(gpr_event_wait(&ev6, grpc_timeout_milliseconds_to_deadline(100)) ==
nullptr); nullptr);
// Clean up. // Clean up.

@ -32,9 +32,7 @@ static grpc_combiner* g_combiner;
class ResultHandler : public grpc_core::Resolver::ResultHandler { class ResultHandler : public grpc_core::Resolver::ResultHandler {
public: public:
void ReturnResult(const grpc_channel_args* args) override { void ReturnResult(grpc_core::Resolver::Result result) override {}
grpc_channel_args_destroy(args);
}
void ReturnError(grpc_error* error) override { GRPC_ERROR_UNREF(error); } void ReturnError(grpc_error* error) override { GRPC_ERROR_UNREF(error); }
}; };

@ -28,7 +28,6 @@
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/service_config.h"
#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/cq_verifier.h"
#include "test/core/util/port.h" #include "test/core/util/port.h"

@ -30,7 +30,6 @@
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/service_config.h"
#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/tests/cancel_test_helpers.h" #include "test/core/end2end/tests/cancel_test_helpers.h"

@ -30,7 +30,6 @@
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/service_config.h"
#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/tests/cancel_test_helpers.h" #include "test/core/end2end/tests/cancel_test_helpers.h"

@ -30,7 +30,6 @@
#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/service_config.h"
#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/cq_verifier.h"

@ -64,9 +64,8 @@ class ForwardingLoadBalancingPolicy : public LoadBalancingPolicy {
~ForwardingLoadBalancingPolicy() override = default; ~ForwardingLoadBalancingPolicy() override = default;
void UpdateLocked(const grpc_channel_args& args, void UpdateLocked(UpdateArgs args) override {
RefCountedPtr<Config> lb_config) override { delegate_->UpdateLocked(std::move(args));
delegate_->UpdateLocked(args, std::move(lb_config));
} }
void ExitIdleLocked() override { delegate_->ExitIdleLocked(); } void ExitIdleLocked() override { delegate_->ExitIdleLocked(); }

@ -218,7 +218,7 @@ class ClientChannelStressTest {
void SetNextResolution(const std::vector<AddressData>& address_data) { void SetNextResolution(const std::vector<AddressData>& address_data) {
grpc_core::ExecCtx exec_ctx; grpc_core::ExecCtx exec_ctx;
grpc_core::ServerAddressList addresses; grpc_core::Resolver::Result result;
for (const auto& addr : address_data) { for (const auto& addr : address_data) {
char* lb_uri_str; char* lb_uri_str;
gpr_asprintf(&lb_uri_str, "ipv4:127.0.0.1:%d", addr.port); gpr_asprintf(&lb_uri_str, "ipv4:127.0.0.1:%d", addr.port);
@ -236,13 +236,11 @@ class ClientChannelStressTest {
} }
grpc_channel_args* args = grpc_channel_args_copy_and_add( grpc_channel_args* args = grpc_channel_args_copy_and_add(
nullptr, args_to_add.data(), args_to_add.size()); nullptr, args_to_add.data(), args_to_add.size());
addresses.emplace_back(address.addr, address.len, args); result.addresses.emplace_back(address.addr, address.len, args);
grpc_uri_destroy(lb_uri); grpc_uri_destroy(lb_uri);
gpr_free(lb_uri_str); gpr_free(lb_uri_str);
} }
grpc_arg fake_addresses = CreateServerAddressListChannelArg(&addresses); response_generator_->SetResponse(std::move(result));
grpc_channel_args fake_result = {1, &fake_addresses};
response_generator_->SetResponse(&fake_result);
} }
void KeepSendingRequests() { void KeepSendingRequests() {

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

Loading…
Cancel
Save