Merge branch 'master' of https://github.com/grpc/grpc into channel

pull/17797/head
Nicolas "Pixel" Noble 6 years ago
commit dffbe4a1eb
  1. 100
      .pylintrc-examples
  2. 26
      BUILD
  3. 74
      CMakeLists.txt
  4. 82
      Makefile
  5. 26
      build.yaml
  6. 5
      config.m4
  7. 5
      config.w32
  8. 3
      examples/BUILD
  9. 134
      examples/cpp/keyvaluestore/caching_interceptor.h
  10. 19
      examples/cpp/keyvaluestore/client.cc
  11. 2
      examples/python/helloworld/greeter_client_with_options.py
  12. 8
      gRPC-C++.podspec
  13. 20
      gRPC-Core.podspec
  14. 15
      grpc.gemspec
  15. 24
      grpc.gyp
  16. 8
      include/grpc/impl/codegen/grpc_types.h
  17. 11
      package.xml
  18. 15
      src/compiler/objective_c_generator.cc
  19. 29
      src/core/ext/filters/client_channel/client_channel.cc
  20. 6
      src/core/ext/filters/client_channel/client_channel_plugin.cc
  21. 177
      src/core/ext/filters/client_channel/global_subchannel_pool.cc
  22. 68
      src/core/ext/filters/client_channel/global_subchannel_pool.h
  23. 4
      src/core/ext/filters/client_channel/lb_policy.cc
  24. 26
      src/core/ext/filters/client_channel/lb_policy.h
  25. 53
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  26. 11
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
  27. 11
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
  28. 5
      src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
  29. 22
      src/core/ext/filters/client_channel/lb_policy/xds/xds.cc
  30. 7
      src/core/ext/filters/client_channel/lb_policy_factory.h
  31. 4
      src/core/ext/filters/client_channel/lb_policy_registry.cc
  32. 2
      src/core/ext/filters/client_channel/lb_policy_registry.h
  33. 96
      src/core/ext/filters/client_channel/local_subchannel_pool.cc
  34. 56
      src/core/ext/filters/client_channel/local_subchannel_pool.h
  35. 16
      src/core/ext/filters/client_channel/request_routing.cc
  36. 6
      src/core/ext/filters/client_channel/request_routing.h
  37. 17
      src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
  38. 44
      src/core/ext/filters/client_channel/subchannel.cc
  39. 6
      src/core/ext/filters/client_channel/subchannel.h
  40. 8
      src/core/ext/filters/client_channel/subchannel_index.cc
  41. 9
      src/core/ext/filters/client_channel/subchannel_index.h
  42. 97
      src/core/ext/filters/client_channel/subchannel_pool_interface.cc
  43. 94
      src/core/ext/filters/client_channel/subchannel_pool_interface.h
  44. 7
      src/core/ext/filters/http/client_authority_filter.cc
  45. 1
      src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc
  46. 6
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  47. 3
      src/core/lib/gpr/log_posix.cc
  48. 47
      src/core/lib/gprpp/optional.h
  49. 206
      src/core/lib/iomgr/buffer_list.cc
  50. 74
      src/core/lib/iomgr/buffer_list.h
  51. 7
      src/core/lib/iomgr/combiner.cc
  52. 2
      src/core/lib/iomgr/error.cc
  53. 201
      src/core/lib/iomgr/executor.cc
  54. 101
      src/core/lib/iomgr/executor.h
  55. 6
      src/core/lib/iomgr/fork_posix.cc
  56. 108
      src/core/lib/iomgr/internal_errqueue.h
  57. 7
      src/core/lib/iomgr/iomgr.cc
  58. 2
      src/core/lib/iomgr/iomgr_custom.cc
  59. 36
      src/core/lib/iomgr/network_status_tracker.cc
  60. 7
      src/core/lib/iomgr/resolve_address_posix.cc
  61. 3
      src/core/lib/iomgr/resolve_address_windows.cc
  62. 4
      src/core/lib/iomgr/tcp_custom.cc
  63. 44
      src/core/lib/iomgr/tcp_posix.cc
  64. 1
      src/core/lib/iomgr/tcp_uv.cc
  65. 4
      src/core/lib/iomgr/tcp_windows.cc
  66. 10
      src/core/lib/iomgr/udp_server.cc
  67. 4
      src/core/lib/security/credentials/composite/composite_credentials.h
  68. 8
      src/core/lib/security/credentials/credentials.h
  69. 13
      src/core/lib/security/credentials/google_default/google_default_credentials.cc
  70. 2
      src/core/lib/security/credentials/google_default/google_default_credentials.h
  71. 2
      src/core/lib/surface/init.cc
  72. 5
      src/core/lib/surface/server.cc
  73. 1
      src/core/lib/transport/service_config.h
  74. 2
      src/core/lib/transport/transport.cc
  75. 1
      src/cpp/client/client_context.cc
  76. 67
      src/csharp/Grpc.Core.Testing/TestServerCallContext.cs
  77. 110
      src/csharp/Grpc.Core/Internal/DefaultServerCallContext.cs
  78. 38
      src/csharp/Grpc.Core/Internal/IServerResponseStream.cs
  79. 10
      src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
  80. 2
      src/csharp/Grpc.Core/Internal/ServerResponseStream.cs
  81. 183
      src/csharp/Grpc.Core/ServerCallContext.cs
  82. 11
      src/objective-c/GRPCClient/GRPCCall.m
  83. 4
      src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm
  84. 11
      src/python/grpcio/grpc/_channel.py
  85. 14
      src/python/grpcio/grpc/_server.py
  86. 16
      src/python/grpcio/grpc/_utilities.py
  87. 5
      src/python/grpcio/grpc_core_dependencies.py
  88. 1
      src/python/grpcio_channelz/LICENSE
  89. 3
      src/python/grpcio_channelz/channelz_commands.py
  90. 1
      src/python/grpcio_health_checking/LICENSE
  91. 3
      src/python/grpcio_health_checking/health_commands.py
  92. 1
      src/python/grpcio_reflection/LICENSE
  93. 3
      src/python/grpcio_reflection/reflection_commands.py
  94. 1
      src/python/grpcio_status/LICENSE
  95. 19
      src/python/grpcio_status/setup.py
  96. 39
      src/python/grpcio_status/status_commands.py
  97. 1
      src/python/grpcio_testing/LICENSE
  98. 16
      src/python/grpcio_testing/setup.py
  99. 39
      src/python/grpcio_testing/testing_commands.py
  100. 4
      templates/grpc.gemspec.template
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,100 @@
[MASTER]
ignore=
src/python/grpcio/grpc/beta,
src/python/grpcio/grpc/framework,
src/python/grpcio/grpc/framework/common,
src/python/grpcio/grpc/framework/foundation,
src/python/grpcio/grpc/framework/interfaces,
[VARIABLES]
# TODO(https://github.com/PyCQA/pylint/issues/1345): How does the inspection
# not include "unused_" and "ignored_" by default?
dummy-variables-rgx=^ignored_|^unused_
[DESIGN]
# NOTE(nathaniel): Not particularly attached to this value; it just seems to
# be what works for us at the moment (excepting the dead-code-walking Beta
# API).
max-args=6
[MISCELLANEOUS]
# NOTE(nathaniel): We are big fans of "TODO(<issue link>): " and
# "NOTE(<username or issue link>): ". We do not allow "TODO:",
# "TODO(<username>):", "FIXME:", or anything else.
notes=FIXME,XXX
[MESSAGES CONTROL]
disable=
# -- START OF EXAMPLE-SPECIFIC SUPPRESSIONS --
no-self-use,
unused-argument,
unused-variable,
# -- END OF EXAMPLE-SPECIFIC SUPPRESSIONS --
# TODO(https://github.com/PyCQA/pylint/issues/59#issuecomment-283774279):
# Enable cyclic-import after a 1.7-or-later pylint release that
# recognizes our disable=cyclic-import suppressions.
cyclic-import,
# TODO(https://github.com/grpc/grpc/issues/8622): Enable this after the
# Beta API is removed.
duplicate-code,
# TODO(https://github.com/grpc/grpc/issues/261): Doesn't seem to
# understand enum and concurrent.futures; look into this later with the
# latest pylint version.
import-error,
# TODO(https://github.com/grpc/grpc/issues/261): Enable this one.
# Should take a little configuration but not much.
invalid-name,
# TODO(https://github.com/grpc/grpc/issues/261): This doesn't seem to
# work for now? Try with a later pylint?
locally-disabled,
# NOTE(nathaniel): What even is this? *Enabling* an inspection results
# in a warning? How does that encourage more analysis and coverage?
locally-enabled,
# NOTE(nathaniel): We don't write doc strings for most private code
# elements.
missing-docstring,
# NOTE(nathaniel): In numeric comparisons it is better to have the
# lesser (or lesser-or-equal-to) quantity on the left when the
# expression is true than it is to worry about which is an identifier
# and which a literal value.
misplaced-comparison-constant,
# NOTE(nathaniel): Our completely abstract interface classes don't have
# constructors.
no-init,
# TODO(https://github.com/grpc/grpc/issues/261): Doesn't yet play
# nicely with some of our code being implemented in Cython. Maybe in a
# later version?
no-name-in-module,
# TODO(https://github.com/grpc/grpc/issues/261): Suppress these where
# the odd shape of the authentication portion of the API forces them on
# us and enable everywhere else.
protected-access,
# NOTE(nathaniel): Pylint and I will probably never agree on this.
too-few-public-methods,
# NOTE(nathaniel): Pylint and I wil probably never agree on this for
# private classes. For public classes maybe?
too-many-instance-attributes,
# NOTE(nathaniel): Some of our modules have a lot of lines... of
# specification and documentation. Maybe if this were
# lines-of-code-based we would use it.
too-many-lines,
# TODO(https://github.com/grpc/grpc/issues/261): Maybe we could have
# this one if we extracted just a few more helper functions...
too-many-nested-blocks,
# TODO(https://github.com/grpc/grpc/issues/261): Disable unnecessary
# super-init requirement for abstract class implementations for now.
super-init-not-called,
# NOTE(nathaniel): A single statement that always returns program
# control is better than two statements the first of which sometimes
# returns program control and the second of which always returns
# program control. Probably generally, but definitely in the cases of
# if:/else: and for:/else:.
useless-else-on-loop,
no-else-return,
# NOTE(lidiz): Python 3 make object inheritance default, but not PY2
useless-object-inheritance,

26
BUILD

@ -643,6 +643,17 @@ grpc_cc_library(
public_hdrs = ["src/core/lib/gprpp/debug_location.h"],
)
grpc_cc_library(
name = "optional",
language = "c++",
public_hdrs = [
"src/core/lib/gprpp/optional.h",
],
deps = [
"gpr_base",
],
)
grpc_cc_library(
name = "orphanable",
language = "c++",
@ -724,6 +735,8 @@ grpc_cc_library(
"src/core/lib/iomgr/gethostname_fallback.cc",
"src/core/lib/iomgr/gethostname_host_name_max.cc",
"src/core/lib/iomgr/gethostname_sysconf.cc",
"src/core/lib/iomgr/grpc_if_nametoindex_posix.cc",
"src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc",
"src/core/lib/iomgr/internal_errqueue.cc",
"src/core/lib/iomgr/iocp_windows.cc",
"src/core/lib/iomgr/iomgr.cc",
@ -732,11 +745,8 @@ grpc_cc_library(
"src/core/lib/iomgr/iomgr_posix.cc",
"src/core/lib/iomgr/iomgr_windows.cc",
"src/core/lib/iomgr/is_epollexclusive_available.cc",
"src/core/lib/iomgr/grpc_if_nametoindex_posix.cc",
"src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc",
"src/core/lib/iomgr/load_file.cc",
"src/core/lib/iomgr/lockfree_event.cc",
"src/core/lib/iomgr/network_status_tracker.cc",
"src/core/lib/iomgr/polling_entity.cc",
"src/core/lib/iomgr/pollset.cc",
"src/core/lib/iomgr/pollset_custom.cc",
@ -886,7 +896,6 @@ grpc_cc_library(
"src/core/lib/iomgr/load_file.h",
"src/core/lib/iomgr/lockfree_event.h",
"src/core/lib/iomgr/nameser.h",
"src/core/lib/iomgr/network_status_tracker.h",
"src/core/lib/iomgr/polling_entity.h",
"src/core/lib/iomgr/pollset.h",
"src/core/lib/iomgr/pollset_custom.h",
@ -978,6 +987,7 @@ grpc_cc_library(
"grpc_codegen",
"grpc_trace",
"inlined_vector",
"optional",
"orphanable",
"ref_counted",
"ref_counted_ptr",
@ -1051,11 +1061,13 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/client_channel_factory.cc",
"src/core/ext/filters/client_channel/client_channel_plugin.cc",
"src/core/ext/filters/client_channel/connector.cc",
"src/core/ext/filters/client_channel/global_subchannel_pool.cc",
"src/core/ext/filters/client_channel/health/health_check_client.cc",
"src/core/ext/filters/client_channel/http_connect_handshaker.cc",
"src/core/ext/filters/client_channel/http_proxy.cc",
"src/core/ext/filters/client_channel/lb_policy.cc",
"src/core/ext/filters/client_channel/lb_policy_registry.cc",
"src/core/ext/filters/client_channel/local_subchannel_pool.cc",
"src/core/ext/filters/client_channel/parse_address.cc",
"src/core/ext/filters/client_channel/proxy_mapper.cc",
"src/core/ext/filters/client_channel/proxy_mapper_registry.cc",
@ -1066,7 +1078,7 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/retry_throttle.cc",
"src/core/ext/filters/client_channel/server_address.cc",
"src/core/ext/filters/client_channel/subchannel.cc",
"src/core/ext/filters/client_channel/subchannel_index.cc",
"src/core/ext/filters/client_channel/subchannel_pool_interface.cc",
],
hdrs = [
"src/core/ext/filters/client_channel/backup_poller.h",
@ -1074,12 +1086,14 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/client_channel_channelz.h",
"src/core/ext/filters/client_channel/client_channel_factory.h",
"src/core/ext/filters/client_channel/connector.h",
"src/core/ext/filters/client_channel/global_subchannel_pool.h",
"src/core/ext/filters/client_channel/health/health_check_client.h",
"src/core/ext/filters/client_channel/http_connect_handshaker.h",
"src/core/ext/filters/client_channel/http_proxy.h",
"src/core/ext/filters/client_channel/lb_policy.h",
"src/core/ext/filters/client_channel/lb_policy_factory.h",
"src/core/ext/filters/client_channel/lb_policy_registry.h",
"src/core/ext/filters/client_channel/local_subchannel_pool.h",
"src/core/ext/filters/client_channel/parse_address.h",
"src/core/ext/filters/client_channel/proxy_mapper.h",
"src/core/ext/filters/client_channel/proxy_mapper_registry.h",
@ -1091,7 +1105,7 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/retry_throttle.h",
"src/core/ext/filters/client_channel/server_address.h",
"src/core/ext/filters/client_channel/subchannel.h",
"src/core/ext/filters/client_channel/subchannel_index.h",
"src/core/ext/filters/client_channel/subchannel_pool_interface.h",
],
language = "c++",
deps = [

@ -652,6 +652,7 @@ add_dependencies(buildtests_cxx metrics_client)
add_dependencies(buildtests_cxx mock_test)
add_dependencies(buildtests_cxx nonblocking_test)
add_dependencies(buildtests_cxx noop-benchmark)
add_dependencies(buildtests_cxx optional_test)
add_dependencies(buildtests_cxx orphanable_test)
add_dependencies(buildtests_cxx proto_server_reflection_test)
add_dependencies(buildtests_cxx proto_utils_test)
@ -1008,7 +1009,6 @@ add_library(grpc
src/core/lib/iomgr/is_epollexclusive_available.cc
src/core/lib/iomgr/load_file.cc
src/core/lib/iomgr/lockfree_event.cc
src/core/lib/iomgr/network_status_tracker.cc
src/core/lib/iomgr/polling_entity.cc
src/core/lib/iomgr/pollset.cc
src/core/lib/iomgr/pollset_custom.cc
@ -1213,11 +1213,13 @@ add_library(grpc
src/core/ext/filters/client_channel/client_channel_factory.cc
src/core/ext/filters/client_channel/client_channel_plugin.cc
src/core/ext/filters/client_channel/connector.cc
src/core/ext/filters/client_channel/global_subchannel_pool.cc
src/core/ext/filters/client_channel/health/health_check_client.cc
src/core/ext/filters/client_channel/http_connect_handshaker.cc
src/core/ext/filters/client_channel/http_proxy.cc
src/core/ext/filters/client_channel/lb_policy.cc
src/core/ext/filters/client_channel/lb_policy_registry.cc
src/core/ext/filters/client_channel/local_subchannel_pool.cc
src/core/ext/filters/client_channel/parse_address.cc
src/core/ext/filters/client_channel/proxy_mapper.cc
src/core/ext/filters/client_channel/proxy_mapper_registry.cc
@ -1228,7 +1230,7 @@ add_library(grpc
src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_index.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/deadline/deadline_filter.cc
src/core/ext/filters/client_channel/health/health.pb.c
src/core/tsi/fake_transport_security.cc
@ -1432,7 +1434,6 @@ add_library(grpc_cronet
src/core/lib/iomgr/is_epollexclusive_available.cc
src/core/lib/iomgr/load_file.cc
src/core/lib/iomgr/lockfree_event.cc
src/core/lib/iomgr/network_status_tracker.cc
src/core/lib/iomgr/polling_entity.cc
src/core/lib/iomgr/pollset.cc
src/core/lib/iomgr/pollset_custom.cc
@ -1568,11 +1569,13 @@ add_library(grpc_cronet
src/core/ext/filters/client_channel/client_channel_factory.cc
src/core/ext/filters/client_channel/client_channel_plugin.cc
src/core/ext/filters/client_channel/connector.cc
src/core/ext/filters/client_channel/global_subchannel_pool.cc
src/core/ext/filters/client_channel/health/health_check_client.cc
src/core/ext/filters/client_channel/http_connect_handshaker.cc
src/core/ext/filters/client_channel/http_proxy.cc
src/core/ext/filters/client_channel/lb_policy.cc
src/core/ext/filters/client_channel/lb_policy_registry.cc
src/core/ext/filters/client_channel/local_subchannel_pool.cc
src/core/ext/filters/client_channel/parse_address.cc
src/core/ext/filters/client_channel/proxy_mapper.cc
src/core/ext/filters/client_channel/proxy_mapper_registry.cc
@ -1583,7 +1586,7 @@ add_library(grpc_cronet
src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_index.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/deadline/deadline_filter.cc
src/core/ext/filters/client_channel/health/health.pb.c
third_party/nanopb/pb_common.c
@ -1780,6 +1783,7 @@ add_library(grpc_test_util
test/core/util/subprocess_posix.cc
test/core/util/subprocess_windows.cc
test/core/util/test_config.cc
test/core/util/test_lb_policies.cc
test/core/util/tracer_util.cc
test/core/util/trickle_endpoint.cc
test/core/util/cmdline.cc
@ -1840,7 +1844,6 @@ add_library(grpc_test_util
src/core/lib/iomgr/is_epollexclusive_available.cc
src/core/lib/iomgr/load_file.cc
src/core/lib/iomgr/lockfree_event.cc
src/core/lib/iomgr/network_status_tracker.cc
src/core/lib/iomgr/polling_entity.cc
src/core/lib/iomgr/pollset.cc
src/core/lib/iomgr/pollset_custom.cc
@ -1944,11 +1947,13 @@ add_library(grpc_test_util
src/core/ext/filters/client_channel/client_channel_factory.cc
src/core/ext/filters/client_channel/client_channel_plugin.cc
src/core/ext/filters/client_channel/connector.cc
src/core/ext/filters/client_channel/global_subchannel_pool.cc
src/core/ext/filters/client_channel/health/health_check_client.cc
src/core/ext/filters/client_channel/http_connect_handshaker.cc
src/core/ext/filters/client_channel/http_proxy.cc
src/core/ext/filters/client_channel/lb_policy.cc
src/core/ext/filters/client_channel/lb_policy_registry.cc
src/core/ext/filters/client_channel/local_subchannel_pool.cc
src/core/ext/filters/client_channel/parse_address.cc
src/core/ext/filters/client_channel/proxy_mapper.cc
src/core/ext/filters/client_channel/proxy_mapper_registry.cc
@ -1959,7 +1964,7 @@ add_library(grpc_test_util
src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_index.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/deadline/deadline_filter.cc
src/core/ext/filters/client_channel/health/health.pb.c
third_party/nanopb/pb_common.c
@ -2104,6 +2109,7 @@ add_library(grpc_test_util_unsecure
test/core/util/subprocess_posix.cc
test/core/util/subprocess_windows.cc
test/core/util/test_config.cc
test/core/util/test_lb_policies.cc
test/core/util/tracer_util.cc
test/core/util/trickle_endpoint.cc
test/core/util/cmdline.cc
@ -2164,7 +2170,6 @@ add_library(grpc_test_util_unsecure
src/core/lib/iomgr/is_epollexclusive_available.cc
src/core/lib/iomgr/load_file.cc
src/core/lib/iomgr/lockfree_event.cc
src/core/lib/iomgr/network_status_tracker.cc
src/core/lib/iomgr/polling_entity.cc
src/core/lib/iomgr/pollset.cc
src/core/lib/iomgr/pollset_custom.cc
@ -2268,11 +2273,13 @@ add_library(grpc_test_util_unsecure
src/core/ext/filters/client_channel/client_channel_factory.cc
src/core/ext/filters/client_channel/client_channel_plugin.cc
src/core/ext/filters/client_channel/connector.cc
src/core/ext/filters/client_channel/global_subchannel_pool.cc
src/core/ext/filters/client_channel/health/health_check_client.cc
src/core/ext/filters/client_channel/http_connect_handshaker.cc
src/core/ext/filters/client_channel/http_proxy.cc
src/core/ext/filters/client_channel/lb_policy.cc
src/core/ext/filters/client_channel/lb_policy_registry.cc
src/core/ext/filters/client_channel/local_subchannel_pool.cc
src/core/ext/filters/client_channel/parse_address.cc
src/core/ext/filters/client_channel/proxy_mapper.cc
src/core/ext/filters/client_channel/proxy_mapper_registry.cc
@ -2283,7 +2290,7 @@ add_library(grpc_test_util_unsecure
src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_index.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/deadline/deadline_filter.cc
src/core/ext/filters/client_channel/health/health.pb.c
third_party/nanopb/pb_common.c
@ -2465,7 +2472,6 @@ add_library(grpc_unsecure
src/core/lib/iomgr/is_epollexclusive_available.cc
src/core/lib/iomgr/load_file.cc
src/core/lib/iomgr/lockfree_event.cc
src/core/lib/iomgr/network_status_tracker.cc
src/core/lib/iomgr/polling_entity.cc
src/core/lib/iomgr/pollset.cc
src/core/lib/iomgr/pollset_custom.cc
@ -2604,11 +2610,13 @@ add_library(grpc_unsecure
src/core/ext/filters/client_channel/client_channel_factory.cc
src/core/ext/filters/client_channel/client_channel_plugin.cc
src/core/ext/filters/client_channel/connector.cc
src/core/ext/filters/client_channel/global_subchannel_pool.cc
src/core/ext/filters/client_channel/health/health_check_client.cc
src/core/ext/filters/client_channel/http_connect_handshaker.cc
src/core/ext/filters/client_channel/http_proxy.cc
src/core/ext/filters/client_channel/lb_policy.cc
src/core/ext/filters/client_channel/lb_policy_registry.cc
src/core/ext/filters/client_channel/local_subchannel_pool.cc
src/core/ext/filters/client_channel/parse_address.cc
src/core/ext/filters/client_channel/proxy_mapper.cc
src/core/ext/filters/client_channel/proxy_mapper_registry.cc
@ -2619,7 +2627,7 @@ add_library(grpc_unsecure
src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_index.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/deadline/deadline_filter.cc
src/core/ext/filters/client_channel/health/health.pb.c
third_party/nanopb/pb_common.c
@ -3352,7 +3360,6 @@ add_library(grpc++_cronet
src/core/lib/iomgr/is_epollexclusive_available.cc
src/core/lib/iomgr/load_file.cc
src/core/lib/iomgr/lockfree_event.cc
src/core/lib/iomgr/network_status_tracker.cc
src/core/lib/iomgr/polling_entity.cc
src/core/lib/iomgr/pollset.cc
src/core/lib/iomgr/pollset_custom.cc
@ -3461,11 +3468,13 @@ add_library(grpc++_cronet
src/core/ext/filters/client_channel/client_channel_factory.cc
src/core/ext/filters/client_channel/client_channel_plugin.cc
src/core/ext/filters/client_channel/connector.cc
src/core/ext/filters/client_channel/global_subchannel_pool.cc
src/core/ext/filters/client_channel/health/health_check_client.cc
src/core/ext/filters/client_channel/http_connect_handshaker.cc
src/core/ext/filters/client_channel/http_proxy.cc
src/core/ext/filters/client_channel/lb_policy.cc
src/core/ext/filters/client_channel/lb_policy_registry.cc
src/core/ext/filters/client_channel/local_subchannel_pool.cc
src/core/ext/filters/client_channel/parse_address.cc
src/core/ext/filters/client_channel/proxy_mapper.cc
src/core/ext/filters/client_channel/proxy_mapper_registry.cc
@ -3476,7 +3485,7 @@ add_library(grpc++_cronet
src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_index.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/deadline/deadline_filter.cc
src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc
src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc
@ -5609,7 +5618,6 @@ add_library(end2end_tests
test/core/end2end/tests/max_connection_idle.cc
test/core/end2end/tests/max_message_length.cc
test/core/end2end/tests/negative_deadline.cc
test/core/end2end/tests/network_status_change.cc
test/core/end2end/tests/no_error_on_hotpath.cc
test/core/end2end/tests/no_logging.cc
test/core/end2end/tests/no_op.cc
@ -5733,7 +5741,6 @@ add_library(end2end_nosec_tests
test/core/end2end/tests/max_connection_idle.cc
test/core/end2end/tests/max_message_length.cc
test/core/end2end/tests/negative_deadline.cc
test/core/end2end/tests/network_status_change.cc
test/core/end2end/tests/no_error_on_hotpath.cc
test/core/end2end/tests/no_logging.cc
test/core/end2end/tests/no_op.cc
@ -14439,6 +14446,45 @@ target_link_libraries(noop-benchmark
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(optional_test
test/core/gprpp/optional_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(optional_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(optional_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc++
grpc
gpr
${_gRPC_GFLAGS_LIBRARIES}
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)

@ -1213,6 +1213,7 @@ metrics_client: $(BINDIR)/$(CONFIG)/metrics_client
mock_test: $(BINDIR)/$(CONFIG)/mock_test
nonblocking_test: $(BINDIR)/$(CONFIG)/nonblocking_test
noop-benchmark: $(BINDIR)/$(CONFIG)/noop-benchmark
optional_test: $(BINDIR)/$(CONFIG)/optional_test
orphanable_test: $(BINDIR)/$(CONFIG)/orphanable_test
proto_server_reflection_test: $(BINDIR)/$(CONFIG)/proto_server_reflection_test
proto_utils_test: $(BINDIR)/$(CONFIG)/proto_utils_test
@ -1720,6 +1721,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/mock_test \
$(BINDIR)/$(CONFIG)/nonblocking_test \
$(BINDIR)/$(CONFIG)/noop-benchmark \
$(BINDIR)/$(CONFIG)/optional_test \
$(BINDIR)/$(CONFIG)/orphanable_test \
$(BINDIR)/$(CONFIG)/proto_server_reflection_test \
$(BINDIR)/$(CONFIG)/proto_utils_test \
@ -1906,6 +1908,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/mock_test \
$(BINDIR)/$(CONFIG)/nonblocking_test \
$(BINDIR)/$(CONFIG)/noop-benchmark \
$(BINDIR)/$(CONFIG)/optional_test \
$(BINDIR)/$(CONFIG)/orphanable_test \
$(BINDIR)/$(CONFIG)/proto_server_reflection_test \
$(BINDIR)/$(CONFIG)/proto_utils_test \
@ -2399,6 +2402,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/nonblocking_test || ( echo test nonblocking_test failed ; exit 1 )
$(E) "[RUN] Testing noop-benchmark"
$(Q) $(BINDIR)/$(CONFIG)/noop-benchmark || ( echo test noop-benchmark failed ; exit 1 )
$(E) "[RUN] Testing optional_test"
$(Q) $(BINDIR)/$(CONFIG)/optional_test || ( echo test optional_test failed ; exit 1 )
$(E) "[RUN] Testing orphanable_test"
$(Q) $(BINDIR)/$(CONFIG)/orphanable_test || ( echo test orphanable_test failed ; exit 1 )
$(E) "[RUN] Testing proto_server_reflection_test"
@ -3525,7 +3530,6 @@ LIBGRPC_SRC = \
src/core/lib/iomgr/is_epollexclusive_available.cc \
src/core/lib/iomgr/load_file.cc \
src/core/lib/iomgr/lockfree_event.cc \
src/core/lib/iomgr/network_status_tracker.cc \
src/core/lib/iomgr/polling_entity.cc \
src/core/lib/iomgr/pollset.cc \
src/core/lib/iomgr/pollset_custom.cc \
@ -3730,11 +3734,13 @@ LIBGRPC_SRC = \
src/core/ext/filters/client_channel/client_channel_factory.cc \
src/core/ext/filters/client_channel/client_channel_plugin.cc \
src/core/ext/filters/client_channel/connector.cc \
src/core/ext/filters/client_channel/global_subchannel_pool.cc \
src/core/ext/filters/client_channel/health/health_check_client.cc \
src/core/ext/filters/client_channel/http_connect_handshaker.cc \
src/core/ext/filters/client_channel/http_proxy.cc \
src/core/ext/filters/client_channel/lb_policy.cc \
src/core/ext/filters/client_channel/lb_policy_registry.cc \
src/core/ext/filters/client_channel/local_subchannel_pool.cc \
src/core/ext/filters/client_channel/parse_address.cc \
src/core/ext/filters/client_channel/proxy_mapper.cc \
src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
@ -3745,7 +3751,7 @@ LIBGRPC_SRC = \
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_index.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \
src/core/ext/filters/client_channel/health/health.pb.c \
src/core/tsi/fake_transport_security.cc \
@ -3943,7 +3949,6 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/iomgr/is_epollexclusive_available.cc \
src/core/lib/iomgr/load_file.cc \
src/core/lib/iomgr/lockfree_event.cc \
src/core/lib/iomgr/network_status_tracker.cc \
src/core/lib/iomgr/polling_entity.cc \
src/core/lib/iomgr/pollset.cc \
src/core/lib/iomgr/pollset_custom.cc \
@ -4079,11 +4084,13 @@ LIBGRPC_CRONET_SRC = \
src/core/ext/filters/client_channel/client_channel_factory.cc \
src/core/ext/filters/client_channel/client_channel_plugin.cc \
src/core/ext/filters/client_channel/connector.cc \
src/core/ext/filters/client_channel/global_subchannel_pool.cc \
src/core/ext/filters/client_channel/health/health_check_client.cc \
src/core/ext/filters/client_channel/http_connect_handshaker.cc \
src/core/ext/filters/client_channel/http_proxy.cc \
src/core/ext/filters/client_channel/lb_policy.cc \
src/core/ext/filters/client_channel/lb_policy_registry.cc \
src/core/ext/filters/client_channel/local_subchannel_pool.cc \
src/core/ext/filters/client_channel/parse_address.cc \
src/core/ext/filters/client_channel/proxy_mapper.cc \
src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
@ -4094,7 +4101,7 @@ LIBGRPC_CRONET_SRC = \
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_index.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \
src/core/ext/filters/client_channel/health/health.pb.c \
third_party/nanopb/pb_common.c \
@ -4284,6 +4291,7 @@ LIBGRPC_TEST_UTIL_SRC = \
test/core/util/subprocess_posix.cc \
test/core/util/subprocess_windows.cc \
test/core/util/test_config.cc \
test/core/util/test_lb_policies.cc \
test/core/util/tracer_util.cc \
test/core/util/trickle_endpoint.cc \
test/core/util/cmdline.cc \
@ -4344,7 +4352,6 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/iomgr/is_epollexclusive_available.cc \
src/core/lib/iomgr/load_file.cc \
src/core/lib/iomgr/lockfree_event.cc \
src/core/lib/iomgr/network_status_tracker.cc \
src/core/lib/iomgr/polling_entity.cc \
src/core/lib/iomgr/pollset.cc \
src/core/lib/iomgr/pollset_custom.cc \
@ -4448,11 +4455,13 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/ext/filters/client_channel/client_channel_factory.cc \
src/core/ext/filters/client_channel/client_channel_plugin.cc \
src/core/ext/filters/client_channel/connector.cc \
src/core/ext/filters/client_channel/global_subchannel_pool.cc \
src/core/ext/filters/client_channel/health/health_check_client.cc \
src/core/ext/filters/client_channel/http_connect_handshaker.cc \
src/core/ext/filters/client_channel/http_proxy.cc \
src/core/ext/filters/client_channel/lb_policy.cc \
src/core/ext/filters/client_channel/lb_policy_registry.cc \
src/core/ext/filters/client_channel/local_subchannel_pool.cc \
src/core/ext/filters/client_channel/parse_address.cc \
src/core/ext/filters/client_channel/proxy_mapper.cc \
src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
@ -4463,7 +4472,7 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_index.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \
src/core/ext/filters/client_channel/health/health.pb.c \
third_party/nanopb/pb_common.c \
@ -4595,6 +4604,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
test/core/util/subprocess_posix.cc \
test/core/util/subprocess_windows.cc \
test/core/util/test_config.cc \
test/core/util/test_lb_policies.cc \
test/core/util/tracer_util.cc \
test/core/util/trickle_endpoint.cc \
test/core/util/cmdline.cc \
@ -4655,7 +4665,6 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/lib/iomgr/is_epollexclusive_available.cc \
src/core/lib/iomgr/load_file.cc \
src/core/lib/iomgr/lockfree_event.cc \
src/core/lib/iomgr/network_status_tracker.cc \
src/core/lib/iomgr/polling_entity.cc \
src/core/lib/iomgr/pollset.cc \
src/core/lib/iomgr/pollset_custom.cc \
@ -4759,11 +4768,13 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/ext/filters/client_channel/client_channel_factory.cc \
src/core/ext/filters/client_channel/client_channel_plugin.cc \
src/core/ext/filters/client_channel/connector.cc \
src/core/ext/filters/client_channel/global_subchannel_pool.cc \
src/core/ext/filters/client_channel/health/health_check_client.cc \
src/core/ext/filters/client_channel/http_connect_handshaker.cc \
src/core/ext/filters/client_channel/http_proxy.cc \
src/core/ext/filters/client_channel/lb_policy.cc \
src/core/ext/filters/client_channel/lb_policy_registry.cc \
src/core/ext/filters/client_channel/local_subchannel_pool.cc \
src/core/ext/filters/client_channel/parse_address.cc \
src/core/ext/filters/client_channel/proxy_mapper.cc \
src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
@ -4774,7 +4785,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_index.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \
src/core/ext/filters/client_channel/health/health.pb.c \
third_party/nanopb/pb_common.c \
@ -4930,7 +4941,6 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/iomgr/is_epollexclusive_available.cc \
src/core/lib/iomgr/load_file.cc \
src/core/lib/iomgr/lockfree_event.cc \
src/core/lib/iomgr/network_status_tracker.cc \
src/core/lib/iomgr/polling_entity.cc \
src/core/lib/iomgr/pollset.cc \
src/core/lib/iomgr/pollset_custom.cc \
@ -5069,11 +5079,13 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/filters/client_channel/client_channel_factory.cc \
src/core/ext/filters/client_channel/client_channel_plugin.cc \
src/core/ext/filters/client_channel/connector.cc \
src/core/ext/filters/client_channel/global_subchannel_pool.cc \
src/core/ext/filters/client_channel/health/health_check_client.cc \
src/core/ext/filters/client_channel/http_connect_handshaker.cc \
src/core/ext/filters/client_channel/http_proxy.cc \
src/core/ext/filters/client_channel/lb_policy.cc \
src/core/ext/filters/client_channel/lb_policy_registry.cc \
src/core/ext/filters/client_channel/local_subchannel_pool.cc \
src/core/ext/filters/client_channel/parse_address.cc \
src/core/ext/filters/client_channel/proxy_mapper.cc \
src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
@ -5084,7 +5096,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_index.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \
src/core/ext/filters/client_channel/health/health.pb.c \
third_party/nanopb/pb_common.c \
@ -5794,7 +5806,6 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/iomgr/is_epollexclusive_available.cc \
src/core/lib/iomgr/load_file.cc \
src/core/lib/iomgr/lockfree_event.cc \
src/core/lib/iomgr/network_status_tracker.cc \
src/core/lib/iomgr/polling_entity.cc \
src/core/lib/iomgr/pollset.cc \
src/core/lib/iomgr/pollset_custom.cc \
@ -5903,11 +5914,13 @@ LIBGRPC++_CRONET_SRC = \
src/core/ext/filters/client_channel/client_channel_factory.cc \
src/core/ext/filters/client_channel/client_channel_plugin.cc \
src/core/ext/filters/client_channel/connector.cc \
src/core/ext/filters/client_channel/global_subchannel_pool.cc \
src/core/ext/filters/client_channel/health/health_check_client.cc \
src/core/ext/filters/client_channel/http_connect_handshaker.cc \
src/core/ext/filters/client_channel/http_proxy.cc \
src/core/ext/filters/client_channel/lb_policy.cc \
src/core/ext/filters/client_channel/lb_policy_registry.cc \
src/core/ext/filters/client_channel/local_subchannel_pool.cc \
src/core/ext/filters/client_channel/parse_address.cc \
src/core/ext/filters/client_channel/proxy_mapper.cc \
src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
@ -5918,7 +5931,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_index.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \
src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc \
src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc \
@ -10379,7 +10392,6 @@ LIBEND2END_TESTS_SRC = \
test/core/end2end/tests/max_connection_idle.cc \
test/core/end2end/tests/max_message_length.cc \
test/core/end2end/tests/negative_deadline.cc \
test/core/end2end/tests/network_status_change.cc \
test/core/end2end/tests/no_error_on_hotpath.cc \
test/core/end2end/tests/no_logging.cc \
test/core/end2end/tests/no_op.cc \
@ -10496,7 +10508,6 @@ LIBEND2END_NOSEC_TESTS_SRC = \
test/core/end2end/tests/max_connection_idle.cc \
test/core/end2end/tests/max_message_length.cc \
test/core/end2end/tests/negative_deadline.cc \
test/core/end2end/tests/network_status_change.cc \
test/core/end2end/tests/no_error_on_hotpath.cc \
test/core/end2end/tests/no_logging.cc \
test/core/end2end/tests/no_op.cc \
@ -19438,6 +19449,49 @@ endif
endif
OPTIONAL_TEST_SRC = \
test/core/gprpp/optional_test.cc \
OPTIONAL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(OPTIONAL_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/optional_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
$(BINDIR)/$(CONFIG)/optional_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/optional_test: $(PROTOBUF_DEP) $(OPTIONAL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(OPTIONAL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/optional_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/core/gprpp/optional_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_optional_test: $(OPTIONAL_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(OPTIONAL_TEST_OBJS:.o=.dep)
endif
endif
ORPHANABLE_TEST_SRC = \
test/core/gprpp/orphanable_test.cc \

@ -289,7 +289,6 @@ filegroups:
- src/core/lib/iomgr/is_epollexclusive_available.cc
- src/core/lib/iomgr/load_file.cc
- src/core/lib/iomgr/lockfree_event.cc
- src/core/lib/iomgr/network_status_tracker.cc
- src/core/lib/iomgr/polling_entity.cc
- src/core/lib/iomgr/pollset.cc
- src/core/lib/iomgr/pollset_custom.cc
@ -431,6 +430,7 @@ filegroups:
- src/core/lib/debug/stats_data.h
- src/core/lib/gprpp/debug_location.h
- src/core/lib/gprpp/inlined_vector.h
- src/core/lib/gprpp/optional.h
- src/core/lib/gprpp/orphanable.h
- src/core/lib/gprpp/ref_counted.h
- src/core/lib/gprpp/ref_counted_ptr.h
@ -465,7 +465,6 @@ filegroups:
- src/core/lib/iomgr/load_file.h
- src/core/lib/iomgr/lockfree_event.h
- src/core/lib/iomgr/nameser.h
- src/core/lib/iomgr/network_status_tracker.h
- src/core/lib/iomgr/polling_entity.h
- src/core/lib/iomgr/pollset.h
- src/core/lib/iomgr/pollset_custom.h
@ -578,12 +577,14 @@ filegroups:
- src/core/ext/filters/client_channel/client_channel_channelz.h
- src/core/ext/filters/client_channel/client_channel_factory.h
- src/core/ext/filters/client_channel/connector.h
- src/core/ext/filters/client_channel/global_subchannel_pool.h
- src/core/ext/filters/client_channel/health/health_check_client.h
- src/core/ext/filters/client_channel/http_connect_handshaker.h
- src/core/ext/filters/client_channel/http_proxy.h
- src/core/ext/filters/client_channel/lb_policy.h
- src/core/ext/filters/client_channel/lb_policy_factory.h
- src/core/ext/filters/client_channel/lb_policy_registry.h
- src/core/ext/filters/client_channel/local_subchannel_pool.h
- src/core/ext/filters/client_channel/parse_address.h
- src/core/ext/filters/client_channel/proxy_mapper.h
- src/core/ext/filters/client_channel/proxy_mapper_registry.h
@ -595,7 +596,7 @@ filegroups:
- src/core/ext/filters/client_channel/retry_throttle.h
- src/core/ext/filters/client_channel/server_address.h
- src/core/ext/filters/client_channel/subchannel.h
- src/core/ext/filters/client_channel/subchannel_index.h
- src/core/ext/filters/client_channel/subchannel_pool_interface.h
src:
- src/core/ext/filters/client_channel/backup_poller.cc
- src/core/ext/filters/client_channel/channel_connectivity.cc
@ -604,11 +605,13 @@ filegroups:
- src/core/ext/filters/client_channel/client_channel_factory.cc
- src/core/ext/filters/client_channel/client_channel_plugin.cc
- src/core/ext/filters/client_channel/connector.cc
- src/core/ext/filters/client_channel/global_subchannel_pool.cc
- src/core/ext/filters/client_channel/health/health_check_client.cc
- src/core/ext/filters/client_channel/http_connect_handshaker.cc
- src/core/ext/filters/client_channel/http_proxy.cc
- src/core/ext/filters/client_channel/lb_policy.cc
- src/core/ext/filters/client_channel/lb_policy_registry.cc
- src/core/ext/filters/client_channel/local_subchannel_pool.cc
- src/core/ext/filters/client_channel/parse_address.cc
- src/core/ext/filters/client_channel/proxy_mapper.cc
- src/core/ext/filters/client_channel/proxy_mapper_registry.cc
@ -619,7 +622,7 @@ filegroups:
- src/core/ext/filters/client_channel/retry_throttle.cc
- src/core/ext/filters/client_channel/server_address.cc
- src/core/ext/filters/client_channel/subchannel.cc
- src/core/ext/filters/client_channel/subchannel_index.cc
- src/core/ext/filters/client_channel/subchannel_pool_interface.cc
plugin: grpc_client_channel
uses:
- grpc_base
@ -921,6 +924,7 @@ filegroups:
- test/core/util/slice_splitter.h
- test/core/util/subprocess.h
- test/core/util/test_config.h
- test/core/util/test_lb_policies.h
- test/core/util/tracer_util.h
- test/core/util/trickle_endpoint.h
src:
@ -945,6 +949,7 @@ filegroups:
- test/core/util/subprocess_posix.cc
- test/core/util/subprocess_windows.cc
- test/core/util/test_config.cc
- test/core/util/test_lb_policies.cc
- test/core/util/tracer_util.cc
- test/core/util/trickle_endpoint.cc
deps:
@ -5055,6 +5060,19 @@ targets:
deps:
- benchmark
defaults: benchmark
- name: optional_test
gtest: true
build: test
language: c++
src:
- test/core/gprpp/optional_test.cc
deps:
- grpc_test_util
- grpc++
- grpc
- gpr
uses:
- grpc++_test
- name: orphanable_test
gtest: true
build: test

@ -141,7 +141,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/iomgr/is_epollexclusive_available.cc \
src/core/lib/iomgr/load_file.cc \
src/core/lib/iomgr/lockfree_event.cc \
src/core/lib/iomgr/network_status_tracker.cc \
src/core/lib/iomgr/polling_entity.cc \
src/core/lib/iomgr/pollset.cc \
src/core/lib/iomgr/pollset_custom.cc \
@ -346,11 +345,13 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/client_channel_factory.cc \
src/core/ext/filters/client_channel/client_channel_plugin.cc \
src/core/ext/filters/client_channel/connector.cc \
src/core/ext/filters/client_channel/global_subchannel_pool.cc \
src/core/ext/filters/client_channel/health/health_check_client.cc \
src/core/ext/filters/client_channel/http_connect_handshaker.cc \
src/core/ext/filters/client_channel/http_proxy.cc \
src/core/ext/filters/client_channel/lb_policy.cc \
src/core/ext/filters/client_channel/lb_policy_registry.cc \
src/core/ext/filters/client_channel/local_subchannel_pool.cc \
src/core/ext/filters/client_channel/parse_address.cc \
src/core/ext/filters/client_channel/proxy_mapper.cc \
src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
@ -361,7 +362,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_index.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/deadline/deadline_filter.cc \
src/core/ext/filters/client_channel/health/health.pb.c \
src/core/tsi/fake_transport_security.cc \

@ -116,7 +116,6 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\iomgr\\is_epollexclusive_available.cc " +
"src\\core\\lib\\iomgr\\load_file.cc " +
"src\\core\\lib\\iomgr\\lockfree_event.cc " +
"src\\core\\lib\\iomgr\\network_status_tracker.cc " +
"src\\core\\lib\\iomgr\\polling_entity.cc " +
"src\\core\\lib\\iomgr\\pollset.cc " +
"src\\core\\lib\\iomgr\\pollset_custom.cc " +
@ -321,11 +320,13 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\client_channel_factory.cc " +
"src\\core\\ext\\filters\\client_channel\\client_channel_plugin.cc " +
"src\\core\\ext\\filters\\client_channel\\connector.cc " +
"src\\core\\ext\\filters\\client_channel\\global_subchannel_pool.cc " +
"src\\core\\ext\\filters\\client_channel\\health\\health_check_client.cc " +
"src\\core\\ext\\filters\\client_channel\\http_connect_handshaker.cc " +
"src\\core\\ext\\filters\\client_channel\\http_proxy.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy_registry.cc " +
"src\\core\\ext\\filters\\client_channel\\local_subchannel_pool.cc " +
"src\\core\\ext\\filters\\client_channel\\parse_address.cc " +
"src\\core\\ext\\filters\\client_channel\\proxy_mapper.cc " +
"src\\core\\ext\\filters\\client_channel\\proxy_mapper_registry.cc " +
@ -336,7 +337,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\retry_throttle.cc " +
"src\\core\\ext\\filters\\client_channel\\server_address.cc " +
"src\\core\\ext\\filters\\client_channel\\subchannel.cc " +
"src\\core\\ext\\filters\\client_channel\\subchannel_index.cc " +
"src\\core\\ext\\filters\\client_channel\\subchannel_pool_interface.cc " +
"src\\core\\ext\\filters\\deadline\\deadline_filter.cc " +
"src\\core\\ext\\filters\\client_channel\\health\\health.pb.c " +
"src\\core\\tsi\\fake_transport_security.cc " +

@ -101,7 +101,8 @@ cc_binary(
cc_binary(
name = "keyvaluestore_client",
srcs = ["cpp/keyvaluestore/client.cc"],
srcs = ["cpp/keyvaluestore/caching_interceptor.h",
"cpp/keyvaluestore/client.cc"],
defines = ["BAZEL_BUILD"],
deps = [":keyvaluestore", "//:grpc++"],
)

@ -0,0 +1,134 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <map>
#include <grpcpp/support/client_interceptor.h>
#ifdef BAZEL_BUILD
#include "examples/protos/keyvaluestore.grpc.pb.h"
#else
#include "keyvaluestore.grpc.pb.h"
#endif
// This is a naive implementation of a cache. A new cache is for each call. For
// each new key request, the key is first searched in the map and if found, the
// interceptor fills in the return value without making a request to the server.
// Only if the key is not found in the cache do we make a request.
class CachingInterceptor : public grpc::experimental::Interceptor {
public:
CachingInterceptor(grpc::experimental::ClientRpcInfo* info) {}
void Intercept(
::grpc::experimental::InterceptorBatchMethods* methods) override {
bool hijack = false;
if (methods->QueryInterceptionHookPoint(
grpc::experimental::InterceptionHookPoints::
PRE_SEND_INITIAL_METADATA)) {
// Hijack all calls
hijack = true;
// Create a stream on which this interceptor can make requests
stub_ = keyvaluestore::KeyValueStore::NewStub(
methods->GetInterceptedChannel());
stream_ = stub_->GetValues(&context_);
}
if (methods->QueryInterceptionHookPoint(
grpc::experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) {
// We know that clients perform a Read and a Write in a loop, so we don't
// need to maintain a list of the responses.
std::string requested_key;
const keyvaluestore::Request* req_msg =
static_cast<const keyvaluestore::Request*>(methods->GetSendMessage());
if (req_msg != nullptr) {
requested_key = req_msg->key();
} else {
// The non-serialized form would not be available in certain scenarios,
// so add a fallback
keyvaluestore::Request req_msg;
auto* buffer = methods->GetSerializedSendMessage();
auto copied_buffer = *buffer;
GPR_ASSERT(
grpc::SerializationTraits<keyvaluestore::Request>::Deserialize(
&copied_buffer, &req_msg)
.ok());
requested_key = req_msg.key();
}
// Check if the key is present in the map
auto search = cached_map_.find(requested_key);
if (search != cached_map_.end()) {
std::cout << "Key " << requested_key << "found in map";
response_ = search->second;
} else {
std::cout << "Key " << requested_key << "not found in cache";
// Key was not found in the cache, so make a request
keyvaluestore::Request req;
req.set_key(requested_key);
stream_->Write(req);
keyvaluestore::Response resp;
stream_->Read(&resp);
response_ = resp.value();
// Insert the pair in the cache for future requests
cached_map_.insert({requested_key, response_});
}
}
if (methods->QueryInterceptionHookPoint(
grpc::experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) {
stream_->WritesDone();
}
if (methods->QueryInterceptionHookPoint(
grpc::experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) {
keyvaluestore::Response* resp =
static_cast<keyvaluestore::Response*>(methods->GetRecvMessage());
resp->set_value(response_);
}
if (methods->QueryInterceptionHookPoint(
grpc::experimental::InterceptionHookPoints::PRE_RECV_STATUS)) {
auto* status = methods->GetRecvStatus();
*status = grpc::Status::OK;
}
// One of Hijack or Proceed always needs to be called to make progress.
if (hijack) {
// Hijack is called only once when PRE_SEND_INITIAL_METADATA is present in
// the hook points
methods->Hijack();
} else {
// Proceed is an indicator that the interceptor is done intercepting the
// batch.
methods->Proceed();
}
}
private:
grpc::ClientContext context_;
std::unique_ptr<keyvaluestore::KeyValueStore::Stub> stub_;
std::unique_ptr<
grpc::ClientReaderWriter<keyvaluestore::Request, keyvaluestore::Response>>
stream_;
std::map<std::string, std::string> cached_map_;
std::string response_;
};
class CachingInterceptorFactory
: public grpc::experimental::ClientInterceptorFactoryInterface {
public:
grpc::experimental::Interceptor* CreateClientInterceptor(
grpc::experimental::ClientRpcInfo* info) override {
return new CachingInterceptor(info);
}
};

@ -23,6 +23,8 @@
#include <grpcpp/grpcpp.h>
#include "caching_interceptor.h"
#ifdef BAZEL_BUILD
#include "examples/protos/keyvaluestore.grpc.pb.h"
#else
@ -77,9 +79,20 @@ int main(int argc, char** argv) {
// are created. This channel models a connection to an endpoint (in this case,
// localhost at port 50051). We indicate that the channel isn't authenticated
// (use of InsecureChannelCredentials()).
KeyValueStoreClient client(grpc::CreateChannel(
"localhost:50051", grpc::InsecureChannelCredentials()));
std::vector<std::string> keys = {"key1", "key2", "key3", "key4", "key5"};
// In this example, we are using a cache which has been added in as an
// interceptor.
grpc::ChannelArguments args;
std::vector<
std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface>>
interceptor_creators;
interceptor_creators.push_back(std::unique_ptr<CachingInterceptorFactory>(
new CachingInterceptorFactory()));
auto channel = grpc::experimental::CreateCustomChannelWithInterceptors(
"localhost:50051", grpc::InsecureChannelCredentials(), args,
std::move(interceptor_creators));
KeyValueStoreClient client(channel);
std::vector<std::string> keys = {"key1", "key2", "key3", "key4",
"key5", "key1", "key2", "key4"};
client.GetValues(keys);
return 0;

@ -11,7 +11,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The Python implementation of the GRPC helloworld.Greeter client with channel options and call timeout parameters."""
"""gRPC Python helloworld.Greeter client with channel options and call timeout parameters."""
from __future__ import print_function
import logging

@ -346,12 +346,14 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/client_channel_channelz.h',
'src/core/ext/filters/client_channel/client_channel_factory.h',
'src/core/ext/filters/client_channel/connector.h',
'src/core/ext/filters/client_channel/global_subchannel_pool.h',
'src/core/ext/filters/client_channel/health/health_check_client.h',
'src/core/ext/filters/client_channel/http_connect_handshaker.h',
'src/core/ext/filters/client_channel/http_proxy.h',
'src/core/ext/filters/client_channel/lb_policy.h',
'src/core/ext/filters/client_channel/lb_policy_factory.h',
'src/core/ext/filters/client_channel/lb_policy_registry.h',
'src/core/ext/filters/client_channel/local_subchannel_pool.h',
'src/core/ext/filters/client_channel/parse_address.h',
'src/core/ext/filters/client_channel/proxy_mapper.h',
'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
@ -363,7 +365,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/subchannel.h',
'src/core/ext/filters/client_channel/subchannel_index.h',
'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
'src/core/ext/filters/deadline/deadline_filter.h',
'src/core/ext/filters/client_channel/health/health.pb.h',
'src/core/tsi/fake_transport_security.h',
@ -400,6 +402,7 @@ Pod::Spec.new do |s|
'src/core/lib/debug/stats_data.h',
'src/core/lib/gprpp/debug_location.h',
'src/core/lib/gprpp/inlined_vector.h',
'src/core/lib/gprpp/optional.h',
'src/core/lib/gprpp/orphanable.h',
'src/core/lib/gprpp/ref_counted.h',
'src/core/lib/gprpp/ref_counted_ptr.h',
@ -434,7 +437,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/load_file.h',
'src/core/lib/iomgr/lockfree_event.h',
'src/core/lib/iomgr/nameser.h',
'src/core/lib/iomgr/network_status_tracker.h',
'src/core/lib/iomgr/polling_entity.h',
'src/core/lib/iomgr/pollset.h',
'src/core/lib/iomgr/pollset_custom.h',
@ -594,6 +596,7 @@ Pod::Spec.new do |s|
'src/core/lib/debug/stats_data.h',
'src/core/lib/gprpp/debug_location.h',
'src/core/lib/gprpp/inlined_vector.h',
'src/core/lib/gprpp/optional.h',
'src/core/lib/gprpp/orphanable.h',
'src/core/lib/gprpp/ref_counted.h',
'src/core/lib/gprpp/ref_counted_ptr.h',
@ -628,7 +631,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/load_file.h',
'src/core/lib/iomgr/lockfree_event.h',
'src/core/lib/iomgr/nameser.h',
'src/core/lib/iomgr/network_status_tracker.h',
'src/core/lib/iomgr/polling_entity.h',
'src/core/lib/iomgr/pollset.h',
'src/core/lib/iomgr/pollset_custom.h',

@ -340,12 +340,14 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/client_channel_channelz.h',
'src/core/ext/filters/client_channel/client_channel_factory.h',
'src/core/ext/filters/client_channel/connector.h',
'src/core/ext/filters/client_channel/global_subchannel_pool.h',
'src/core/ext/filters/client_channel/health/health_check_client.h',
'src/core/ext/filters/client_channel/http_connect_handshaker.h',
'src/core/ext/filters/client_channel/http_proxy.h',
'src/core/ext/filters/client_channel/lb_policy.h',
'src/core/ext/filters/client_channel/lb_policy_factory.h',
'src/core/ext/filters/client_channel/lb_policy_registry.h',
'src/core/ext/filters/client_channel/local_subchannel_pool.h',
'src/core/ext/filters/client_channel/parse_address.h',
'src/core/ext/filters/client_channel/proxy_mapper.h',
'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
@ -357,7 +359,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/subchannel.h',
'src/core/ext/filters/client_channel/subchannel_index.h',
'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
'src/core/ext/filters/deadline/deadline_filter.h',
'src/core/ext/filters/client_channel/health/health.pb.h',
'src/core/tsi/fake_transport_security.h',
@ -394,6 +396,7 @@ Pod::Spec.new do |s|
'src/core/lib/debug/stats_data.h',
'src/core/lib/gprpp/debug_location.h',
'src/core/lib/gprpp/inlined_vector.h',
'src/core/lib/gprpp/optional.h',
'src/core/lib/gprpp/orphanable.h',
'src/core/lib/gprpp/ref_counted.h',
'src/core/lib/gprpp/ref_counted_ptr.h',
@ -428,7 +431,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/load_file.h',
'src/core/lib/iomgr/lockfree_event.h',
'src/core/lib/iomgr/nameser.h',
'src/core/lib/iomgr/network_status_tracker.h',
'src/core/lib/iomgr/polling_entity.h',
'src/core/lib/iomgr/pollset.h',
'src/core/lib/iomgr/pollset_custom.h',
@ -585,7 +587,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/is_epollexclusive_available.cc',
'src/core/lib/iomgr/load_file.cc',
'src/core/lib/iomgr/lockfree_event.cc',
'src/core/lib/iomgr/network_status_tracker.cc',
'src/core/lib/iomgr/polling_entity.cc',
'src/core/lib/iomgr/pollset.cc',
'src/core/lib/iomgr/pollset_custom.cc',
@ -787,11 +788,13 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/client_channel_factory.cc',
'src/core/ext/filters/client_channel/client_channel_plugin.cc',
'src/core/ext/filters/client_channel/connector.cc',
'src/core/ext/filters/client_channel/global_subchannel_pool.cc',
'src/core/ext/filters/client_channel/health/health_check_client.cc',
'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
'src/core/ext/filters/client_channel/http_proxy.cc',
'src/core/ext/filters/client_channel/lb_policy.cc',
'src/core/ext/filters/client_channel/lb_policy_registry.cc',
'src/core/ext/filters/client_channel/local_subchannel_pool.cc',
'src/core/ext/filters/client_channel/parse_address.cc',
'src/core/ext/filters/client_channel/proxy_mapper.cc',
'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
@ -802,7 +805,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_index.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/deadline/deadline_filter.cc',
'src/core/ext/filters/client_channel/health/health.pb.c',
'src/core/tsi/fake_transport_security.cc',
@ -966,12 +969,14 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/client_channel_channelz.h',
'src/core/ext/filters/client_channel/client_channel_factory.h',
'src/core/ext/filters/client_channel/connector.h',
'src/core/ext/filters/client_channel/global_subchannel_pool.h',
'src/core/ext/filters/client_channel/health/health_check_client.h',
'src/core/ext/filters/client_channel/http_connect_handshaker.h',
'src/core/ext/filters/client_channel/http_proxy.h',
'src/core/ext/filters/client_channel/lb_policy.h',
'src/core/ext/filters/client_channel/lb_policy_factory.h',
'src/core/ext/filters/client_channel/lb_policy_registry.h',
'src/core/ext/filters/client_channel/local_subchannel_pool.h',
'src/core/ext/filters/client_channel/parse_address.h',
'src/core/ext/filters/client_channel/proxy_mapper.h',
'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
@ -983,7 +988,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/subchannel.h',
'src/core/ext/filters/client_channel/subchannel_index.h',
'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
'src/core/ext/filters/deadline/deadline_filter.h',
'src/core/ext/filters/client_channel/health/health.pb.h',
'src/core/tsi/fake_transport_security.h',
@ -1020,6 +1025,7 @@ Pod::Spec.new do |s|
'src/core/lib/debug/stats_data.h',
'src/core/lib/gprpp/debug_location.h',
'src/core/lib/gprpp/inlined_vector.h',
'src/core/lib/gprpp/optional.h',
'src/core/lib/gprpp/orphanable.h',
'src/core/lib/gprpp/ref_counted.h',
'src/core/lib/gprpp/ref_counted_ptr.h',
@ -1054,7 +1060,6 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/load_file.h',
'src/core/lib/iomgr/lockfree_event.h',
'src/core/lib/iomgr/nameser.h',
'src/core/lib/iomgr/network_status_tracker.h',
'src/core/lib/iomgr/polling_entity.h',
'src/core/lib/iomgr/pollset.h',
'src/core/lib/iomgr/pollset_custom.h',
@ -1230,6 +1235,7 @@ Pod::Spec.new do |s|
'test/core/util/subprocess_posix.cc',
'test/core/util/subprocess_windows.cc',
'test/core/util/test_config.cc',
'test/core/util/test_lb_policies.cc',
'test/core/util/tracer_util.cc',
'test/core/util/trickle_endpoint.cc',
'test/core/util/cmdline.cc',
@ -1256,6 +1262,7 @@ Pod::Spec.new do |s|
'test/core/util/slice_splitter.h',
'test/core/util/subprocess.h',
'test/core/util/test_config.h',
'test/core/util/test_lb_policies.h',
'test/core/util/tracer_util.h',
'test/core/util/trickle_endpoint.h',
'test/core/util/cmdline.h',
@ -1300,7 +1307,6 @@ Pod::Spec.new do |s|
'test/core/end2end/tests/max_connection_idle.cc',
'test/core/end2end/tests/max_message_length.cc',
'test/core/end2end/tests/negative_deadline.cc',
'test/core/end2end/tests/network_status_change.cc',
'test/core/end2end/tests/no_error_on_hotpath.cc',
'test/core/end2end/tests/no_logging.cc',
'test/core/end2end/tests/no_op.cc',

@ -41,8 +41,8 @@ Gem::Specification.new do |s|
s.add_development_dependency 'rake-compiler-dock', '~> 0.5.1'
s.add_development_dependency 'rspec', '~> 3.6'
s.add_development_dependency 'rubocop', '~> 0.49.1'
s.add_development_dependency 'signet', '~> 0.7.0'
s.add_development_dependency 'googleauth', '>= 0.5.1', '< 0.7'
s.add_development_dependency 'signet', '~> 0.7'
s.add_development_dependency 'googleauth', '>= 0.5.1', '< 0.10'
s.extensions = %w(src/ruby/ext/grpc/extconf.rb)
@ -276,12 +276,14 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/client_channel_channelz.h )
s.files += %w( src/core/ext/filters/client_channel/client_channel_factory.h )
s.files += %w( src/core/ext/filters/client_channel/connector.h )
s.files += %w( src/core/ext/filters/client_channel/global_subchannel_pool.h )
s.files += %w( src/core/ext/filters/client_channel/health/health_check_client.h )
s.files += %w( src/core/ext/filters/client_channel/http_connect_handshaker.h )
s.files += %w( src/core/ext/filters/client_channel/http_proxy.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy_factory.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy_registry.h )
s.files += %w( src/core/ext/filters/client_channel/local_subchannel_pool.h )
s.files += %w( src/core/ext/filters/client_channel/parse_address.h )
s.files += %w( src/core/ext/filters/client_channel/proxy_mapper.h )
s.files += %w( src/core/ext/filters/client_channel/proxy_mapper_registry.h )
@ -293,7 +295,7 @@ Gem::Specification.new do |s|
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/subchannel.h )
s.files += %w( src/core/ext/filters/client_channel/subchannel_index.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/client_channel/health/health.pb.h )
s.files += %w( src/core/tsi/fake_transport_security.h )
@ -330,6 +332,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/debug/stats_data.h )
s.files += %w( src/core/lib/gprpp/debug_location.h )
s.files += %w( src/core/lib/gprpp/inlined_vector.h )
s.files += %w( src/core/lib/gprpp/optional.h )
s.files += %w( src/core/lib/gprpp/orphanable.h )
s.files += %w( src/core/lib/gprpp/ref_counted.h )
s.files += %w( src/core/lib/gprpp/ref_counted_ptr.h )
@ -364,7 +367,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/load_file.h )
s.files += %w( src/core/lib/iomgr/lockfree_event.h )
s.files += %w( src/core/lib/iomgr/nameser.h )
s.files += %w( src/core/lib/iomgr/network_status_tracker.h )
s.files += %w( src/core/lib/iomgr/polling_entity.h )
s.files += %w( src/core/lib/iomgr/pollset.h )
s.files += %w( src/core/lib/iomgr/pollset_custom.h )
@ -521,7 +523,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/is_epollexclusive_available.cc )
s.files += %w( src/core/lib/iomgr/load_file.cc )
s.files += %w( src/core/lib/iomgr/lockfree_event.cc )
s.files += %w( src/core/lib/iomgr/network_status_tracker.cc )
s.files += %w( src/core/lib/iomgr/polling_entity.cc )
s.files += %w( src/core/lib/iomgr/pollset.cc )
s.files += %w( src/core/lib/iomgr/pollset_custom.cc )
@ -726,11 +727,13 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/client_channel_factory.cc )
s.files += %w( src/core/ext/filters/client_channel/client_channel_plugin.cc )
s.files += %w( src/core/ext/filters/client_channel/connector.cc )
s.files += %w( src/core/ext/filters/client_channel/global_subchannel_pool.cc )
s.files += %w( src/core/ext/filters/client_channel/health/health_check_client.cc )
s.files += %w( src/core/ext/filters/client_channel/http_connect_handshaker.cc )
s.files += %w( src/core/ext/filters/client_channel/http_proxy.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy_registry.cc )
s.files += %w( src/core/ext/filters/client_channel/local_subchannel_pool.cc )
s.files += %w( src/core/ext/filters/client_channel/parse_address.cc )
s.files += %w( src/core/ext/filters/client_channel/proxy_mapper.cc )
s.files += %w( src/core/ext/filters/client_channel/proxy_mapper_registry.cc )
@ -741,7 +744,7 @@ Gem::Specification.new do |s|
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/subchannel.cc )
s.files += %w( src/core/ext/filters/client_channel/subchannel_index.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/client_channel/health/health.pb.c )
s.files += %w( src/core/tsi/fake_transport_security.cc )

@ -323,7 +323,6 @@
'src/core/lib/iomgr/is_epollexclusive_available.cc',
'src/core/lib/iomgr/load_file.cc',
'src/core/lib/iomgr/lockfree_event.cc',
'src/core/lib/iomgr/network_status_tracker.cc',
'src/core/lib/iomgr/polling_entity.cc',
'src/core/lib/iomgr/pollset.cc',
'src/core/lib/iomgr/pollset_custom.cc',
@ -528,11 +527,13 @@
'src/core/ext/filters/client_channel/client_channel_factory.cc',
'src/core/ext/filters/client_channel/client_channel_plugin.cc',
'src/core/ext/filters/client_channel/connector.cc',
'src/core/ext/filters/client_channel/global_subchannel_pool.cc',
'src/core/ext/filters/client_channel/health/health_check_client.cc',
'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
'src/core/ext/filters/client_channel/http_proxy.cc',
'src/core/ext/filters/client_channel/lb_policy.cc',
'src/core/ext/filters/client_channel/lb_policy_registry.cc',
'src/core/ext/filters/client_channel/local_subchannel_pool.cc',
'src/core/ext/filters/client_channel/parse_address.cc',
'src/core/ext/filters/client_channel/proxy_mapper.cc',
'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
@ -543,7 +544,7 @@
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_index.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/deadline/deadline_filter.cc',
'src/core/ext/filters/client_channel/health/health.pb.c',
'src/core/tsi/fake_transport_security.cc',
@ -627,6 +628,7 @@
'test/core/util/subprocess_posix.cc',
'test/core/util/subprocess_windows.cc',
'test/core/util/test_config.cc',
'test/core/util/test_lb_policies.cc',
'test/core/util/tracer_util.cc',
'test/core/util/trickle_endpoint.cc',
'test/core/util/cmdline.cc',
@ -687,7 +689,6 @@
'src/core/lib/iomgr/is_epollexclusive_available.cc',
'src/core/lib/iomgr/load_file.cc',
'src/core/lib/iomgr/lockfree_event.cc',
'src/core/lib/iomgr/network_status_tracker.cc',
'src/core/lib/iomgr/polling_entity.cc',
'src/core/lib/iomgr/pollset.cc',
'src/core/lib/iomgr/pollset_custom.cc',
@ -791,11 +792,13 @@
'src/core/ext/filters/client_channel/client_channel_factory.cc',
'src/core/ext/filters/client_channel/client_channel_plugin.cc',
'src/core/ext/filters/client_channel/connector.cc',
'src/core/ext/filters/client_channel/global_subchannel_pool.cc',
'src/core/ext/filters/client_channel/health/health_check_client.cc',
'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
'src/core/ext/filters/client_channel/http_proxy.cc',
'src/core/ext/filters/client_channel/lb_policy.cc',
'src/core/ext/filters/client_channel/lb_policy_registry.cc',
'src/core/ext/filters/client_channel/local_subchannel_pool.cc',
'src/core/ext/filters/client_channel/parse_address.cc',
'src/core/ext/filters/client_channel/proxy_mapper.cc',
'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
@ -806,7 +809,7 @@
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_index.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/deadline/deadline_filter.cc',
'src/core/ext/filters/client_channel/health/health.pb.c',
'third_party/nanopb/pb_common.c',
@ -871,6 +874,7 @@
'test/core/util/subprocess_posix.cc',
'test/core/util/subprocess_windows.cc',
'test/core/util/test_config.cc',
'test/core/util/test_lb_policies.cc',
'test/core/util/tracer_util.cc',
'test/core/util/trickle_endpoint.cc',
'test/core/util/cmdline.cc',
@ -931,7 +935,6 @@
'src/core/lib/iomgr/is_epollexclusive_available.cc',
'src/core/lib/iomgr/load_file.cc',
'src/core/lib/iomgr/lockfree_event.cc',
'src/core/lib/iomgr/network_status_tracker.cc',
'src/core/lib/iomgr/polling_entity.cc',
'src/core/lib/iomgr/pollset.cc',
'src/core/lib/iomgr/pollset_custom.cc',
@ -1035,11 +1038,13 @@
'src/core/ext/filters/client_channel/client_channel_factory.cc',
'src/core/ext/filters/client_channel/client_channel_plugin.cc',
'src/core/ext/filters/client_channel/connector.cc',
'src/core/ext/filters/client_channel/global_subchannel_pool.cc',
'src/core/ext/filters/client_channel/health/health_check_client.cc',
'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
'src/core/ext/filters/client_channel/http_proxy.cc',
'src/core/ext/filters/client_channel/lb_policy.cc',
'src/core/ext/filters/client_channel/lb_policy_registry.cc',
'src/core/ext/filters/client_channel/local_subchannel_pool.cc',
'src/core/ext/filters/client_channel/parse_address.cc',
'src/core/ext/filters/client_channel/proxy_mapper.cc',
'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
@ -1050,7 +1055,7 @@
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_index.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/deadline/deadline_filter.cc',
'src/core/ext/filters/client_channel/health/health.pb.c',
'third_party/nanopb/pb_common.c',
@ -1152,7 +1157,6 @@
'src/core/lib/iomgr/is_epollexclusive_available.cc',
'src/core/lib/iomgr/load_file.cc',
'src/core/lib/iomgr/lockfree_event.cc',
'src/core/lib/iomgr/network_status_tracker.cc',
'src/core/lib/iomgr/polling_entity.cc',
'src/core/lib/iomgr/pollset.cc',
'src/core/lib/iomgr/pollset_custom.cc',
@ -1291,11 +1295,13 @@
'src/core/ext/filters/client_channel/client_channel_factory.cc',
'src/core/ext/filters/client_channel/client_channel_plugin.cc',
'src/core/ext/filters/client_channel/connector.cc',
'src/core/ext/filters/client_channel/global_subchannel_pool.cc',
'src/core/ext/filters/client_channel/health/health_check_client.cc',
'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
'src/core/ext/filters/client_channel/http_proxy.cc',
'src/core/ext/filters/client_channel/lb_policy.cc',
'src/core/ext/filters/client_channel/lb_policy_registry.cc',
'src/core/ext/filters/client_channel/local_subchannel_pool.cc',
'src/core/ext/filters/client_channel/parse_address.cc',
'src/core/ext/filters/client_channel/proxy_mapper.cc',
'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
@ -1306,7 +1312,7 @@
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_index.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/deadline/deadline_filter.cc',
'src/core/ext/filters/client_channel/health/health.pb.c',
'third_party/nanopb/pb_common.c',
@ -2721,7 +2727,6 @@
'test/core/end2end/tests/max_connection_idle.cc',
'test/core/end2end/tests/max_message_length.cc',
'test/core/end2end/tests/negative_deadline.cc',
'test/core/end2end/tests/network_status_change.cc',
'test/core/end2end/tests/no_error_on_hotpath.cc',
'test/core/end2end/tests/no_logging.cc',
'test/core/end2end/tests/no_op.cc',
@ -2811,7 +2816,6 @@
'test/core/end2end/tests/max_connection_idle.cc',
'test/core/end2end/tests/max_message_length.cc',
'test/core/end2end/tests/negative_deadline.cc',
'test/core/end2end/tests/network_status_change.cc',
'test/core/end2end/tests/no_error_on_hotpath.cc',
'test/core/end2end/tests/no_logging.cc',
'test/core/end2end/tests/no_op.cc',

@ -350,11 +350,19 @@ typedef struct {
/** If set, inhibits health checking (which may be enabled via the
* service config.) */
#define GRPC_ARG_INHIBIT_HEALTH_CHECKING "grpc.inhibit_health_checking"
/** If set, the channel's resolver is allowed to query for SRV records.
* For example, this is useful as a way to enable the "grpclb"
* load balancing policy. Note that this only works with the "ares"
* DNS resolver, and isn't supported by the "native" DNS resolver. */
#define GRPC_ARG_DNS_ENABLE_SRV_QUERIES "grpc.dns_enable_srv_queries"
/** If set, determines the number of milliseconds that the c-ares based
* DNS resolver will wait on queries before cancelling them. The default value
* is 10000. Setting this to "0" will disable c-ares query timeouts
* entirely. */
#define GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS "grpc.dns_ares_query_timeout"
/** If set, uses a local subchannel pool within the channel. Otherwise, uses the
* global subchannel pool. */
#define GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL "grpc.use_local_subchannel_pool"
/** gRPC Objective-C channel pooling domain string. */
#define GRPC_ARG_CHANNEL_POOL_DOMAIN "grpc.channel_pooling_domain"
/** gRPC Objective-C channel pooling id. */

@ -281,12 +281,14 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel_channelz.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/connector.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/global_subchannel_pool.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/health/health_check_client.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/http_connect_handshaker.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/http_proxy.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_registry.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/local_subchannel_pool.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/parse_address.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper_registry.h" role="src" />
@ -298,7 +300,7 @@
<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/subchannel.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_index.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/client_channel/health/health.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/fake_transport_security.h" role="src" />
@ -335,6 +337,7 @@
<file baseinstalldir="/" name="src/core/lib/debug/stats_data.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/debug_location.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/inlined_vector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/optional.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/orphanable.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/ref_counted.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/ref_counted_ptr.h" role="src" />
@ -369,7 +372,6 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/load_file.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/lockfree_event.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/nameser.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/network_status_tracker.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/polling_entity.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/pollset.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/pollset_custom.h" role="src" />
@ -526,7 +528,6 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/is_epollexclusive_available.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/load_file.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/lockfree_event.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/network_status_tracker.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/polling_entity.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/pollset.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/pollset_custom.cc" role="src" />
@ -731,11 +732,13 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel_factory.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel_plugin.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/connector.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/global_subchannel_pool.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/health/health_check_client.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/http_connect_handshaker.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/http_proxy.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_registry.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/local_subchannel_pool.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/parse_address.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper_registry.cc" role="src" />
@ -746,7 +749,7 @@
<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/subchannel.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_index.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/client_channel/health/health.pb.c" role="src" />
<file baseinstalldir="/" name="src/core/tsi/fake_transport_security.cc" role="src" />

@ -353,20 +353,23 @@ void PrintMethodImplementations(Printer* printer,
printer.Print(vars,
"@implementation $service_class$\n\n"
"#pragma clang diagnostic push\n"
"#pragma clang diagnostic ignored "
"\"-Wobjc-designated-initializers\"\n\n"
"// Designated initializer\n"
"- (instancetype)initWithHost:(NSString *)host "
"callOptions:(GRPCCallOptions *_Nullable)callOptions {\n"
" self = [super initWithHost:host\n"
" return [super initWithHost:host\n"
" packageName:@\"$package$\"\n"
" serviceName:@\"$service_name$\"\n"
" callOptions:callOptions];\n"
" return self;\n"
"}\n\n"
"- (instancetype)initWithHost:(NSString *)host {\n"
" return [super initWithHost:host\n"
" packageName:@\"$package$\"\n"
" serviceName:@\"$service_name$\"];\n"
"}\n\n");
"}\n\n"
"#pragma clang diagnostic pop\n\n");
printer.Print(
"// Override superclass initializer to disallow different"
@ -375,6 +378,12 @@ void PrintMethodImplementations(Printer* printer,
" packageName:(NSString *)packageName\n"
" serviceName:(NSString *)serviceName {\n"
" return [self initWithHost:host];\n"
"}\n\n"
"- (instancetype)initWithHost:(NSString *)host\n"
" packageName:(NSString *)packageName\n"
" serviceName:(NSString *)serviceName\n"
" callOptions:(GRPCCallOptions *)callOptions {\n"
" return [self initWithHost:host callOptions:callOptions];\n"
"}\n\n");
printer.Print(

@ -727,6 +727,25 @@ static void free_cached_send_op_data_for_completed_batch(
}
}
//
// LB recv_trailing_metadata_ready handling
//
void maybe_inject_recv_trailing_metadata_ready_for_lb(
const grpc_core::LoadBalancingPolicy::PickState& pick,
grpc_transport_stream_op_batch* batch) {
if (pick.recv_trailing_metadata_ready != nullptr) {
*pick.original_recv_trailing_metadata_ready =
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
pick.recv_trailing_metadata_ready;
if (pick.recv_trailing_metadata != nullptr) {
*pick.recv_trailing_metadata =
batch->payload->recv_trailing_metadata.recv_trailing_metadata;
}
}
}
//
// pending_batches management
//
@ -851,6 +870,10 @@ static void pending_batches_fail(grpc_call_element* elem, grpc_error* error,
pending_batch* pending = &calld->pending_batches[i];
grpc_transport_stream_op_batch* batch = pending->batch;
if (batch != nullptr) {
if (batch->recv_trailing_metadata && calld->have_request) {
maybe_inject_recv_trailing_metadata_ready_for_lb(
*calld->request->pick(), batch);
}
batch->handler_private.extra_arg = calld;
GRPC_CLOSURE_INIT(&batch->handler_private.closure,
fail_pending_batch_in_call_combiner, batch,
@ -903,6 +926,10 @@ static void pending_batches_resume(grpc_call_element* elem) {
pending_batch* pending = &calld->pending_batches[i];
grpc_transport_stream_op_batch* batch = pending->batch;
if (batch != nullptr) {
if (batch->recv_trailing_metadata) {
maybe_inject_recv_trailing_metadata_ready_for_lb(
*calld->request->pick(), batch);
}
batch->handler_private.extra_arg = calld->subchannel_call;
GRPC_CLOSURE_INIT(&batch->handler_private.closure,
resume_pending_batch_in_call_combiner, batch,
@ -1932,6 +1959,8 @@ static void add_retriable_recv_trailing_metadata_op(
batch_data->batch.payload->recv_trailing_metadata
.recv_trailing_metadata_ready =
&retry_state->recv_trailing_metadata_ready;
maybe_inject_recv_trailing_metadata_ready_for_lb(*calld->request->pick(),
&batch_data->batch);
}
// Helper function used to start a recv_trailing_metadata batch. This

@ -26,13 +26,13 @@
#include "src/core/ext/filters/client_channel/client_channel.h"
#include "src/core/ext/filters/client_channel/client_channel_channelz.h"
#include "src/core/ext/filters/client_channel/global_subchannel_pool.h"
#include "src/core/ext/filters/client_channel/http_connect_handshaker.h"
#include "src/core/ext/filters/client_channel/http_proxy.h"
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/ext/filters/client_channel/proxy_mapper_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/subchannel_index.h"
#include "src/core/lib/surface/channel_init.h"
static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
@ -54,7 +54,7 @@ void grpc_client_channel_init(void) {
grpc_core::internal::ServerRetryThrottleMap::Init();
grpc_proxy_mapper_registry_init();
grpc_register_http_proxy_mapper();
grpc_subchannel_index_init();
grpc_core::GlobalSubchannelPool::Init();
grpc_channel_init_register_stage(
GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter,
(void*)&grpc_client_channel_filter);
@ -62,7 +62,7 @@ void grpc_client_channel_init(void) {
}
void grpc_client_channel_shutdown(void) {
grpc_subchannel_index_shutdown();
grpc_core::GlobalSubchannelPool::Shutdown();
grpc_channel_init_shutdown();
grpc_proxy_mapper_registry_shutdown();
grpc_core::internal::ServerRetryThrottleMap::Shutdown();

@ -0,0 +1,177 @@
//
//
// Copyright 2018 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/global_subchannel_pool.h"
#include "src/core/ext/filters/client_channel/subchannel.h"
namespace grpc_core {
GlobalSubchannelPool::GlobalSubchannelPool() {
subchannel_map_ = grpc_avl_create(&subchannel_avl_vtable_);
gpr_mu_init(&mu_);
}
GlobalSubchannelPool::~GlobalSubchannelPool() {
gpr_mu_destroy(&mu_);
grpc_avl_unref(subchannel_map_, nullptr);
}
void GlobalSubchannelPool::Init() {
instance_ = New<RefCountedPtr<GlobalSubchannelPool>>(
MakeRefCounted<GlobalSubchannelPool>());
}
void GlobalSubchannelPool::Shutdown() {
// To ensure Init() was called before.
GPR_ASSERT(instance_ != nullptr);
// To ensure Shutdown() was not called before.
GPR_ASSERT(*instance_ != nullptr);
instance_->reset();
Delete(instance_);
}
RefCountedPtr<GlobalSubchannelPool> GlobalSubchannelPool::instance() {
GPR_ASSERT(instance_ != nullptr);
GPR_ASSERT(*instance_ != nullptr);
return *instance_;
}
grpc_subchannel* GlobalSubchannelPool::RegisterSubchannel(
SubchannelKey* key, grpc_subchannel* constructed) {
grpc_subchannel* c = nullptr;
// Compare and swap (CAS) loop:
while (c == nullptr) {
// Ref the shared map to have a local copy.
gpr_mu_lock(&mu_);
grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr);
gpr_mu_unlock(&mu_);
// Check to see if a subchannel already exists.
c = static_cast<grpc_subchannel*>(grpc_avl_get(old_map, key, nullptr));
if (c != nullptr) {
// The subchannel already exists. Reuse it.
c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "subchannel_register+reuse");
GRPC_SUBCHANNEL_UNREF(constructed, "subchannel_register+found_existing");
// Exit the CAS loop without modifying the shared map.
} else {
// There hasn't been such subchannel. Add one.
// Note that we should ref the old map first because grpc_avl_add() will
// unref it while we still need to access it later.
grpc_avl new_map = grpc_avl_add(
grpc_avl_ref(old_map, nullptr), New<SubchannelKey>(*key),
GRPC_SUBCHANNEL_WEAK_REF(constructed, "subchannel_register+new"),
nullptr);
// Try to publish the change to the shared map. It may happen (but
// unlikely) that some other thread has changed the shared map, so compare
// to make sure it's unchanged before swapping. Retry if it's changed.
gpr_mu_lock(&mu_);
if (old_map.root == subchannel_map_.root) {
GPR_SWAP(grpc_avl, new_map, subchannel_map_);
c = constructed;
}
gpr_mu_unlock(&mu_);
grpc_avl_unref(new_map, nullptr);
}
grpc_avl_unref(old_map, nullptr);
}
return c;
}
void GlobalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) {
bool done = false;
// Compare and swap (CAS) loop:
while (!done) {
// Ref the shared map to have a local copy.
gpr_mu_lock(&mu_);
grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr);
gpr_mu_unlock(&mu_);
// Remove the subchannel.
// Note that we should ref the old map first because grpc_avl_remove() will
// unref it while we still need to access it later.
grpc_avl new_map =
grpc_avl_remove(grpc_avl_ref(old_map, nullptr), key, nullptr);
// Try to publish the change to the shared map. It may happen (but
// unlikely) that some other thread has changed the shared map, so compare
// to make sure it's unchanged before swapping. Retry if it's changed.
gpr_mu_lock(&mu_);
if (old_map.root == subchannel_map_.root) {
GPR_SWAP(grpc_avl, new_map, subchannel_map_);
done = true;
}
gpr_mu_unlock(&mu_);
grpc_avl_unref(new_map, nullptr);
grpc_avl_unref(old_map, nullptr);
}
}
grpc_subchannel* GlobalSubchannelPool::FindSubchannel(SubchannelKey* key) {
// Lock, and take a reference to the subchannel map.
// We don't need to do the search under a lock as AVL's are immutable.
gpr_mu_lock(&mu_);
grpc_avl index = grpc_avl_ref(subchannel_map_, nullptr);
gpr_mu_unlock(&mu_);
grpc_subchannel* c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(
static_cast<grpc_subchannel*>(grpc_avl_get(index, key, nullptr)),
"found_from_pool");
grpc_avl_unref(index, nullptr);
return c;
}
RefCountedPtr<GlobalSubchannelPool>* GlobalSubchannelPool::instance_ = nullptr;
namespace {
void sck_avl_destroy(void* p, void* user_data) {
SubchannelKey* key = static_cast<SubchannelKey*>(p);
Delete(key);
}
void* sck_avl_copy(void* p, void* unused) {
const SubchannelKey* key = static_cast<const SubchannelKey*>(p);
auto* new_key = New<SubchannelKey>(*key);
return static_cast<void*>(new_key);
}
long sck_avl_compare(void* a, void* b, void* unused) {
const SubchannelKey* key_a = static_cast<const SubchannelKey*>(a);
const SubchannelKey* key_b = static_cast<const SubchannelKey*>(b);
return key_a->Cmp(*key_b);
}
void scv_avl_destroy(void* p, void* user_data) {
GRPC_SUBCHANNEL_WEAK_UNREF((grpc_subchannel*)p, "global_subchannel_pool");
}
void* scv_avl_copy(void* p, void* unused) {
GRPC_SUBCHANNEL_WEAK_REF((grpc_subchannel*)p, "global_subchannel_pool");
return p;
}
} // namespace
const grpc_avl_vtable GlobalSubchannelPool::subchannel_avl_vtable_ = {
sck_avl_destroy, // destroy_key
sck_avl_copy, // copy_key
sck_avl_compare, // compare_keys
scv_avl_destroy, // destroy_value
scv_avl_copy // copy_value
};
} // namespace grpc_core

@ -0,0 +1,68 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_GLOBAL_SUBCHANNEL_POOL_H
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_GLOBAL_SUBCHANNEL_POOL_H
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
namespace grpc_core {
// The global subchannel pool. It shares subchannels among channels. There
// should be only one instance of this class. Init() should be called once at
// the filter initialization time; Shutdown() should be called once at the
// filter shutdown time.
// TODO(juanlishen): Enable subchannel retention.
class GlobalSubchannelPool final : public SubchannelPoolInterface {
public:
// The ctor and dtor are not intended to use directly.
GlobalSubchannelPool();
~GlobalSubchannelPool() override;
// Should be called exactly once at filter initialization time.
static void Init();
// Should be called exactly once at filter shutdown time.
static void Shutdown();
// Gets the singleton instance.
static RefCountedPtr<GlobalSubchannelPool> instance();
// Implements interface methods.
grpc_subchannel* RegisterSubchannel(SubchannelKey* key,
grpc_subchannel* constructed) override;
void UnregisterSubchannel(SubchannelKey* key) override;
grpc_subchannel* FindSubchannel(SubchannelKey* key) override;
private:
// The singleton instance. (It's a pointer to RefCountedPtr so that this
// non-local static object can be trivially destructible.)
static RefCountedPtr<GlobalSubchannelPool>* instance_;
// The vtable for subchannel operations in an AVL tree.
static const grpc_avl_vtable subchannel_avl_vtable_;
// A map from subchannel key to subchannel.
grpc_avl subchannel_map_;
// To protect subchannel_map_.
gpr_mu mu_;
};
} // namespace grpc_core
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_GLOBAL_SUBCHANNEL_POOL_H */

@ -19,6 +19,7 @@
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/lb_policy.h"
#include "src/core/lib/iomgr/combiner.h"
grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount(
@ -26,10 +27,11 @@ grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount(
namespace grpc_core {
LoadBalancingPolicy::LoadBalancingPolicy(const Args& args)
LoadBalancingPolicy::LoadBalancingPolicy(Args args)
: InternallyRefCounted(&grpc_trace_lb_policy_refcount),
combiner_(GRPC_COMBINER_REF(args.combiner, "lb_policy")),
client_channel_factory_(args.client_channel_factory),
subchannel_pool_(std::move(args.subchannel_pool)),
interested_parties_(grpc_pollset_set_create()),
request_reresolution_(nullptr) {}

@ -24,6 +24,7 @@
#include "src/core/ext/filters/client_channel/client_channel_channelz.h"
#include "src/core/ext/filters/client_channel/client_channel_factory.h"
#include "src/core/ext/filters/client_channel/subchannel.h"
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
#include "src/core/lib/gprpp/abstract.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
@ -53,6 +54,8 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
grpc_combiner* combiner = nullptr;
/// Used to create channels and subchannels.
grpc_client_channel_factory* client_channel_factory = nullptr;
/// Subchannel pool.
RefCountedPtr<SubchannelPoolInterface> subchannel_pool;
/// Channel args from the resolver.
/// Note that the LB policy gets the set of addresses from the
/// GRPC_ARG_SERVER_ADDRESS_LIST channel arg.
@ -74,6 +77,19 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
/// Closure to run when pick is complete, if not completed synchronously.
/// If null, pick will fail if a result is not available synchronously.
grpc_closure* on_complete = nullptr;
// Callback set by lb policy to be notified of trailing metadata.
// The callback must be scheduled on grpc_schedule_on_exec_ctx.
grpc_closure* recv_trailing_metadata_ready = nullptr;
// The address that will be set to point to the original
// recv_trailing_metadata_ready callback, to be invoked by the LB
// policy's recv_trailing_metadata_ready callback when complete.
// Must be non-null if recv_trailing_metadata_ready is non-null.
grpc_closure** original_recv_trailing_metadata_ready = nullptr;
// If this is not nullptr, then the client channel will point it to the
// call's trailing metadata before invoking recv_trailing_metadata_ready.
// If this is nullptr, then the callback will still be called.
// The lb does not have ownership of the metadata.
grpc_metadata_batch** recv_trailing_metadata = nullptr;
/// Will be set to the selected subchannel, or nullptr on failure or when
/// the LB policy decides to drop the call.
RefCountedPtr<ConnectedSubchannel> connected_subchannel;
@ -171,12 +187,18 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
grpc_pollset_set* interested_parties() const { return interested_parties_; }
// Callers that need their own reference can call the returned
// object's Ref() method.
SubchannelPoolInterface* subchannel_pool() const {
return subchannel_pool_.get();
}
GRPC_ABSTRACT_BASE_CLASS
protected:
GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
explicit LoadBalancingPolicy(const Args& args);
explicit LoadBalancingPolicy(Args args);
virtual ~LoadBalancingPolicy();
grpc_combiner* combiner() const { return combiner_; }
@ -204,6 +226,8 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
grpc_combiner* combiner_;
/// Client channel factory, used to create channels and subchannels.
grpc_client_channel_factory* client_channel_factory_;
/// Subchannel pool.
RefCountedPtr<SubchannelPoolInterface> subchannel_pool_;
/// Owned pointer to interested parties in load balancing decisions.
grpc_pollset_set* interested_parties_;
/// Callback to force a re-resolution.

@ -85,7 +85,6 @@
#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/server_address.h"
#include "src/core/ext/filters/client_channel/subchannel_index.h"
#include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
@ -126,7 +125,7 @@ constexpr char kGrpclb[] = "grpclb";
class GrpcLb : public LoadBalancingPolicy {
public:
explicit GrpcLb(const Args& args);
explicit GrpcLb(Args args);
const char* name() const override { return kGrpclb; }
@ -274,7 +273,7 @@ class GrpcLb : public LoadBalancingPolicy {
// Methods for dealing with the RR policy.
void CreateOrUpdateRoundRobinPolicyLocked();
grpc_channel_args* CreateRoundRobinPolicyArgsLocked();
void CreateRoundRobinPolicyLocked(const Args& args);
void CreateRoundRobinPolicyLocked(Args args);
bool PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp,
grpc_error** error);
void UpdateConnectivityStateFromRoundRobinPolicyLocked(
@ -297,9 +296,8 @@ class GrpcLb : public LoadBalancingPolicy {
// The channel for communicating with the LB server.
grpc_channel* lb_channel_ = nullptr;
// Mutex to protect the channel to the LB server. This is used when
// processing a channelz request.
gpr_mu lb_channel_mu_;
// Uuid of the lb channel. Used for channelz.
gpr_atm lb_channel_uuid_ = 0;
grpc_connectivity_state lb_channel_connectivity_;
grpc_closure lb_channel_on_connectivity_changed_;
// Are we already watching the LB channel's connectivity?
@ -975,8 +973,8 @@ grpc_channel_args* BuildBalancerChannelArgs(
// ctor and dtor
//
GrpcLb::GrpcLb(const LoadBalancingPolicy::Args& args)
: LoadBalancingPolicy(args),
GrpcLb::GrpcLb(LoadBalancingPolicy::Args args)
: LoadBalancingPolicy(std::move(args)),
response_generator_(MakeRefCounted<FakeResolverResponseGenerator>()),
lb_call_backoff_(
BackOff::Options()
@ -987,8 +985,6 @@ GrpcLb::GrpcLb(const LoadBalancingPolicy::Args& args)
.set_max_backoff(GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS *
1000)) {
// Initialization.
gpr_mu_init(&lb_channel_mu_);
grpc_subchannel_index_ref();
GRPC_CLOSURE_INIT(&lb_channel_on_connectivity_changed_,
&GrpcLb::OnBalancerChannelConnectivityChangedLocked, this,
grpc_combiner_scheduler(args.combiner));
@ -1025,14 +1021,12 @@ GrpcLb::GrpcLb(const LoadBalancingPolicy::Args& args)
GrpcLb::~GrpcLb() {
GPR_ASSERT(pending_picks_ == nullptr);
gpr_mu_destroy(&lb_channel_mu_);
gpr_free((void*)server_name_);
grpc_channel_args_destroy(args_);
grpc_connectivity_state_destroy(&state_tracker_);
if (serverlist_ != nullptr) {
grpc_grpclb_destroy_serverlist(serverlist_);
}
grpc_subchannel_index_unref();
}
void GrpcLb::ShutdownLocked() {
@ -1052,10 +1046,9 @@ void GrpcLb::ShutdownLocked() {
// OnBalancerChannelConnectivityChangedLocked(), and we need to be
// alive when that callback is invoked.
if (lb_channel_ != nullptr) {
gpr_mu_lock(&lb_channel_mu_);
grpc_channel_destroy(lb_channel_);
lb_channel_ = nullptr;
gpr_mu_unlock(&lb_channel_mu_);
gpr_atm_no_barrier_store(&lb_channel_uuid_, 0);
}
grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_REF(error), "grpclb_shutdown");
@ -1210,14 +1203,12 @@ void GrpcLb::FillChildRefsForChannelz(
channelz::ChildRefsList* child_subchannels,
channelz::ChildRefsList* child_channels) {
// delegate to the RoundRobin to fill the children subchannels.
rr_policy_->FillChildRefsForChannelz(child_subchannels, child_channels);
MutexLock lock(&lb_channel_mu_);
if (lb_channel_ != nullptr) {
grpc_core::channelz::ChannelNode* channel_node =
grpc_channel_get_channelz_node(lb_channel_);
if (channel_node != nullptr) {
child_channels->push_back(channel_node->uuid());
}
if (rr_policy_ != nullptr) {
rr_policy_->FillChildRefsForChannelz(child_subchannels, child_channels);
}
gpr_atm uuid = gpr_atm_no_barrier_load(&lb_channel_uuid_);
if (uuid != 0) {
child_channels->push_back(uuid);
}
}
@ -1277,12 +1268,15 @@ void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
if (lb_channel_ == nullptr) {
char* uri_str;
gpr_asprintf(&uri_str, "fake:///%s", server_name_);
gpr_mu_lock(&lb_channel_mu_);
lb_channel_ = grpc_client_channel_factory_create_channel(
client_channel_factory(), uri_str,
GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, lb_channel_args);
gpr_mu_unlock(&lb_channel_mu_);
GPR_ASSERT(lb_channel_ != nullptr);
grpc_core::channelz::ChannelNode* channel_node =
grpc_channel_get_channelz_node(lb_channel_);
if (channel_node != nullptr) {
gpr_atm_no_barrier_store(&lb_channel_uuid_, channel_node->uuid());
}
gpr_free(uri_str);
}
// Propagate updates to the LB channel (pick_first) through the fake
@ -1594,10 +1588,10 @@ bool GrpcLb::PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp,
return pick_done;
}
void GrpcLb::CreateRoundRobinPolicyLocked(const Args& args) {
void GrpcLb::CreateRoundRobinPolicyLocked(Args args) {
GPR_ASSERT(rr_policy_ == nullptr);
rr_policy_ = LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
"round_robin", args);
"round_robin", std::move(args));
if (GPR_UNLIKELY(rr_policy_ == nullptr)) {
gpr_log(GPR_ERROR, "[grpclb %p] Failure creating a RoundRobin policy",
this);
@ -1699,7 +1693,8 @@ void GrpcLb::CreateOrUpdateRoundRobinPolicyLocked() {
lb_policy_args.combiner = combiner();
lb_policy_args.client_channel_factory = client_channel_factory();
lb_policy_args.args = args;
CreateRoundRobinPolicyLocked(lb_policy_args);
lb_policy_args.subchannel_pool = subchannel_pool()->Ref();
CreateRoundRobinPolicyLocked(std::move(lb_policy_args));
}
grpc_channel_args_destroy(args);
}
@ -1807,7 +1802,7 @@ void GrpcLb::OnRoundRobinConnectivityChangedLocked(void* arg,
class GrpcLbFactory : public LoadBalancingPolicyFactory {
public:
OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
const LoadBalancingPolicy::Args& args) const override {
LoadBalancingPolicy::Args args) const override {
/* Count the number of gRPC-LB addresses. There must be at least one. */
const ServerAddressList* addresses =
FindServerAddressListChannelArg(args.args);
@ -1820,7 +1815,7 @@ class GrpcLbFactory : public LoadBalancingPolicyFactory {
}
}
if (!found_balancer) return nullptr;
return OrphanablePtr<LoadBalancingPolicy>(New<GrpcLb>(args));
return OrphanablePtr<LoadBalancingPolicy>(New<GrpcLb>(std::move(args)));
}
const char* name() const override { return kGrpclb; }

@ -26,7 +26,6 @@
#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/subchannel.h"
#include "src/core/ext/filters/client_channel/subchannel_index.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gprpp/mutex_lock.h"
#include "src/core/lib/iomgr/combiner.h"
@ -47,7 +46,7 @@ constexpr char kPickFirst[] = "pick_first";
class PickFirst : public LoadBalancingPolicy {
public:
explicit PickFirst(const Args& args);
explicit PickFirst(Args args);
const char* name() const override { return kPickFirst; }
@ -155,7 +154,7 @@ class PickFirst : public LoadBalancingPolicy {
channelz::ChildRefsList child_channels_;
};
PickFirst::PickFirst(const Args& args) : LoadBalancingPolicy(args) {
PickFirst::PickFirst(Args args) : LoadBalancingPolicy(std::move(args)) {
GPR_ASSERT(args.client_channel_factory != nullptr);
gpr_mu_init(&child_refs_mu_);
grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE,
@ -164,7 +163,6 @@ PickFirst::PickFirst(const Args& args) : LoadBalancingPolicy(args) {
gpr_log(GPR_INFO, "Pick First %p created.", this);
}
UpdateLocked(*args.args, args.lb_config);
grpc_subchannel_index_ref();
}
PickFirst::~PickFirst() {
@ -176,7 +174,6 @@ PickFirst::~PickFirst() {
GPR_ASSERT(latest_pending_subchannel_list_ == nullptr);
GPR_ASSERT(pending_picks_ == nullptr);
grpc_connectivity_state_destroy(&state_tracker_);
grpc_subchannel_index_unref();
}
void PickFirst::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) {
@ -622,8 +619,8 @@ void PickFirst::PickFirstSubchannelData::
class PickFirstFactory : public LoadBalancingPolicyFactory {
public:
OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
const LoadBalancingPolicy::Args& args) const override {
return OrphanablePtr<LoadBalancingPolicy>(New<PickFirst>(args));
LoadBalancingPolicy::Args args) const override {
return OrphanablePtr<LoadBalancingPolicy>(New<PickFirst>(std::move(args)));
}
const char* name() const override { return kPickFirst; }

@ -33,7 +33,6 @@
#include "src/core/ext/filters/client_channel/lb_policy/subchannel_list.h"
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/ext/filters/client_channel/subchannel.h"
#include "src/core/ext/filters/client_channel/subchannel_index.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/mutex_lock.h"
@ -57,7 +56,7 @@ constexpr char kRoundRobin[] = "round_robin";
class RoundRobin : public LoadBalancingPolicy {
public:
explicit RoundRobin(const Args& args);
explicit RoundRobin(Args args);
const char* name() const override { return kRoundRobin; }
@ -211,7 +210,7 @@ class RoundRobin : public LoadBalancingPolicy {
channelz::ChildRefsList child_channels_;
};
RoundRobin::RoundRobin(const Args& args) : LoadBalancingPolicy(args) {
RoundRobin::RoundRobin(Args args) : LoadBalancingPolicy(std::move(args)) {
GPR_ASSERT(args.client_channel_factory != nullptr);
gpr_mu_init(&child_refs_mu_);
grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE,
@ -221,7 +220,6 @@ RoundRobin::RoundRobin(const Args& args) : LoadBalancingPolicy(args) {
gpr_log(GPR_INFO, "[RR %p] Created with %" PRIuPTR " subchannels", this,
subchannel_list_->num_subchannels());
}
grpc_subchannel_index_ref();
}
RoundRobin::~RoundRobin() {
@ -233,7 +231,6 @@ RoundRobin::~RoundRobin() {
GPR_ASSERT(latest_pending_subchannel_list_ == nullptr);
GPR_ASSERT(pending_picks_ == nullptr);
grpc_connectivity_state_destroy(&state_tracker_);
grpc_subchannel_index_unref();
}
void RoundRobin::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) {
@ -700,8 +697,8 @@ void RoundRobin::UpdateLocked(const grpc_channel_args& args,
class RoundRobinFactory : public LoadBalancingPolicyFactory {
public:
OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
const LoadBalancingPolicy::Args& args) const override {
return OrphanablePtr<LoadBalancingPolicy>(New<RoundRobin>(args));
LoadBalancingPolicy::Args args) const override {
return OrphanablePtr<LoadBalancingPolicy>(New<RoundRobin>(std::move(args)));
}
const char* name() const override { return kRoundRobin; }

@ -514,6 +514,9 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
// policy, which does not use a SubchannelList.
GPR_ASSERT(!addresses[i].IsBalancer());
InlinedVector<grpc_arg, 4> args_to_add;
args_to_add.emplace_back(
SubchannelPoolInterface::CreateChannelArg(policy_->subchannel_pool()));
const size_t subchannel_address_arg_index = args_to_add.size();
args_to_add.emplace_back(
grpc_create_subchannel_address_arg(&addresses[i].address()));
if (addresses[i].args() != nullptr) {
@ -524,7 +527,7 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
&args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove),
args_to_add.data(), args_to_add.size());
gpr_free(args_to_add[0].value.string);
gpr_free(args_to_add[subchannel_address_arg_index].value.string);
grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel(
client_channel_factory, new_args);
grpc_channel_args_destroy(new_args);

@ -80,7 +80,6 @@
#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/server_address.h"
#include "src/core/ext/filters/client_channel/subchannel_index.h"
#include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
@ -119,7 +118,7 @@ constexpr char kXds[] = "xds_experimental";
class XdsLb : public LoadBalancingPolicy {
public:
explicit XdsLb(const Args& args);
explicit XdsLb(Args args);
const char* name() const override { return kXds; }
@ -266,7 +265,7 @@ class XdsLb : public LoadBalancingPolicy {
// Methods for dealing with the child policy.
void CreateOrUpdateChildPolicyLocked();
grpc_channel_args* CreateChildPolicyArgsLocked();
void CreateChildPolicyLocked(const Args& args);
void CreateChildPolicyLocked(Args args);
bool PickFromChildPolicyLocked(bool force_async, PendingPick* pp,
grpc_error** error);
void UpdateConnectivityStateFromChildPolicyLocked(
@ -893,8 +892,8 @@ grpc_channel_args* BuildBalancerChannelArgs(
//
// TODO(vishalpowar): Use lb_config in args to configure LB policy.
XdsLb::XdsLb(const LoadBalancingPolicy::Args& args)
: LoadBalancingPolicy(args),
XdsLb::XdsLb(LoadBalancingPolicy::Args args)
: LoadBalancingPolicy(std::move(args)),
response_generator_(MakeRefCounted<FakeResolverResponseGenerator>()),
lb_call_backoff_(
BackOff::Options()
@ -905,7 +904,6 @@ XdsLb::XdsLb(const LoadBalancingPolicy::Args& args)
.set_max_backoff(GRPC_XDS_RECONNECT_MAX_BACKOFF_SECONDS * 1000)) {
// Initialization.
gpr_mu_init(&lb_channel_mu_);
grpc_subchannel_index_ref();
GRPC_CLOSURE_INIT(&lb_channel_on_connectivity_changed_,
&XdsLb::OnBalancerChannelConnectivityChangedLocked, this,
grpc_combiner_scheduler(args.combiner));
@ -949,7 +947,6 @@ XdsLb::~XdsLb() {
if (serverlist_ != nullptr) {
xds_grpclb_destroy_serverlist(serverlist_);
}
grpc_subchannel_index_unref();
}
void XdsLb::ShutdownLocked() {
@ -1439,10 +1436,10 @@ bool XdsLb::PickFromChildPolicyLocked(bool force_async, PendingPick* pp,
return pick_done;
}
void XdsLb::CreateChildPolicyLocked(const Args& args) {
void XdsLb::CreateChildPolicyLocked(Args args) {
GPR_ASSERT(child_policy_ == nullptr);
child_policy_ = LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
"round_robin", args);
"round_robin", std::move(args));
if (GPR_UNLIKELY(child_policy_ == nullptr)) {
gpr_log(GPR_ERROR, "[xdslb %p] Failure creating a child policy", this);
return;
@ -1526,8 +1523,9 @@ void XdsLb::CreateOrUpdateChildPolicyLocked() {
LoadBalancingPolicy::Args lb_policy_args;
lb_policy_args.combiner = combiner();
lb_policy_args.client_channel_factory = client_channel_factory();
lb_policy_args.subchannel_pool = subchannel_pool()->Ref();
lb_policy_args.args = args;
CreateChildPolicyLocked(lb_policy_args);
CreateChildPolicyLocked(std::move(lb_policy_args));
if (grpc_lb_xds_trace.enabled()) {
gpr_log(GPR_INFO, "[xdslb %p] Created a new child policy %p", this,
child_policy_.get());
@ -1639,7 +1637,7 @@ void XdsLb::OnChildPolicyConnectivityChangedLocked(void* arg,
class XdsFactory : public LoadBalancingPolicyFactory {
public:
OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
const LoadBalancingPolicy::Args& args) const override {
LoadBalancingPolicy::Args args) const override {
/* Count the number of gRPC-LB addresses. There must be at least one. */
const ServerAddressList* addresses =
FindServerAddressListChannelArg(args.args);
@ -1652,7 +1650,7 @@ class XdsFactory : public LoadBalancingPolicyFactory {
}
}
if (!found_balancer_address) return nullptr;
return OrphanablePtr<LoadBalancingPolicy>(New<XdsLb>(args));
return OrphanablePtr<LoadBalancingPolicy>(New<XdsLb>(std::move(args)));
}
const char* name() const override { return kXds; }

@ -31,7 +31,12 @@ class LoadBalancingPolicyFactory {
public:
/// Returns a new LB policy instance.
virtual OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
const LoadBalancingPolicy::Args& args) const GRPC_ABSTRACT;
LoadBalancingPolicy::Args args) const {
std::move(args); // Suppress clang-tidy complaint.
// The rest of this is copied from the GRPC_ABSTRACT macro.
gpr_log(GPR_ERROR, "Function marked GRPC_ABSTRACT was not implemented");
GPR_ASSERT(false);
}
/// Returns the LB policy name that this factory provides.
/// Caller does NOT take ownership of result.

@ -84,14 +84,14 @@ void LoadBalancingPolicyRegistry::Builder::RegisterLoadBalancingPolicyFactory(
OrphanablePtr<LoadBalancingPolicy>
LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
const char* name, const LoadBalancingPolicy::Args& args) {
const char* name, LoadBalancingPolicy::Args args) {
GPR_ASSERT(g_state != nullptr);
// Find factory.
LoadBalancingPolicyFactory* factory =
g_state->GetLoadBalancingPolicyFactory(name);
if (factory == nullptr) return nullptr; // Specified name not found.
// Create policy via factory.
return factory->CreateLoadBalancingPolicy(args);
return factory->CreateLoadBalancingPolicy(std::move(args));
}
bool LoadBalancingPolicyRegistry::LoadBalancingPolicyExists(const char* name) {

@ -46,7 +46,7 @@ class LoadBalancingPolicyRegistry {
/// Creates an LB policy of the type specified by \a name.
static OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
const char* name, const LoadBalancingPolicy::Args& args);
const char* name, LoadBalancingPolicy::Args args);
/// Returns true if the LB policy factory specified by \a name exists in this
/// registry.

@ -0,0 +1,96 @@
//
//
// Copyright 2018 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/local_subchannel_pool.h"
#include "src/core/ext/filters/client_channel/subchannel.h"
namespace grpc_core {
LocalSubchannelPool::LocalSubchannelPool() {
subchannel_map_ = grpc_avl_create(&subchannel_avl_vtable_);
}
LocalSubchannelPool::~LocalSubchannelPool() {
grpc_avl_unref(subchannel_map_, nullptr);
}
grpc_subchannel* LocalSubchannelPool::RegisterSubchannel(
SubchannelKey* key, grpc_subchannel* constructed) {
// Check to see if a subchannel already exists.
grpc_subchannel* c = static_cast<grpc_subchannel*>(
grpc_avl_get(subchannel_map_, key, nullptr));
if (c != nullptr) {
// The subchannel already exists. Reuse it.
c = GRPC_SUBCHANNEL_REF(c, "subchannel_register+reuse");
GRPC_SUBCHANNEL_UNREF(constructed, "subchannel_register+found_existing");
} else {
// There hasn't been such subchannel. Add one.
subchannel_map_ = grpc_avl_add(subchannel_map_, New<SubchannelKey>(*key),
constructed, nullptr);
c = constructed;
}
return c;
}
void LocalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) {
subchannel_map_ = grpc_avl_remove(subchannel_map_, key, nullptr);
}
grpc_subchannel* LocalSubchannelPool::FindSubchannel(SubchannelKey* key) {
grpc_subchannel* c = static_cast<grpc_subchannel*>(
grpc_avl_get(subchannel_map_, key, nullptr));
return c == nullptr ? c : GRPC_SUBCHANNEL_REF(c, "found_from_pool");
}
namespace {
void sck_avl_destroy(void* p, void* user_data) {
SubchannelKey* key = static_cast<SubchannelKey*>(p);
Delete(key);
}
void* sck_avl_copy(void* p, void* unused) {
const SubchannelKey* key = static_cast<const SubchannelKey*>(p);
auto new_key = New<SubchannelKey>(*key);
return static_cast<void*>(new_key);
}
long sck_avl_compare(void* a, void* b, void* unused) {
const SubchannelKey* key_a = static_cast<const SubchannelKey*>(a);
const SubchannelKey* key_b = static_cast<const SubchannelKey*>(b);
return key_a->Cmp(*key_b);
}
void scv_avl_destroy(void* p, void* user_data) {}
void* scv_avl_copy(void* p, void* unused) { return p; }
} // namespace
const grpc_avl_vtable LocalSubchannelPool::subchannel_avl_vtable_ = {
sck_avl_destroy, // destroy_key
sck_avl_copy, // copy_key
sck_avl_compare, // compare_keys
scv_avl_destroy, // destroy_value
scv_avl_copy // copy_value
};
} // namespace grpc_core

@ -0,0 +1,56 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LOCAL_SUBCHANNEL_POOL_H
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LOCAL_SUBCHANNEL_POOL_H
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
namespace grpc_core {
// The local subchannel pool that is owned by a single channel. It doesn't
// support subchannel sharing with other channels by nature. Nor does it support
// subchannel retention when a subchannel is not used. The only real purpose of
// using this subchannel pool is to allow subchannel reuse within the channel
// when an incoming resolver update contains some addresses for which the
// channel has already created subchannels.
// Thread-unsafe.
class LocalSubchannelPool final : public SubchannelPoolInterface {
public:
LocalSubchannelPool();
~LocalSubchannelPool() override;
// Implements interface methods.
// Thread-unsafe. Intended to be invoked within the client_channel combiner.
grpc_subchannel* RegisterSubchannel(SubchannelKey* key,
grpc_subchannel* constructed) override;
void UnregisterSubchannel(SubchannelKey* key) override;
grpc_subchannel* FindSubchannel(SubchannelKey* key) override;
private:
// The vtable for subchannel operations in an AVL tree.
static const grpc_avl_vtable subchannel_avl_vtable_;
// A map from subchannel key to subchannel.
grpc_avl subchannel_map_;
};
} // namespace grpc_core
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LOCAL_SUBCHANNEL_POOL_H */

@ -32,8 +32,10 @@
#include <grpc/support/sync.h>
#include "src/core/ext/filters/client_channel/backup_poller.h"
#include "src/core/ext/filters/client_channel/global_subchannel_pool.h"
#include "src/core/ext/filters/client_channel/http_connect_handshaker.h"
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/ext/filters/client_channel/local_subchannel_pool.h"
#include "src/core/ext/filters/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/filters/client_channel/resolver_registry.h"
#include "src/core/ext/filters/client_channel/retry_throttle.h"
@ -517,6 +519,14 @@ RequestRouter::RequestRouter(
tracer_(tracer),
process_resolver_result_(process_resolver_result),
process_resolver_result_user_data_(process_resolver_result_user_data) {
// Get subchannel pool.
const grpc_arg* arg =
grpc_channel_args_find(args, GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL);
if (grpc_channel_arg_get_bool(arg, false)) {
subchannel_pool_ = MakeRefCounted<LocalSubchannelPool>();
} else {
subchannel_pool_ = GlobalSubchannelPool::instance();
}
GRPC_CLOSURE_INIT(&on_resolver_result_changed_,
&RequestRouter::OnResolverResultChangedLocked, this,
grpc_combiner_scheduler(combiner));
@ -666,6 +676,7 @@ void RequestRouter::CreateNewLbPolicyLocked(
LoadBalancingPolicy::Args lb_policy_args;
lb_policy_args.combiner = combiner_;
lb_policy_args.client_channel_factory = client_channel_factory_;
lb_policy_args.subchannel_pool = subchannel_pool_;
lb_policy_args.args = resolver_result_;
lb_policy_args.lb_config = lb_config;
OrphanablePtr<LoadBalancingPolicy> new_lb_policy =
@ -751,9 +762,8 @@ void RequestRouter::ConcatenateAndAddChannelTraceLocked(
char* flat;
size_t flat_len = 0;
flat = gpr_strvec_flatten(&v, &flat_len);
channelz_node_->AddTraceEvent(
grpc_core::channelz::ChannelTrace::Severity::Info,
grpc_slice_new(flat, flat_len, gpr_free));
channelz_node_->AddTraceEvent(channelz::ChannelTrace::Severity::Info,
grpc_slice_new(flat, flat_len, gpr_free));
gpr_strvec_destroy(&v);
}
}

@ -25,6 +25,7 @@
#include "src/core/ext/filters/client_channel/client_channel_factory.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/subchannel_pool_interface.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/debug/trace.h"
@ -126,7 +127,7 @@ class RequestRouter {
LoadBalancingPolicy* lb_policy() const { return lb_policy_.get(); }
private:
using TraceStringVector = grpc_core::InlinedVector<char*, 3>;
using TraceStringVector = InlinedVector<char*, 3>;
class ReresolutionRequestHandler;
class LbConnectivityWatcher;
@ -169,6 +170,9 @@ class RequestRouter {
OrphanablePtr<LoadBalancingPolicy> lb_policy_;
bool exit_idle_when_lb_policy_arrives_ = false;
// Subchannel pool to pass to LB policy.
RefCountedPtr<SubchannelPoolInterface> subchannel_pool_;
grpc_connectivity_state_tracker state_tracker_;
};

@ -125,6 +125,8 @@ class AresDnsResolver : public Resolver {
bool shutdown_initiated_ = false;
// timeout in milliseconds for active DNS queries
int query_timeout_ms_;
// whether or not to enable SRV DNS queries
bool enable_srv_queries_;
};
AresDnsResolver::AresDnsResolver(const ResolverArgs& args)
@ -146,14 +148,18 @@ AresDnsResolver::AresDnsResolver(const ResolverArgs& args)
dns_server_ = gpr_strdup(args.uri->authority);
}
channel_args_ = grpc_channel_args_copy(args.args);
// Disable service config option
const grpc_arg* arg = grpc_channel_args_find(
channel_args_, GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION);
grpc_integer_options integer_options = {false, false, true};
request_service_config_ = !grpc_channel_arg_get_integer(arg, integer_options);
request_service_config_ = !grpc_channel_arg_get_bool(arg, false);
// Min time b/t resolutions option
arg = grpc_channel_args_find(channel_args_,
GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS);
min_time_between_resolutions_ =
grpc_channel_arg_get_integer(arg, {1000, 0, INT_MAX});
// Enable SRV queries option
arg = grpc_channel_args_find(channel_args_, GRPC_ARG_DNS_ENABLE_SRV_QUERIES);
enable_srv_queries_ = grpc_channel_arg_get_bool(arg, false);
interested_parties_ = grpc_pollset_set_create();
if (args.pollset_set != nullptr) {
grpc_pollset_set_add_pollset_set(interested_parties_, args.pollset_set);
@ -419,7 +425,7 @@ void AresDnsResolver::StartResolvingLocked() {
service_config_json_ = nullptr;
pending_request_ = grpc_dns_lookup_ares_locked(
dns_server_, name_to_resolve_, kDefaultPort, interested_parties_,
&on_resolved_, &addresses_, true /* check_grpclb */,
&on_resolved_, &addresses_, enable_srv_queries_ /* check_grpclb */,
request_service_config_ ? &service_config_json_ : nullptr,
query_timeout_ms_, combiner());
last_resolution_timestamp_ = grpc_core::ExecCtx::Get()->Now();
@ -472,13 +478,12 @@ static grpc_address_resolver_vtable ares_resolver = {
grpc_resolve_address_ares, blocking_resolve_address_ares};
static bool should_use_ares(const char* resolver_env) {
return resolver_env == nullptr || gpr_stricmp(resolver_env, "ares") == 0;
return resolver_env == nullptr || strlen(resolver_env) == 0 ||
gpr_stricmp(resolver_env, "ares") == 0;
}
void grpc_resolver_dns_ares_init() {
char* resolver_env = gpr_getenv("GRPC_DNS_RESOLVER");
/* TODO(zyc): Turn on c-ares based resolver by default after the address
sorter and the CNAME support are added. */
if (should_use_ares(resolver_env)) {
gpr_log(GPR_DEBUG, "Using ares dns resolver");
address_sorting_init();

@ -33,7 +33,7 @@
#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/proxy_mapper_registry.h"
#include "src/core/ext/filters/client_channel/subchannel_index.h"
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
#include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/connected_channel.h"
@ -80,6 +80,9 @@ class ConnectedSubchannelStateWatcher;
} // namespace grpc_core
struct grpc_subchannel {
/** The subchannel pool this subchannel is in */
grpc_core::RefCountedPtr<grpc_core::SubchannelPoolInterface> subchannel_pool;
grpc_connector* connector;
/** refcount
@ -92,7 +95,7 @@ struct grpc_subchannel {
/** channel arguments */
grpc_channel_args* args;
grpc_subchannel_key* key;
grpc_core::SubchannelKey* key;
/** set during connection */
grpc_connect_out_args connecting_result;
@ -375,7 +378,7 @@ static void subchannel_destroy(void* arg, grpc_error* error) {
grpc_connectivity_state_destroy(&c->state_and_health_tracker);
grpc_connector_unref(c->connector);
grpc_pollset_set_destroy(c->pollset_set);
grpc_subchannel_key_destroy(c->key);
grpc_core::Delete(c->key);
gpr_mu_destroy(&c->mu);
gpr_free(c);
}
@ -428,7 +431,12 @@ grpc_subchannel* grpc_subchannel_ref_from_weak_ref(
}
static void disconnect(grpc_subchannel* c) {
grpc_subchannel_index_unregister(c->key, c);
// The subchannel_pool is only used once here in this subchannel, so the
// access can be outside of the lock.
if (c->subchannel_pool != nullptr) {
c->subchannel_pool->UnregisterSubchannel(c->key);
c->subchannel_pool.reset();
}
gpr_mu_lock(&c->mu);
GPR_ASSERT(!c->disconnected);
c->disconnected = true;
@ -538,13 +546,17 @@ struct HealthCheckParams {
grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
const grpc_channel_args* args) {
grpc_subchannel_key* key = grpc_subchannel_key_create(args);
grpc_subchannel* c = grpc_subchannel_index_find(key);
if (c) {
grpc_subchannel_key_destroy(key);
grpc_core::SubchannelKey* key =
grpc_core::New<grpc_core::SubchannelKey>(args);
grpc_core::SubchannelPoolInterface* subchannel_pool =
grpc_core::SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs(
args);
GPR_ASSERT(subchannel_pool != nullptr);
grpc_subchannel* c = subchannel_pool->FindSubchannel(key);
if (c != nullptr) {
grpc_core::Delete(key);
return c;
}
GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED();
c = static_cast<grpc_subchannel*>(gpr_zalloc(sizeof(*c)));
c->key = key;
@ -616,8 +628,13 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
grpc_core::channelz::ChannelTrace::Severity::Info,
grpc_slice_from_static_string("Subchannel created"));
}
return grpc_subchannel_index_register(key, c);
// Try to register the subchannel before setting the subchannel pool.
// Otherwise, in case of a registration race, unreffing c in
// RegisterSubchannel() will cause c to be tried to be unregistered, while its
// key maps to a different subchannel.
grpc_subchannel* registered = subchannel_pool->RegisterSubchannel(key, c);
if (registered == c) c->subchannel_pool = subchannel_pool->Ref();
return registered;
}
grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node(
@ -983,11 +1000,6 @@ grpc_subchannel_get_connected_subchannel(grpc_subchannel* c) {
return copy;
}
const grpc_subchannel_key* grpc_subchannel_get_key(
const grpc_subchannel* subchannel) {
return subchannel->key;
}
void* grpc_connected_subchannel_call_get_parent_data(
grpc_subchannel_call* subchannel_call) {
grpc_channel_stack* chanstk = subchannel_call->connection->channel_stack();

@ -23,6 +23,7 @@
#include "src/core/ext/filters/client_channel/client_channel_channelz.h"
#include "src/core/ext/filters/client_channel/connector.h"
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/gpr/arena.h"
#include "src/core/lib/gprpp/ref_counted.h"
@ -38,7 +39,6 @@
address. Provides a target for load balancing. */
typedef struct grpc_subchannel grpc_subchannel;
typedef struct grpc_subchannel_call grpc_subchannel_call;
typedef struct grpc_subchannel_key grpc_subchannel_key;
#ifndef NDEBUG
#define GRPC_SUBCHANNEL_REF(p, r) \
@ -162,10 +162,6 @@ void grpc_subchannel_notify_on_state_change(
grpc_core::RefCountedPtr<grpc_core::ConnectedSubchannel>
grpc_subchannel_get_connected_subchannel(grpc_subchannel* c);
/** return the subchannel index key for \a subchannel */
const grpc_subchannel_key* grpc_subchannel_get_key(
const grpc_subchannel* subchannel);
// Resets the connection backoff of the subchannel.
// TODO(roth): Move connection backoff out of subchannels and up into LB
// policy code (probably by adding a SubchannelGroup between

@ -42,8 +42,6 @@ struct grpc_subchannel_key {
grpc_channel_args* args;
};
static bool g_force_creation = false;
static grpc_subchannel_key* create_key(
const grpc_channel_args* args,
grpc_channel_args* (*copy_channel_args)(const grpc_channel_args* args)) {
@ -63,8 +61,6 @@ static grpc_subchannel_key* subchannel_key_copy(grpc_subchannel_key* k) {
int grpc_subchannel_key_compare(const grpc_subchannel_key* a,
const grpc_subchannel_key* b) {
// To pretend the keys are different, return a non-zero value.
if (GPR_UNLIKELY(g_force_creation)) return 1;
return grpc_channel_args_compare(a->args, b->args);
}
@ -224,7 +220,3 @@ void grpc_subchannel_index_unregister(grpc_subchannel_key* key,
grpc_avl_unref(index, nullptr);
}
}
void grpc_subchannel_index_test_only_set_force_creation(bool force_creation) {
g_force_creation = force_creation;
}

@ -63,13 +63,4 @@ void grpc_subchannel_index_ref(void);
to zero, unref the subchannel index and destroy its mutex. */
void grpc_subchannel_index_unref(void);
/** \em TEST ONLY.
* If \a force_creation is true, all keys are regarded different, resulting in
* new subchannels always being created. Otherwise, the keys will be compared as
* usual.
*
* Tests using this function \em MUST run tests with and without \a
* force_creation set. */
void grpc_subchannel_index_test_only_set_force_creation(bool force_creation);
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_INDEX_H */

@ -0,0 +1,97 @@
//
//
// Copyright 2018 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
#include "src/core/lib/gpr/useful.h"
// The subchannel pool to reuse subchannels.
#define GRPC_ARG_SUBCHANNEL_POOL "grpc.subchannel_pool"
// The subchannel key ID that is only used in test to make each key unique.
#define GRPC_ARG_SUBCHANNEL_KEY_TEST_ONLY_ID "grpc.subchannel_key_test_only_id"
namespace grpc_core {
TraceFlag grpc_subchannel_pool_trace(false, "subchannel_pool");
SubchannelKey::SubchannelKey(const grpc_channel_args* args) {
Init(args, grpc_channel_args_normalize);
}
SubchannelKey::~SubchannelKey() {
grpc_channel_args_destroy(const_cast<grpc_channel_args*>(args_));
}
SubchannelKey::SubchannelKey(const SubchannelKey& other) {
Init(other.args_, grpc_channel_args_copy);
}
SubchannelKey& SubchannelKey::operator=(const SubchannelKey& other) {
grpc_channel_args_destroy(const_cast<grpc_channel_args*>(args_));
Init(other.args_, grpc_channel_args_copy);
return *this;
}
int SubchannelKey::Cmp(const SubchannelKey& other) const {
return grpc_channel_args_compare(args_, other.args_);
}
void SubchannelKey::Init(
const grpc_channel_args* args,
grpc_channel_args* (*copy_channel_args)(const grpc_channel_args* args)) {
args_ = copy_channel_args(args);
}
namespace {
void* arg_copy(void* p) {
auto* subchannel_pool = static_cast<SubchannelPoolInterface*>(p);
subchannel_pool->Ref().release();
return p;
}
void arg_destroy(void* p) {
auto* subchannel_pool = static_cast<SubchannelPoolInterface*>(p);
subchannel_pool->Unref();
}
int arg_cmp(void* a, void* b) { return GPR_ICMP(a, b); }
const grpc_arg_pointer_vtable subchannel_pool_arg_vtable = {
arg_copy, arg_destroy, arg_cmp};
} // namespace
grpc_arg SubchannelPoolInterface::CreateChannelArg(
SubchannelPoolInterface* subchannel_pool) {
return grpc_channel_arg_pointer_create(
const_cast<char*>(GRPC_ARG_SUBCHANNEL_POOL), subchannel_pool,
&subchannel_pool_arg_vtable);
}
SubchannelPoolInterface*
SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs(
const grpc_channel_args* args) {
const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_POOL);
if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr;
return static_cast<SubchannelPoolInterface*>(arg->value.pointer.p);
}
} // namespace grpc_core

@ -0,0 +1,94 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_POOL_INTERFACE_H
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_POOL_INTERFACE_H
#include <grpc/support/port_platform.h>
#include "src/core/lib/avl/avl.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gprpp/abstract.h"
#include "src/core/lib/gprpp/ref_counted.h"
struct grpc_subchannel;
namespace grpc_core {
extern TraceFlag grpc_subchannel_pool_trace;
// A key that can uniquely identify a subchannel.
class SubchannelKey {
public:
explicit SubchannelKey(const grpc_channel_args* args);
~SubchannelKey();
// Copyable.
SubchannelKey(const SubchannelKey& other);
SubchannelKey& operator=(const SubchannelKey& other);
// Not movable.
SubchannelKey(SubchannelKey&&) = delete;
SubchannelKey& operator=(SubchannelKey&&) = delete;
int Cmp(const SubchannelKey& other) const;
private:
// Initializes the subchannel key with the given \a args and the function to
// copy channel args.
void Init(
const grpc_channel_args* args,
grpc_channel_args* (*copy_channel_args)(const grpc_channel_args* args));
const grpc_channel_args* args_;
};
// Interface for subchannel pool.
// TODO(juanlishen): This refcounting mechanism may lead to memory leak.
// To solve that, we should force polling to flush any pending callbacks, then
// shut down safely. See https://github.com/grpc/grpc/issues/12560.
class SubchannelPoolInterface : public RefCounted<SubchannelPoolInterface> {
public:
SubchannelPoolInterface() : RefCounted(&grpc_subchannel_pool_trace) {}
virtual ~SubchannelPoolInterface() {}
// Registers a subchannel against a key. Returns the subchannel registered
// with \a key, which may be different from \a constructed because we reuse
// (instead of update) any existing subchannel already registered with \a key.
virtual grpc_subchannel* RegisterSubchannel(
SubchannelKey* key, grpc_subchannel* constructed) GRPC_ABSTRACT;
// Removes the registered subchannel found by \a key.
virtual void UnregisterSubchannel(SubchannelKey* key) GRPC_ABSTRACT;
// Finds the subchannel registered for the given subchannel key. Returns NULL
// if no such channel exists. Thread-safe.
virtual grpc_subchannel* FindSubchannel(SubchannelKey* key) GRPC_ABSTRACT;
// Creates a channel arg from \a subchannel pool.
static grpc_arg CreateChannelArg(SubchannelPoolInterface* subchannel_pool);
// Gets the subchannel pool from the channel args.
static SubchannelPoolInterface* GetSubchannelPoolFromChannelArgs(
const grpc_channel_args* args);
GRPC_ABSTRACT_BASE_CLASS
};
} // namespace grpc_core
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_POOL_INTERFACE_H */

@ -45,6 +45,7 @@ struct call_data {
struct channel_data {
grpc_slice default_authority;
grpc_mdelem default_authority_mdelem;
};
void authority_start_transport_stream_op_batch(
@ -59,8 +60,7 @@ void authority_start_transport_stream_op_batch(
initial_metadata->idx.named.authority == nullptr) {
grpc_error* error = grpc_metadata_batch_add_head(
initial_metadata, &calld->authority_storage,
grpc_mdelem_create(GRPC_MDSTR_AUTHORITY, chand->default_authority,
nullptr));
GRPC_MDELEM_REF(chand->default_authority_mdelem));
if (error != GRPC_ERROR_NONE) {
grpc_transport_stream_op_batch_finish_with_failure(batch, error,
calld->call_combiner);
@ -103,6 +103,8 @@ grpc_error* init_channel_elem(grpc_channel_element* elem,
}
chand->default_authority =
grpc_slice_intern(grpc_slice_from_static_string(default_authority_str));
chand->default_authority_mdelem = grpc_mdelem_create(
GRPC_MDSTR_AUTHORITY, chand->default_authority, nullptr);
GPR_ASSERT(!args->is_last);
return GRPC_ERROR_NONE;
}
@ -111,6 +113,7 @@ grpc_error* init_channel_elem(grpc_channel_element* elem,
void destroy_channel_elem(grpc_channel_element* elem) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
grpc_slice_unref_internal(chand->default_authority);
GRPC_MDELEM_UNREF(chand->default_authority_mdelem);
}
} // namespace

@ -205,6 +205,7 @@ grpc_channel* grpc_secure_channel_create(grpc_channel_credentials* creds,
grpc_channel_credentials_to_arg(creds)};
grpc_channel_args* new_args = grpc_channel_args_copy_and_add(
args, args_to_add, GPR_ARRAY_SIZE(args_to_add));
new_args = creds->update_arguments(new_args);
// Create channel.
channel = client_channel_factory_create_channel(
&client_channel_factory, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR,

@ -968,19 +968,19 @@ static grpc_closure_scheduler* write_scheduler(grpc_chttp2_transport* t,
get better latency overall if we switch writing work elsewhere and continue
with application work above */
if (!t->is_first_write_in_batch) {
return grpc_executor_scheduler(GRPC_EXECUTOR_SHORT);
return grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT);
}
/* equivalently, if it's a partial write, we *know* we're going to be taking a
thread jump to write it because of the above, may as well do so
immediately */
if (partial_write) {
return grpc_executor_scheduler(GRPC_EXECUTOR_SHORT);
return grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT);
}
switch (t->opt_target) {
case GRPC_CHTTP2_OPTIMIZE_FOR_THROUGHPUT:
/* executor gives us the largest probability of being able to batch a
* write with others on this transport */
return grpc_executor_scheduler(GRPC_EXECUTOR_SHORT);
return grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT);
case GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY:
return grpc_schedule_on_exec_ctx;
}

@ -24,6 +24,7 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include <inttypes.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
@ -83,7 +84,7 @@ void gpr_default_log(gpr_log_func_args* args) {
}
char* prefix;
gpr_asprintf(&prefix, "%s%s.%09d %7tu %s:%d]",
gpr_asprintf(&prefix, "%s%s.%09d %7" PRIdPTR " %s:%d]",
gpr_log_severity_string(args->severity), time_buffer,
(int)(now.tv_nsec), gettid(), display_file, args->line);

@ -0,0 +1,47 @@
/*
*
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPC_CORE_LIB_GPRPP_OPTIONAL_H
#define GRPC_CORE_LIB_GPRPP_OPTIONAL_H
namespace grpc_core {
/* A make-shift alternative for absl::Optional. This can be removed in favor of
* that once absl dependencies can be introduced. */
template <typename T>
class Optional {
public:
void set(const T& val) {
value_ = val;
set_ = true;
}
bool has_value() { return set_; }
void reset() { set_ = false; }
T value() { return value_; }
private:
T value_;
bool set_ = false;
};
} /* namespace grpc_core */
#endif /* GRPC_CORE_LIB_GPRPP_OPTIONAL_H */

@ -24,32 +24,13 @@
#include <grpc/support/log.h>
#ifdef GRPC_LINUX_ERRQUEUE
#include <netinet/in.h>
#include <string.h>
#include <time.h>
#include "src/core/lib/gprpp/memory.h"
namespace grpc_core {
void TracedBuffer::AddNewEntry(TracedBuffer** head, uint32_t seq_no,
void* arg) {
GPR_DEBUG_ASSERT(head != nullptr);
TracedBuffer* new_elem = New<TracedBuffer>(seq_no, arg);
/* Store the current time as the sendmsg time. */
new_elem->ts_.sendmsg_time = gpr_now(GPR_CLOCK_REALTIME);
new_elem->ts_.scheduled_time = gpr_inf_past(GPR_CLOCK_REALTIME);
new_elem->ts_.sent_time = gpr_inf_past(GPR_CLOCK_REALTIME);
new_elem->ts_.acked_time = gpr_inf_past(GPR_CLOCK_REALTIME);
if (*head == nullptr) {
*head = new_elem;
return;
}
/* Append at the end. */
TracedBuffer* ptr = *head;
while (ptr->next_ != nullptr) {
ptr = ptr->next_;
}
ptr->next_ = new_elem;
}
namespace {
/** Fills gpr_timespec gts based on values from timespec ts */
void fill_gpr_from_timestamp(gpr_timespec* gts, const struct timespec* ts) {
@ -68,10 +49,180 @@ void default_timestamps_callback(void* arg, grpc_core::Timestamps* ts,
void (*timestamps_callback)(void*, grpc_core::Timestamps*,
grpc_error* shutdown_err) =
default_timestamps_callback;
/* Used to extract individual opt stats from cmsg, so as to avoid troubles with
* unaligned reads */
template <typename T>
T read_unaligned(const void* ptr) {
T val;
memcpy(&val, ptr, sizeof(val));
return val;
}
/* Extracts opt stats from the tcp_info struct \a info to \a metrics */
void extract_opt_stats_from_tcp_info(ConnectionMetrics* metrics,
const grpc_core::tcp_info* info) {
if (info == nullptr) {
return;
}
if (info->length > offsetof(grpc_core::tcp_info, tcpi_sndbuf_limited)) {
metrics->recurring_retrans.set(info->tcpi_retransmits);
metrics->is_delivery_rate_app_limited.set(
info->tcpi_delivery_rate_app_limited);
metrics->congestion_window.set(info->tcpi_snd_cwnd);
metrics->reordering.set(info->tcpi_reordering);
metrics->packet_retx.set(info->tcpi_total_retrans);
metrics->pacing_rate.set(info->tcpi_pacing_rate);
metrics->data_notsent.set(info->tcpi_notsent_bytes);
if (info->tcpi_min_rtt != UINT32_MAX) {
metrics->min_rtt.set(info->tcpi_min_rtt);
}
metrics->packet_sent.set(info->tcpi_data_segs_out);
metrics->delivery_rate.set(info->tcpi_delivery_rate);
metrics->busy_usec.set(info->tcpi_busy_time);
metrics->rwnd_limited_usec.set(info->tcpi_rwnd_limited);
metrics->sndbuf_limited_usec.set(info->tcpi_sndbuf_limited);
}
if (info->length > offsetof(grpc_core::tcp_info, tcpi_dsack_dups)) {
metrics->data_sent.set(info->tcpi_bytes_sent);
metrics->data_retx.set(info->tcpi_bytes_retrans);
metrics->packet_spurious_retx.set(info->tcpi_dsack_dups);
}
}
/** Extracts opt stats from the given control message \a opt_stats to the
* connection metrics \a metrics */
void extract_opt_stats_from_cmsg(ConnectionMetrics* metrics,
const cmsghdr* opt_stats) {
if (opt_stats == nullptr) {
return;
}
const auto* data = CMSG_DATA(opt_stats);
constexpr int64_t cmsg_hdr_len = CMSG_ALIGN(sizeof(struct cmsghdr));
const int64_t len = opt_stats->cmsg_len - cmsg_hdr_len;
int64_t offset = 0;
while (offset < len) {
const auto* attr = reinterpret_cast<const nlattr*>(data + offset);
const void* val = data + offset + NLA_HDRLEN;
switch (attr->nla_type) {
case TCP_NLA_BUSY: {
metrics->busy_usec.set(read_unaligned<uint64_t>(val));
break;
}
case TCP_NLA_RWND_LIMITED: {
metrics->rwnd_limited_usec.set(read_unaligned<uint64_t>(val));
break;
}
case TCP_NLA_SNDBUF_LIMITED: {
metrics->sndbuf_limited_usec.set(read_unaligned<uint64_t>(val));
break;
}
case TCP_NLA_PACING_RATE: {
metrics->pacing_rate.set(read_unaligned<uint64_t>(val));
break;
}
case TCP_NLA_DELIVERY_RATE: {
metrics->delivery_rate.set(read_unaligned<uint64_t>(val));
break;
}
case TCP_NLA_DELIVERY_RATE_APP_LMT: {
metrics->is_delivery_rate_app_limited.set(read_unaligned<uint8_t>(val));
break;
}
case TCP_NLA_SND_CWND: {
metrics->congestion_window.set(read_unaligned<uint32_t>(val));
break;
}
case TCP_NLA_MIN_RTT: {
metrics->min_rtt.set(read_unaligned<uint32_t>(val));
break;
}
case TCP_NLA_SRTT: {
metrics->srtt.set(read_unaligned<uint32_t>(val));
break;
}
case TCP_NLA_RECUR_RETRANS: {
metrics->recurring_retrans.set(read_unaligned<uint8_t>(val));
break;
}
case TCP_NLA_BYTES_SENT: {
metrics->data_sent.set(read_unaligned<uint64_t>(val));
break;
}
case TCP_NLA_DATA_SEGS_OUT: {
metrics->packet_sent.set(read_unaligned<uint64_t>(val));
break;
}
case TCP_NLA_TOTAL_RETRANS: {
metrics->packet_retx.set(read_unaligned<uint64_t>(val));
break;
}
case TCP_NLA_DELIVERED: {
metrics->packet_delivered.set(read_unaligned<uint32_t>(val));
break;
}
case TCP_NLA_DELIVERED_CE: {
metrics->packet_delivered_ce.set(read_unaligned<uint32_t>(val));
break;
}
case TCP_NLA_BYTES_RETRANS: {
metrics->data_retx.set(read_unaligned<uint64_t>(val));
break;
}
case TCP_NLA_DSACK_DUPS: {
metrics->packet_spurious_retx.set(read_unaligned<uint32_t>(val));
break;
}
case TCP_NLA_REORDERING: {
metrics->reordering.set(read_unaligned<uint32_t>(val));
break;
}
case TCP_NLA_SND_SSTHRESH: {
metrics->snd_ssthresh.set(read_unaligned<uint32_t>(val));
break;
}
}
offset += NLA_ALIGN(attr->nla_len);
}
}
static int get_socket_tcp_info(grpc_core::tcp_info* info, int fd) {
info->length = sizeof(*info) - sizeof(socklen_t);
memset(info, 0, sizeof(*info));
return getsockopt(fd, IPPROTO_TCP, TCP_INFO, info, &(info->length));
}
} /* namespace */
void TracedBuffer::AddNewEntry(TracedBuffer** head, uint32_t seq_no, int fd,
void* arg) {
GPR_DEBUG_ASSERT(head != nullptr);
TracedBuffer* new_elem = New<TracedBuffer>(seq_no, arg);
/* Store the current time as the sendmsg time. */
new_elem->ts_.sendmsg_time.time = gpr_now(GPR_CLOCK_REALTIME);
new_elem->ts_.scheduled_time.time = gpr_inf_past(GPR_CLOCK_REALTIME);
new_elem->ts_.sent_time.time = gpr_inf_past(GPR_CLOCK_REALTIME);
new_elem->ts_.acked_time.time = gpr_inf_past(GPR_CLOCK_REALTIME);
if (get_socket_tcp_info(&new_elem->ts_.info, fd) == 0) {
extract_opt_stats_from_tcp_info(&new_elem->ts_.sendmsg_time.metrics,
&new_elem->ts_.info);
}
if (*head == nullptr) {
*head = new_elem;
return;
}
/* Append at the end. */
TracedBuffer* ptr = *head;
while (ptr->next_ != nullptr) {
ptr = ptr->next_;
}
ptr->next_ = new_elem;
}
void TracedBuffer::ProcessTimestamp(TracedBuffer** head,
struct sock_extended_err* serr,
struct cmsghdr* opt_stats,
struct scm_timestamping* tss) {
GPR_DEBUG_ASSERT(head != nullptr);
TracedBuffer* elem = *head;
@ -82,15 +233,22 @@ void TracedBuffer::ProcessTimestamp(TracedBuffer** head,
if (serr->ee_data >= elem->seq_no_) {
switch (serr->ee_info) {
case SCM_TSTAMP_SCHED:
fill_gpr_from_timestamp(&(elem->ts_.scheduled_time), &(tss->ts[0]));
fill_gpr_from_timestamp(&(elem->ts_.scheduled_time.time),
&(tss->ts[0]));
extract_opt_stats_from_cmsg(&(elem->ts_.scheduled_time.metrics),
opt_stats);
elem = elem->next_;
break;
case SCM_TSTAMP_SND:
fill_gpr_from_timestamp(&(elem->ts_.sent_time), &(tss->ts[0]));
fill_gpr_from_timestamp(&(elem->ts_.sent_time.time), &(tss->ts[0]));
extract_opt_stats_from_cmsg(&(elem->ts_.sent_time.metrics),
opt_stats);
elem = elem->next_;
break;
case SCM_TSTAMP_ACK:
fill_gpr_from_timestamp(&(elem->ts_.acked_time), &(tss->ts[0]));
fill_gpr_from_timestamp(&(elem->ts_.acked_time.time), &(tss->ts[0]));
extract_opt_stats_from_cmsg(&(elem->ts_.acked_time.metrics),
opt_stats);
/* Got all timestamps. Do the callback and free this TracedBuffer.
* The thing below can be passed by value if we don't want the
* restriction on the lifetime. */

@ -26,19 +26,78 @@
#include <grpc/support/time.h>
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/optional.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/internal_errqueue.h"
namespace grpc_core {
struct ConnectionMetrics {
/* Delivery rate in Bytes/s. */
Optional<uint64_t> delivery_rate;
/* If the delivery rate is limited by the application, this is set to true. */
Optional<bool> is_delivery_rate_app_limited;
/* Total packets retransmitted. */
Optional<uint32_t> packet_retx;
/* Total packets retransmitted spuriously. This metric is smaller than or
equal to packet_retx. */
Optional<uint32_t> packet_spurious_retx;
/* Total packets sent. */
Optional<uint32_t> packet_sent;
/* Total packets delivered. */
Optional<uint32_t> packet_delivered;
/* Total packets delivered with ECE marked. This metric is smaller than or
equal to packet_delivered. */
Optional<uint32_t> packet_delivered_ce;
/* Total bytes lost so far. */
Optional<uint64_t> data_retx;
/* Total bytes sent so far. */
Optional<uint64_t> data_sent;
/* Total bytes in write queue but not sent. */
Optional<uint64_t> data_notsent;
/* Pacing rate of the connection in Bps */
Optional<uint64_t> pacing_rate;
/* Minimum RTT observed in usec. */
Optional<uint32_t> min_rtt;
/* Smoothed RTT in usec */
Optional<uint32_t> srtt;
/* Send congestion window. */
Optional<uint32_t> congestion_window;
/* Slow start threshold in packets. */
Optional<uint32_t> snd_ssthresh;
/* Maximum degree of reordering (i.e., maximum number of packets reodered)
on the connection. */
Optional<uint32_t> reordering;
/* Represents the number of recurring retransmissions of the first sequence
that is not acknowledged yet. */
Optional<uint8_t> recurring_retrans;
/* The cumulative time (in usec) that the transport protocol was busy
sending data. */
Optional<uint64_t> busy_usec;
/* The cumulative time (in usec) that the transport protocol was limited by
the receive window size. */
Optional<uint64_t> rwnd_limited_usec;
/* The cumulative time (in usec) that the transport protocol was limited by
the send buffer size. */
Optional<uint64_t> sndbuf_limited_usec;
};
struct Timestamp {
gpr_timespec time;
ConnectionMetrics metrics; /* Metrics collected with this timestamp */
};
struct Timestamps {
/* TODO(yashykt): This would also need to store OPTSTAT once support is added
*/
gpr_timespec sendmsg_time;
gpr_timespec scheduled_time;
gpr_timespec sent_time;
gpr_timespec acked_time;
Timestamp sendmsg_time;
Timestamp scheduled_time;
Timestamp sent_time;
Timestamp acked_time;
uint32_t byte_offset; /* byte offset relative to the start of the RPC */
#ifdef GRPC_LINUX_ERRQUEUE
grpc_core::tcp_info info; /* tcp_info collected on sendmsg */
#endif /* GRPC_LINUX_ERRQUEUE */
};
/** TracedBuffer is a class to keep track of timestamps for a specific buffer in
@ -58,13 +117,14 @@ class TracedBuffer {
/** Add a new entry in the TracedBuffer list pointed to by head. Also saves
* sendmsg_time with the current timestamp. */
static void AddNewEntry(grpc_core::TracedBuffer** head, uint32_t seq_no,
void* arg);
int fd, void* arg);
/** Processes a received timestamp based on sock_extended_err and
* scm_timestamping structures. It will invoke the timestamps callback if the
* timestamp type is SCM_TSTAMP_ACK. */
static void ProcessTimestamp(grpc_core::TracedBuffer** head,
struct sock_extended_err* serr,
struct cmsghdr* opt_stats,
struct scm_timestamping* tss);
/** Cleans the list by calling the callback for each traced buffer in the list

@ -83,8 +83,9 @@ grpc_combiner* grpc_combiner_create(void) {
gpr_atm_no_barrier_store(&lock->state, STATE_UNORPHANED);
gpr_mpscq_init(&lock->queue);
grpc_closure_list_init(&lock->final_list);
GRPC_CLOSURE_INIT(&lock->offload, offload, lock,
grpc_executor_scheduler(GRPC_EXECUTOR_SHORT));
GRPC_CLOSURE_INIT(
&lock->offload, offload, lock,
grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT));
GRPC_COMBINER_TRACE(gpr_log(GPR_INFO, "C:%p create", lock));
return lock;
}
@ -235,7 +236,7 @@ bool grpc_combiner_continue_exec_ctx() {
// 3. the DEFAULT executor is threaded
// 4. the current thread is not a worker for any background poller
if (contended && grpc_core::ExecCtx::Get()->IsReadyToFinish() &&
grpc_executor_is_threaded() &&
grpc_core::Executor::IsThreadedDefault() &&
!grpc_iomgr_is_any_background_poller_thread()) {
GPR_TIMER_MARK("offload_from_finished_exec_ctx", 0);
// this execution context wants to move on: schedule remaining work to be

@ -765,7 +765,7 @@ grpc_error* grpc_os_error(const char* file, int line, int err,
grpc_error_set_str(
grpc_error_set_int(
grpc_error_create(file, line,
grpc_slice_from_static_string("OS Error"),
grpc_slice_from_static_string(strerror(err)),
nullptr, 0),
GRPC_ERROR_INT_ERRNO, err),
GRPC_ERROR_STR_OS_ERROR,

@ -45,20 +45,70 @@
gpr_log(GPR_INFO, "EXECUTOR " str); \
}
grpc_core::TraceFlag executor_trace(false, "executor");
namespace grpc_core {
namespace {
GPR_TLS_DECL(g_this_thread_state);
GrpcExecutor::GrpcExecutor(const char* name) : name_(name) {
Executor* executors[static_cast<size_t>(ExecutorType::NUM_EXECUTORS)];
void default_enqueue_short(grpc_closure* closure, grpc_error* error) {
executors[static_cast<size_t>(ExecutorType::DEFAULT)]->Enqueue(
closure, error, true /* is_short */);
}
void default_enqueue_long(grpc_closure* closure, grpc_error* error) {
executors[static_cast<size_t>(ExecutorType::DEFAULT)]->Enqueue(
closure, error, false /* is_short */);
}
void resolver_enqueue_short(grpc_closure* closure, grpc_error* error) {
executors[static_cast<size_t>(ExecutorType::RESOLVER)]->Enqueue(
closure, error, true /* is_short */);
}
void resolver_enqueue_long(grpc_closure* closure, grpc_error* error) {
executors[static_cast<size_t>(ExecutorType::RESOLVER)]->Enqueue(
closure, error, false /* is_short */);
}
const grpc_closure_scheduler_vtable
vtables_[static_cast<size_t>(ExecutorType::NUM_EXECUTORS)]
[static_cast<size_t>(ExecutorJobType::NUM_JOB_TYPES)] = {
{{&default_enqueue_short, &default_enqueue_short,
"def-ex-short"},
{&default_enqueue_long, &default_enqueue_long, "def-ex-long"}},
{{&resolver_enqueue_short, &resolver_enqueue_short,
"res-ex-short"},
{&resolver_enqueue_long, &resolver_enqueue_long,
"res-ex-long"}}};
grpc_closure_scheduler
schedulers_[static_cast<size_t>(ExecutorType::NUM_EXECUTORS)]
[static_cast<size_t>(ExecutorJobType::NUM_JOB_TYPES)] = {
{{&vtables_[static_cast<size_t>(ExecutorType::DEFAULT)]
[static_cast<size_t>(ExecutorJobType::SHORT)]},
{&vtables_[static_cast<size_t>(ExecutorType::DEFAULT)]
[static_cast<size_t>(ExecutorJobType::LONG)]}},
{{&vtables_[static_cast<size_t>(ExecutorType::RESOLVER)]
[static_cast<size_t>(ExecutorJobType::SHORT)]},
{&vtables_[static_cast<size_t>(ExecutorType::RESOLVER)]
[static_cast<size_t>(ExecutorJobType::LONG)]}}};
} // namespace
TraceFlag executor_trace(false, "executor");
Executor::Executor(const char* name) : name_(name) {
adding_thread_lock_ = GPR_SPINLOCK_STATIC_INITIALIZER;
gpr_atm_rel_store(&num_threads_, 0);
max_threads_ = GPR_MAX(1, 2 * gpr_cpu_num_cores());
}
void GrpcExecutor::Init() { SetThreading(true); }
void Executor::Init() { SetThreading(true); }
size_t GrpcExecutor::RunClosures(const char* executor_name,
grpc_closure_list list) {
size_t Executor::RunClosures(const char* executor_name,
grpc_closure_list list) {
size_t n = 0;
grpc_closure* c = list.head;
@ -82,11 +132,11 @@ size_t GrpcExecutor::RunClosures(const char* executor_name,
return n;
}
bool GrpcExecutor::IsThreaded() const {
bool Executor::IsThreaded() const {
return gpr_atm_acq_load(&num_threads_) > 0;
}
void GrpcExecutor::SetThreading(bool threading) {
void Executor::SetThreading(bool threading) {
gpr_atm curr_num_threads = gpr_atm_acq_load(&num_threads_);
EXECUTOR_TRACE("(%s) SetThreading(%d) begin", name_, threading);
@ -112,7 +162,7 @@ void GrpcExecutor::SetThreading(bool threading) {
}
thd_state_[0].thd =
grpc_core::Thread(name_, &GrpcExecutor::ThreadMain, &thd_state_[0]);
grpc_core::Thread(name_, &Executor::ThreadMain, &thd_state_[0]);
thd_state_[0].thd.Start();
} else { // !threading
if (curr_num_threads == 0) {
@ -153,9 +203,9 @@ void GrpcExecutor::SetThreading(bool threading) {
EXECUTOR_TRACE("(%s) SetThreading(%d) done", name_, threading);
}
void GrpcExecutor::Shutdown() { SetThreading(false); }
void Executor::Shutdown() { SetThreading(false); }
void GrpcExecutor::ThreadMain(void* arg) {
void Executor::ThreadMain(void* arg) {
ThreadState* ts = static_cast<ThreadState*>(arg);
gpr_tls_set(&g_this_thread_state, reinterpret_cast<intptr_t>(ts));
@ -192,8 +242,8 @@ void GrpcExecutor::ThreadMain(void* arg) {
}
}
void GrpcExecutor::Enqueue(grpc_closure* closure, grpc_error* error,
bool is_short) {
void Executor::Enqueue(grpc_closure* closure, grpc_error* error,
bool is_short) {
bool retry_push;
if (is_short) {
GRPC_STATS_INC_EXECUTOR_SCHEDULED_SHORT_ITEMS();
@ -304,7 +354,7 @@ void GrpcExecutor::Enqueue(grpc_closure* closure, grpc_error* error,
gpr_atm_rel_store(&num_threads_, cur_thread_count + 1);
thd_state_[cur_thread_count].thd = grpc_core::Thread(
name_, &GrpcExecutor::ThreadMain, &thd_state_[cur_thread_count]);
name_, &Executor::ThreadMain, &thd_state_[cur_thread_count]);
thd_state_[cur_thread_count].thd.Start();
}
gpr_spinlock_unlock(&adding_thread_lock_);
@ -316,85 +366,52 @@ void GrpcExecutor::Enqueue(grpc_closure* closure, grpc_error* error,
} while (retry_push);
}
static GrpcExecutor* executors[GRPC_NUM_EXECUTORS];
void default_enqueue_short(grpc_closure* closure, grpc_error* error) {
executors[GRPC_DEFAULT_EXECUTOR]->Enqueue(closure, error,
true /* is_short */);
}
void default_enqueue_long(grpc_closure* closure, grpc_error* error) {
executors[GRPC_DEFAULT_EXECUTOR]->Enqueue(closure, error,
false /* is_short */);
}
void resolver_enqueue_short(grpc_closure* closure, grpc_error* error) {
executors[GRPC_RESOLVER_EXECUTOR]->Enqueue(closure, error,
true /* is_short */);
}
void resolver_enqueue_long(grpc_closure* closure, grpc_error* error) {
executors[GRPC_RESOLVER_EXECUTOR]->Enqueue(closure, error,
false /* is_short */);
}
static const grpc_closure_scheduler_vtable
vtables_[GRPC_NUM_EXECUTORS][GRPC_NUM_EXECUTOR_JOB_TYPES] = {
{{&default_enqueue_short, &default_enqueue_short, "def-ex-short"},
{&default_enqueue_long, &default_enqueue_long, "def-ex-long"}},
{{&resolver_enqueue_short, &resolver_enqueue_short, "res-ex-short"},
{&resolver_enqueue_long, &resolver_enqueue_long, "res-ex-long"}}};
static grpc_closure_scheduler
schedulers_[GRPC_NUM_EXECUTORS][GRPC_NUM_EXECUTOR_JOB_TYPES] = {
{{&vtables_[GRPC_DEFAULT_EXECUTOR][GRPC_EXECUTOR_SHORT]},
{&vtables_[GRPC_DEFAULT_EXECUTOR][GRPC_EXECUTOR_LONG]}},
{{&vtables_[GRPC_RESOLVER_EXECUTOR][GRPC_EXECUTOR_SHORT]},
{&vtables_[GRPC_RESOLVER_EXECUTOR][GRPC_EXECUTOR_LONG]}}};
// grpc_executor_init() and grpc_executor_shutdown() functions are called in the
// Executor::InitAll() and Executor::ShutdownAll() functions are called in the
// the grpc_init() and grpc_shutdown() code paths which are protected by a
// global mutex. So it is okay to assume that these functions are thread-safe
void grpc_executor_init() {
EXECUTOR_TRACE0("grpc_executor_init() enter");
void Executor::InitAll() {
EXECUTOR_TRACE0("Executor::InitAll() enter");
// Return if grpc_executor_init() is already called earlier
if (executors[GRPC_DEFAULT_EXECUTOR] != nullptr) {
GPR_ASSERT(executors[GRPC_RESOLVER_EXECUTOR] != nullptr);
// Return if Executor::InitAll() is already called earlier
if (executors[static_cast<size_t>(ExecutorType::DEFAULT)] != nullptr) {
GPR_ASSERT(executors[static_cast<size_t>(ExecutorType::RESOLVER)] !=
nullptr);
return;
}
executors[GRPC_DEFAULT_EXECUTOR] =
grpc_core::New<GrpcExecutor>("default-executor");
executors[GRPC_RESOLVER_EXECUTOR] =
grpc_core::New<GrpcExecutor>("resolver-executor");
executors[static_cast<size_t>(ExecutorType::DEFAULT)] =
grpc_core::New<Executor>("default-executor");
executors[static_cast<size_t>(ExecutorType::RESOLVER)] =
grpc_core::New<Executor>("resolver-executor");
executors[GRPC_DEFAULT_EXECUTOR]->Init();
executors[GRPC_RESOLVER_EXECUTOR]->Init();
executors[static_cast<size_t>(ExecutorType::DEFAULT)]->Init();
executors[static_cast<size_t>(ExecutorType::RESOLVER)]->Init();
EXECUTOR_TRACE0("grpc_executor_init() done");
EXECUTOR_TRACE0("Executor::InitAll() done");
}
grpc_closure_scheduler* grpc_executor_scheduler(GrpcExecutorType executor_type,
GrpcExecutorJobType job_type) {
return &schedulers_[executor_type][job_type];
grpc_closure_scheduler* Executor::Scheduler(ExecutorType executor_type,
ExecutorJobType job_type) {
return &schedulers_[static_cast<size_t>(executor_type)]
[static_cast<size_t>(job_type)];
}
grpc_closure_scheduler* grpc_executor_scheduler(GrpcExecutorJobType job_type) {
return grpc_executor_scheduler(GRPC_DEFAULT_EXECUTOR, job_type);
grpc_closure_scheduler* Executor::Scheduler(ExecutorJobType job_type) {
return Executor::Scheduler(ExecutorType::DEFAULT, job_type);
}
void grpc_executor_shutdown() {
EXECUTOR_TRACE0("grpc_executor_shutdown() enter");
void Executor::ShutdownAll() {
EXECUTOR_TRACE0("Executor::ShutdownAll() enter");
// Return if grpc_executor_shutdown() is already called earlier
if (executors[GRPC_DEFAULT_EXECUTOR] == nullptr) {
GPR_ASSERT(executors[GRPC_RESOLVER_EXECUTOR] == nullptr);
// Return if Executor:SshutdownAll() is already called earlier
if (executors[static_cast<size_t>(ExecutorType::DEFAULT)] == nullptr) {
GPR_ASSERT(executors[static_cast<size_t>(ExecutorType::RESOLVER)] ==
nullptr);
return;
}
executors[GRPC_DEFAULT_EXECUTOR]->Shutdown();
executors[GRPC_RESOLVER_EXECUTOR]->Shutdown();
executors[static_cast<size_t>(ExecutorType::DEFAULT)]->Shutdown();
executors[static_cast<size_t>(ExecutorType::RESOLVER)]->Shutdown();
// Delete the executor objects.
//
@ -408,26 +425,36 @@ void grpc_executor_shutdown() {
// By ensuring that all executors are shutdown first, we are also ensuring
// that no thread is active across all executors.
grpc_core::Delete<GrpcExecutor>(executors[GRPC_DEFAULT_EXECUTOR]);
grpc_core::Delete<GrpcExecutor>(executors[GRPC_RESOLVER_EXECUTOR]);
executors[GRPC_DEFAULT_EXECUTOR] = nullptr;
executors[GRPC_RESOLVER_EXECUTOR] = nullptr;
grpc_core::Delete<Executor>(
executors[static_cast<size_t>(ExecutorType::DEFAULT)]);
grpc_core::Delete<Executor>(
executors[static_cast<size_t>(ExecutorType::RESOLVER)]);
executors[static_cast<size_t>(ExecutorType::DEFAULT)] = nullptr;
executors[static_cast<size_t>(ExecutorType::RESOLVER)] = nullptr;
EXECUTOR_TRACE0("grpc_executor_shutdown() done");
EXECUTOR_TRACE0("Executor::ShutdownAll() done");
}
bool grpc_executor_is_threaded(GrpcExecutorType executor_type) {
GPR_ASSERT(executor_type < GRPC_NUM_EXECUTORS);
return executors[executor_type]->IsThreaded();
bool Executor::IsThreaded(ExecutorType executor_type) {
GPR_ASSERT(executor_type < ExecutorType::NUM_EXECUTORS);
return executors[static_cast<size_t>(executor_type)]->IsThreaded();
}
bool grpc_executor_is_threaded() {
return grpc_executor_is_threaded(GRPC_DEFAULT_EXECUTOR);
bool Executor::IsThreadedDefault() {
return Executor::IsThreaded(ExecutorType::DEFAULT);
}
void grpc_executor_set_threading(bool enable) {
EXECUTOR_TRACE("grpc_executor_set_threading(%d) called", enable);
for (int i = 0; i < GRPC_NUM_EXECUTORS; i++) {
void Executor::SetThreadingAll(bool enable) {
EXECUTOR_TRACE("Executor::SetThreadingAll(%d) called", enable);
for (size_t i = 0; i < static_cast<size_t>(ExecutorType::NUM_EXECUTORS);
i++) {
executors[i]->SetThreading(enable);
}
}
void Executor::SetThreadingDefault(bool enable) {
EXECUTOR_TRACE("Executor::SetThreadingDefault(%d) called", enable);
executors[static_cast<size_t>(ExecutorType::DEFAULT)]->SetThreading(enable);
}
} // namespace grpc_core

@ -25,7 +25,9 @@
#include "src/core/lib/gprpp/thd.h"
#include "src/core/lib/iomgr/closure.h"
typedef struct {
namespace grpc_core {
struct ThreadState {
gpr_mu mu;
size_t id; // For debugging purposes
const char* name; // Thread state name
@ -35,17 +37,24 @@ typedef struct {
bool shutdown;
bool queued_long_job;
grpc_core::Thread thd;
} ThreadState;
};
typedef enum {
GRPC_EXECUTOR_SHORT = 0,
GRPC_EXECUTOR_LONG,
GRPC_NUM_EXECUTOR_JOB_TYPES // Add new values above this
} GrpcExecutorJobType;
enum class ExecutorType {
DEFAULT = 0,
RESOLVER,
NUM_EXECUTORS // Add new values above this
};
class GrpcExecutor {
enum class ExecutorJobType {
SHORT = 0,
LONG,
NUM_JOB_TYPES // Add new values above this
};
class Executor {
public:
GrpcExecutor(const char* executor_name);
Executor(const char* executor_name);
void Init();
@ -62,55 +71,51 @@ class GrpcExecutor {
* a short job (i.e expected to not block and complete quickly) */
void Enqueue(grpc_closure* closure, grpc_error* error, bool is_short);
private:
static size_t RunClosures(const char* executor_name, grpc_closure_list list);
static void ThreadMain(void* arg);
// TODO(sreek): Currently we have two executors (available globally): The
// default executor and the resolver executor.
//
// Some of the functions below operate on the DEFAULT executor only while some
// operate of ALL the executors. This is a bit confusing and should be cleaned
// up in future (where we make all the following functions take ExecutorType
// and/or JobType)
const char* name_;
ThreadState* thd_state_;
size_t max_threads_;
gpr_atm num_threads_;
gpr_spinlock adding_thread_lock_;
};
// == Global executor functions ==
// Initialize ALL the executors
static void InitAll();
typedef enum {
GRPC_DEFAULT_EXECUTOR = 0,
GRPC_RESOLVER_EXECUTOR,
// Shutdown ALL the executors
static void ShutdownAll();
GRPC_NUM_EXECUTORS // Add new values above this
} GrpcExecutorType;
// Set the threading mode for ALL the executors
static void SetThreadingAll(bool enable);
// TODO(sreek): Currently we have two executors (available globally): The
// default executor and the resolver executor.
//
// Some of the functions below operate on the DEFAULT executor only while some
// operate of ALL the executors. This is a bit confusing and should be cleaned
// up in future (where we make all the following functions take executor_type
// and/or job_type)
// Set the threading mode for ALL the executors
static void SetThreadingDefault(bool enable);
// Initialize ALL the executors
void grpc_executor_init();
// Get the DEFAULT executor scheduler for the given job_type
static grpc_closure_scheduler* Scheduler(ExecutorJobType job_type);
// Shutdown ALL the executors
void grpc_executor_shutdown();
// Get the executor scheduler for a given executor_type and a job_type
static grpc_closure_scheduler* Scheduler(ExecutorType executor_type,
ExecutorJobType job_type);
// Set the threading mode for ALL the executors
void grpc_executor_set_threading(bool enable);
// Return if a given executor is running in threaded mode (i.e if
// SetThreading(true) was called previously on that executor)
static bool IsThreaded(ExecutorType executor_type);
// Get the DEFAULT executor scheduler for the given job_type
grpc_closure_scheduler* grpc_executor_scheduler(GrpcExecutorJobType job_type);
// Return if the DEFAULT executor is threaded
static bool IsThreadedDefault();
// Get the executor scheduler for a given executor_type and a job_type
grpc_closure_scheduler* grpc_executor_scheduler(GrpcExecutorType executor_type,
GrpcExecutorJobType job_type);
private:
static size_t RunClosures(const char* executor_name, grpc_closure_list list);
static void ThreadMain(void* arg);
// Return if a given executor is running in threaded mode (i.e if
// grpc_executor_set_threading(true) was called previously on that executor)
bool grpc_executor_is_threaded(GrpcExecutorType executor_type);
const char* name_;
ThreadState* thd_state_;
size_t max_threads_;
gpr_atm num_threads_;
gpr_spinlock adding_thread_lock_;
};
// Return if the DEFAULT executor is threaded
bool grpc_executor_is_threaded();
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_IOMGR_EXECUTOR_H */

@ -71,7 +71,7 @@ void grpc_prefork() {
return;
}
grpc_timer_manager_set_threading(false);
grpc_executor_set_threading(false);
grpc_core::Executor::SetThreadingAll(false);
grpc_core::ExecCtx::Get()->Flush();
grpc_core::Fork::AwaitThreads();
skipped_handler = false;
@ -82,7 +82,7 @@ void grpc_postfork_parent() {
grpc_core::Fork::AllowExecCtx();
grpc_core::ExecCtx exec_ctx;
grpc_timer_manager_set_threading(true);
grpc_executor_set_threading(true);
grpc_core::Executor::SetThreadingAll(true);
}
}
@ -96,7 +96,7 @@ void grpc_postfork_child() {
reset_polling_engine();
}
grpc_timer_manager_set_threading(true);
grpc_executor_set_threading(true);
grpc_core::Executor::SetThreadingAll(true);
}
}

@ -37,6 +37,7 @@
#ifdef GRPC_LINUX_ERRQUEUE
#include <linux/errqueue.h>
#include <linux/net_tstamp.h>
#include <linux/netlink.h>
#include <sys/socket.h>
#endif /* GRPC_LINUX_ERRQUEUE */
@ -56,6 +57,12 @@ constexpr int SCM_TSTAMP_SND = 0;
constexpr int SCM_TSTAMP_SCHED = 1;
/* The timestamp type for when data acknowledged by peer. */
constexpr int SCM_TSTAMP_ACK = 2;
/* Control message type containing OPT_STATS */
#ifndef SCM_TIMESTAMPING_OPT_STATS
#define SCM_TIMESTAMPING_OPT_STATS 54
#endif
/* Redefine required constants from <linux/net_tstamp.h> */
constexpr uint32_t SOF_TIMESTAMPING_TX_SOFTWARE = 1u << 1;
constexpr uint32_t SOF_TIMESTAMPING_SOFTWARE = 1u << 4;
@ -63,13 +70,108 @@ constexpr uint32_t SOF_TIMESTAMPING_OPT_ID = 1u << 7;
constexpr uint32_t SOF_TIMESTAMPING_TX_SCHED = 1u << 8;
constexpr uint32_t SOF_TIMESTAMPING_TX_ACK = 1u << 9;
constexpr uint32_t SOF_TIMESTAMPING_OPT_TSONLY = 1u << 11;
constexpr uint32_t SOF_TIMESTAMPING_OPT_STATS = 1u << 12;
constexpr uint32_t kTimestampingSocketOptions = SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_OPT_ID |
SOF_TIMESTAMPING_OPT_TSONLY;
constexpr uint32_t kTimestampingSocketOptions =
SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_OPT_ID |
SOF_TIMESTAMPING_OPT_TSONLY | SOF_TIMESTAMPING_OPT_STATS;
constexpr uint32_t kTimestampingRecordingOptions =
SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_TX_ACK;
/* Netlink attribute types used for TCP opt stats. */
enum TCPOptStats {
TCP_NLA_PAD,
TCP_NLA_BUSY, /* Time (usec) busy sending data. */
TCP_NLA_RWND_LIMITED, /* Time (usec) limited by receive window. */
TCP_NLA_SNDBUF_LIMITED, /* Time (usec) limited by send buffer. */
TCP_NLA_DATA_SEGS_OUT, /* Data pkts sent including retransmission. */
TCP_NLA_TOTAL_RETRANS, /* Data pkts retransmitted. */
TCP_NLA_PACING_RATE, /* Pacing rate in Bps. */
TCP_NLA_DELIVERY_RATE, /* Delivery rate in Bps. */
TCP_NLA_SND_CWND, /* Sending congestion window. */
TCP_NLA_REORDERING, /* Reordering metric. */
TCP_NLA_MIN_RTT, /* minimum RTT. */
TCP_NLA_RECUR_RETRANS, /* Recurring retransmits for the current pkt. */
TCP_NLA_DELIVERY_RATE_APP_LMT, /* Delivery rate application limited? */
TCP_NLA_SNDQ_SIZE, /* Data (bytes) pending in send queue */
TCP_NLA_CA_STATE, /* ca_state of socket */
TCP_NLA_SND_SSTHRESH, /* Slow start size threshold */
TCP_NLA_DELIVERED, /* Data pkts delivered incl. out-of-order */
TCP_NLA_DELIVERED_CE, /* Like above but only ones w/ CE marks */
TCP_NLA_BYTES_SENT, /* Data bytes sent including retransmission */
TCP_NLA_BYTES_RETRANS, /* Data bytes retransmitted */
TCP_NLA_DSACK_DUPS, /* DSACK blocks received */
TCP_NLA_REORD_SEEN, /* reordering events seen */
TCP_NLA_SRTT, /* smoothed RTT in usecs */
};
/* tcp_info from from linux/tcp.h */
struct tcp_info {
uint8_t tcpi_state;
uint8_t tcpi_ca_state;
uint8_t tcpi_retransmits;
uint8_t tcpi_probes;
uint8_t tcpi_backoff;
uint8_t tcpi_options;
uint8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4;
uint8_t tcpi_delivery_rate_app_limited : 1;
uint32_t tcpi_rto;
uint32_t tcpi_ato;
uint32_t tcpi_snd_mss;
uint32_t tcpi_rcv_mss;
uint32_t tcpi_unacked;
uint32_t tcpi_sacked;
uint32_t tcpi_lost;
uint32_t tcpi_retrans;
uint32_t tcpi_fackets;
/* Times. */
uint32_t tcpi_last_data_sent;
uint32_t tcpi_last_ack_sent; /* Not remembered, sorry. */
uint32_t tcpi_last_data_recv;
uint32_t tcpi_last_ack_recv;
/* Metrics. */
uint32_t tcpi_pmtu;
uint32_t tcpi_rcv_ssthresh;
uint32_t tcpi_rtt;
uint32_t tcpi_rttvar;
uint32_t tcpi_snd_ssthresh;
uint32_t tcpi_snd_cwnd;
uint32_t tcpi_advmss;
uint32_t tcpi_reordering;
uint32_t tcpi_rcv_rtt;
uint32_t tcpi_rcv_space;
uint32_t tcpi_total_retrans;
uint64_t tcpi_pacing_rate;
uint64_t tcpi_max_pacing_rate;
uint64_t tcpi_bytes_acked; /* RFC4898 tcpEStatsAppHCThruOctetsAcked */
uint64_t tcpi_bytes_received; /* RFC4898 tcpEStatsAppHCThruOctetsReceived */
uint32_t tcpi_segs_out; /* RFC4898 tcpEStatsPerfSegsOut */
uint32_t tcpi_segs_in; /* RFC4898 tcpEStatsPerfSegsIn */
uint32_t tcpi_notsent_bytes;
uint32_t tcpi_min_rtt;
uint32_t tcpi_data_segs_in; /* RFC4898 tcpEStatsDataSegsIn */
uint32_t tcpi_data_segs_out; /* RFC4898 tcpEStatsDataSegsOut */
uint64_t tcpi_delivery_rate;
uint64_t tcpi_busy_time; /* Time (usec) busy sending data */
uint64_t tcpi_rwnd_limited; /* Time (usec) limited by receive window */
uint64_t tcpi_sndbuf_limited; /* Time (usec) limited by send buffer */
uint32_t tcpi_delivered;
uint32_t tcpi_delivered_ce;
uint64_t tcpi_bytes_sent; /* RFC4898 tcpEStatsPerfHCDataOctetsOut */
uint64_t tcpi_bytes_retrans; /* RFC4898 tcpEStatsPerfOctetsRetrans */
uint32_t tcpi_dsack_dups; /* RFC4898 tcpEStatsStackDSACKDups */
uint32_t tcpi_reord_seen; /* reordering events seen */
socklen_t length; /* Length of struct returned by kernel */
};
#ifndef TCP_INFO
#define TCP_INFO 11
#endif
#endif /* GRPC_LINUX_ERRQUEUE */
/* Returns true if kernel is capable of supporting errqueue and timestamping.

@ -38,7 +38,6 @@
#include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/iomgr/internal_errqueue.h"
#include "src/core/lib/iomgr/iomgr_internal.h"
#include "src/core/lib/iomgr/network_status_tracker.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/timer_manager.h"
@ -53,11 +52,10 @@ void grpc_iomgr_init() {
g_shutdown = 0;
gpr_mu_init(&g_mu);
gpr_cv_init(&g_rcv);
grpc_executor_init();
grpc_core::Executor::InitAll();
grpc_timer_list_init();
g_root_object.next = g_root_object.prev = &g_root_object;
g_root_object.name = (char*)"root";
grpc_network_status_init();
grpc_iomgr_platform_init();
grpc_core::grpc_errqueue_init();
}
@ -90,7 +88,7 @@ void grpc_iomgr_shutdown() {
{
grpc_timer_manager_shutdown();
grpc_iomgr_platform_flush();
grpc_executor_shutdown();
grpc_core::Executor::ShutdownAll();
gpr_mu_lock(&g_mu);
g_shutdown = 1;
@ -152,7 +150,6 @@ void grpc_iomgr_shutdown() {
gpr_mu_unlock(&g_mu);
grpc_iomgr_platform_shutdown();
grpc_network_status_shutdown();
gpr_mu_destroy(&g_mu);
gpr_cv_destroy(&g_rcv);
}

@ -34,7 +34,7 @@ gpr_thd_id g_init_thread;
static void iomgr_platform_init(void) {
grpc_core::ExecCtx exec_ctx;
grpc_executor_set_threading(false);
grpc_core::Executor::SetThreadingAll(false);
g_init_thread = gpr_thd_currentid();
grpc_pollset_global_init();
}

@ -1,36 +0,0 @@
/*
*
* Copyright 2015 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/network_status_tracker.h"
void grpc_network_status_shutdown(void) {}
void grpc_network_status_init(void) {
// TODO(makarandd): Install callback with OS to monitor network status.
}
void grpc_destroy_network_status_monitor() {}
void grpc_network_status_register_endpoint(grpc_endpoint* ep) { (void)ep; }
void grpc_network_status_unregister_endpoint(grpc_endpoint* ep) { (void)ep; }
void grpc_network_status_shutdown_all_endpoints() {}

@ -105,7 +105,7 @@ static grpc_error* posix_blocking_resolve_address(
grpc_error_set_str(
grpc_error_set_str(
grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("OS Error"),
GRPC_ERROR_CREATE_FROM_STATIC_STRING(gai_strerror(s)),
GRPC_ERROR_INT_ERRNO, s),
GRPC_ERROR_STR_OS_ERROR,
grpc_slice_from_static_string(gai_strerror(s))),
@ -150,7 +150,7 @@ typedef struct {
void* arg;
} request;
/* Callback to be passed to grpc_executor to asynch-ify
/* Callback to be passed to grpc Executor to asynch-ify
* grpc_blocking_resolve_address */
static void do_request_thread(void* rp, grpc_error* error) {
request* r = static_cast<request*>(rp);
@ -168,7 +168,8 @@ static void posix_resolve_address(const char* name, const char* default_port,
request* r = static_cast<request*>(gpr_malloc(sizeof(request)));
GRPC_CLOSURE_INIT(
&r->request_closure, do_request_thread, r,
grpc_executor_scheduler(GRPC_RESOLVER_EXECUTOR, GRPC_EXECUTOR_SHORT));
grpc_core::Executor::Scheduler(grpc_core::ExecutorType::RESOLVER,
grpc_core::ExecutorJobType::SHORT));
r->name = gpr_strdup(name);
r->default_port = gpr_strdup(default_port);
r->on_done = on_done;

@ -153,7 +153,8 @@ static void windows_resolve_address(const char* name, const char* default_port,
request* r = (request*)gpr_malloc(sizeof(request));
GRPC_CLOSURE_INIT(
&r->request_closure, do_request_thread, r,
grpc_executor_scheduler(GRPC_RESOLVER_EXECUTOR, GRPC_EXECUTOR_SHORT));
grpc_core::Executor::Scheduler(grpc_core::ExecutorType::RESOLVER,
grpc_core::ExecutorJobType::SHORT));
r->name = gpr_strdup(name);
r->default_port = gpr_strdup(default_port);
r->on_done = on_done;

@ -31,7 +31,6 @@
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/iomgr_custom.h"
#include "src/core/lib/iomgr/network_status_tracker.h"
#include "src/core/lib/iomgr/resource_quota.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/iomgr/tcp_custom.h"
@ -309,7 +308,6 @@ static void custom_close_callback(grpc_custom_socket* socket) {
}
static void endpoint_destroy(grpc_endpoint* ep) {
grpc_network_status_unregister_endpoint(ep);
custom_tcp_endpoint* tcp = (custom_tcp_endpoint*)ep;
grpc_custom_socket_vtable->close(tcp->socket, custom_close_callback);
}
@ -361,8 +359,6 @@ grpc_endpoint* custom_tcp_endpoint_create(grpc_custom_socket* socket,
tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string);
grpc_resource_user_slice_allocator_init(
&tcp->slice_allocator, tcp->resource_user, tcp_read_allocation_done, tcp);
/* Tell network status tracking code about the new endpoint */
grpc_network_status_register_endpoint(&tcp->base);
return &tcp->base;
}

@ -22,7 +22,6 @@
#ifdef GRPC_POSIX_SOCKET_TCP
#include "src/core/lib/iomgr/network_status_tracker.h"
#include "src/core/lib/iomgr/tcp_posix.h"
#include <errno.h>
@ -127,9 +126,8 @@ struct grpc_tcp {
bool socket_ts_enabled; /* True if timestamping options are set on the socket
*/
bool ts_capable; /* Cache whether we can set timestamping options */
gpr_atm
stop_error_notification; /* Set to 1 if we do not want to be notified on
errors anymore */
gpr_atm stop_error_notification; /* Set to 1 if we do not want to be notified
on errors anymore */
};
struct backup_poller {
@ -229,10 +227,10 @@ static void cover_self(grpc_tcp* tcp) {
}
grpc_pollset_init(BACKUP_POLLER_POLLSET(p), &p->pollset_mu);
gpr_atm_rel_store(&g_backup_poller, (gpr_atm)p);
GRPC_CLOSURE_SCHED(
GRPC_CLOSURE_INIT(&p->run_poller, run_poller, p,
grpc_executor_scheduler(GRPC_EXECUTOR_LONG)),
GRPC_ERROR_NONE);
GRPC_CLOSURE_SCHED(GRPC_CLOSURE_INIT(&p->run_poller, run_poller, p,
grpc_core::Executor::Scheduler(
grpc_core::ExecutorJobType::LONG)),
GRPC_ERROR_NONE);
} else {
while ((p = (backup_poller*)gpr_atm_acq_load(&g_backup_poller)) ==
nullptr) {
@ -388,7 +386,6 @@ static void tcp_ref(grpc_tcp* tcp) { gpr_ref(&tcp->refcount); }
#endif
static void tcp_destroy(grpc_endpoint* ep) {
grpc_network_status_unregister_endpoint(ep);
grpc_tcp* tcp = reinterpret_cast<grpc_tcp*>(ep);
grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer);
if (grpc_event_engine_can_track_errors()) {
@ -596,6 +593,7 @@ static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg,
static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error);
#ifdef GRPC_LINUX_ERRQUEUE
static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg,
size_t sending_length,
ssize_t* sent_length) {
@ -634,7 +632,7 @@ static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg,
gpr_mu_lock(&tcp->tb_mu);
grpc_core::TracedBuffer::AddNewEntry(
&tcp->tb_head, static_cast<uint32_t>(tcp->bytes_counter + length),
tcp->outgoing_buffer_arg);
tcp->fd, tcp->outgoing_buffer_arg);
gpr_mu_unlock(&tcp->tb_mu);
tcp->outgoing_buffer_arg = nullptr;
}
@ -651,6 +649,7 @@ static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg,
struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg,
struct cmsghdr* cmsg) {
auto next_cmsg = CMSG_NXTHDR(msg, cmsg);
cmsghdr* opt_stats = nullptr;
if (next_cmsg == nullptr) {
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_ERROR, "Received timestamp without extended error");
@ -658,6 +657,19 @@ struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg,
return cmsg;
}
/* Check if next_cmsg is an OPT_STATS msg */
if (next_cmsg->cmsg_level == SOL_SOCKET &&
next_cmsg->cmsg_type == SCM_TIMESTAMPING_OPT_STATS) {
opt_stats = next_cmsg;
next_cmsg = CMSG_NXTHDR(msg, opt_stats);
if (next_cmsg == nullptr) {
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_ERROR, "Received timestamp without extended error");
}
return opt_stats;
}
}
if (!(next_cmsg->cmsg_level == SOL_IP || next_cmsg->cmsg_level == SOL_IPV6) ||
!(next_cmsg->cmsg_type == IP_RECVERR ||
next_cmsg->cmsg_type == IPV6_RECVERR)) {
@ -679,7 +691,8 @@ struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg,
* to protect the traced buffer list. A lock free list might be better. Using
* a simple mutex for now. */
gpr_mu_lock(&tcp->tb_mu);
grpc_core::TracedBuffer::ProcessTimestamp(&tcp->tb_head, serr, tss);
grpc_core::TracedBuffer::ProcessTimestamp(&tcp->tb_head, serr, opt_stats,
tss);
gpr_mu_unlock(&tcp->tb_mu);
return next_cmsg;
}
@ -699,9 +712,11 @@ static void process_errors(grpc_tcp* tcp) {
msg.msg_iovlen = 0;
msg.msg_flags = 0;
// Allocate aligned space for cmsgs received along with a timestamps
union {
char rbuf[1024 /*CMSG_SPACE(sizeof(scm_timestamping)) +
CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in))*/];
char rbuf[CMSG_SPACE(sizeof(grpc_core::scm_timestamping)) +
CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in)) +
CMSG_SPACE(16 * NLA_ALIGN(NLA_HDRLEN + sizeof(uint64_t)))];
struct cmsghdr align;
} aligned_buf;
memset(&aligned_buf, 0, sizeof(aligned_buf));
@ -1131,8 +1146,6 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd,
tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string);
grpc_resource_user_slice_allocator_init(
&tcp->slice_allocator, tcp->resource_user, tcp_read_allocation_done, tcp);
/* Tell network status tracker about new endpoint */
grpc_network_status_register_endpoint(&tcp->base);
grpc_resource_quota_unref_internal(resource_quota);
gpr_mu_init(&tcp->tb_mu);
tcp->tb_head = nullptr;
@ -1159,7 +1172,6 @@ int grpc_tcp_fd(grpc_endpoint* ep) {
void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd,
grpc_closure* done) {
grpc_network_status_unregister_endpoint(ep);
grpc_tcp* tcp = reinterpret_cast<grpc_tcp*>(ep);
GPR_ASSERT(ep->vtable == &vtable);
tcp->release_fd = fd;

@ -33,7 +33,6 @@
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/iomgr_custom.h"
#include "src/core/lib/iomgr/network_status_tracker.h"
#include "src/core/lib/iomgr/resolve_address_custom.h"
#include "src/core/lib/iomgr/resource_quota.h"
#include "src/core/lib/iomgr/tcp_custom.h"

@ -24,7 +24,6 @@
#include <limits.h>
#include "src/core/lib/iomgr/network_status_tracker.h"
#include "src/core/lib/iomgr/sockaddr_windows.h"
#include <grpc/slice_buffer.h>
@ -470,7 +469,6 @@ static void win_shutdown(grpc_endpoint* ep, grpc_error* why) {
}
static void win_destroy(grpc_endpoint* ep) {
grpc_network_status_unregister_endpoint(ep);
grpc_tcp* tcp = (grpc_tcp*)ep;
grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer);
TCP_UNREF(tcp, "destroy");
@ -526,8 +524,6 @@ grpc_endpoint* grpc_tcp_create(grpc_winsocket* socket,
tcp->peer_string = gpr_strdup(peer_string);
grpc_slice_buffer_init(&tcp->last_read_buffer);
tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string);
/* Tell network status tracking code about the new endpoint */
grpc_network_status_register_endpoint(&tcp->base);
grpc_resource_quota_unref_internal(resource_quota);
return &tcp->base;

@ -481,8 +481,9 @@ void GrpcUdpListener::OnRead(grpc_error* error, void* do_read_arg) {
if (udp_handler_->Read()) {
/* There maybe more packets to read. Schedule read_more_cb_ closure to run
* after finishing this event loop. */
GRPC_CLOSURE_INIT(&do_read_closure_, do_read, do_read_arg,
grpc_executor_scheduler(GRPC_EXECUTOR_LONG));
GRPC_CLOSURE_INIT(
&do_read_closure_, do_read, do_read_arg,
grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::LONG));
GRPC_CLOSURE_SCHED(&do_read_closure_, GRPC_ERROR_NONE);
} else {
/* Finish reading all the packets, re-arm the notification event so we can
@ -542,8 +543,9 @@ void GrpcUdpListener::OnCanWrite(grpc_error* error, void* do_write_arg) {
}
/* Schedule actual write in another thread. */
GRPC_CLOSURE_INIT(&do_write_closure_, do_write, do_write_arg,
grpc_executor_scheduler(GRPC_EXECUTOR_LONG));
GRPC_CLOSURE_INIT(
&do_write_closure_, do_write, do_write_arg,
grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::LONG));
GRPC_CLOSURE_SCHED(&do_write_closure_, GRPC_ERROR_NONE);
}

@ -49,6 +49,10 @@ class grpc_composite_channel_credentials : public grpc_channel_credentials {
const char* target, const grpc_channel_args* args,
grpc_channel_args** new_args) override;
grpc_channel_args* update_arguments(grpc_channel_args* args) override {
return inner_creds_->update_arguments(args);
}
const grpc_channel_credentials* inner_creds() const {
return inner_creds_.get();
}

@ -123,6 +123,14 @@ struct grpc_channel_credentials
return Ref();
}
// Allows credentials to optionally modify a parent channel's args.
// By default, leave channel args as is. The callee takes ownership
// of the passed-in channel args, and the caller takes ownership
// of the returned channel args.
virtual grpc_channel_args* update_arguments(grpc_channel_args* args) {
return args;
}
const char* type() const { return type_; }
GRPC_ABSTRACT_BASE_CLASS

@ -114,6 +114,19 @@ grpc_google_default_channel_credentials::create_security_connector(
return sc;
}
grpc_channel_args* grpc_google_default_channel_credentials::update_arguments(
grpc_channel_args* args) {
grpc_channel_args* updated = args;
if (grpc_channel_args_find(args, GRPC_ARG_DNS_ENABLE_SRV_QUERIES) ==
nullptr) {
grpc_arg new_srv_arg = grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_DNS_ENABLE_SRV_QUERIES), true);
updated = grpc_channel_args_copy_and_add(args, &new_srv_arg, 1);
grpc_channel_args_destroy(args);
}
return updated;
}
static void on_metadata_server_detection_http_response(void* user_data,
grpc_error* error) {
metadata_server_detector* detector =

@ -58,6 +58,8 @@ class grpc_google_default_channel_credentials
const char* target, const grpc_channel_args* args,
grpc_channel_args** new_args) override;
grpc_channel_args* update_arguments(grpc_channel_args* args) override;
const grpc_channel_credentials* alts_creds() const {
return alts_creds_.get();
}

@ -165,7 +165,7 @@ void grpc_shutdown(void) {
{
grpc_timer_manager_set_threading(
false); // shutdown timer_manager thread
grpc_executor_shutdown();
grpc_core::Executor::ShutdownAll();
for (i = g_number_of_plugins; i >= 0; i--) {
if (g_all_of_the_plugins[i].destroy != nullptr) {
g_all_of_the_plugins[i].destroy();

@ -1134,8 +1134,9 @@ void grpc_server_start(grpc_server* server) {
server_ref(server);
server->starting = true;
GRPC_CLOSURE_SCHED(
GRPC_CLOSURE_CREATE(start_listeners, server,
grpc_executor_scheduler(GRPC_EXECUTOR_SHORT)),
GRPC_CLOSURE_CREATE(
start_listeners, server,
grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT)),
GRPC_ERROR_NONE);
}

@ -240,6 +240,7 @@ RefCountedPtr<T> ServiceConfig::MethodConfigTableLookup(
value = table.Get(wildcard_path);
grpc_slice_unref_internal(wildcard_path);
gpr_free(path_str);
if (value == nullptr) return nullptr;
}
return RefCountedPtr<T>(*value);
}

@ -73,7 +73,7 @@ void grpc_stream_unref(grpc_stream_refcount* refcount) {
Throw this over to the executor (on a core-owned thread) and process it
there. */
refcount->destroy.scheduler =
grpc_executor_scheduler(GRPC_EXECUTOR_SHORT);
grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT);
}
GRPC_CLOSURE_SCHED(&refcount->destroy, GRPC_ERROR_NONE);
}

@ -63,6 +63,7 @@ ClientContext::ClientContext()
deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)),
census_context_(nullptr),
propagate_from_call_(nullptr),
compression_algorithm_(GRPC_COMPRESS_NONE),
initial_metadata_corked_(false) {
g_client_callbacks->DefaultConstructor(this);
}

@ -19,7 +19,6 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
namespace Grpc.Core.Testing
{
@ -36,23 +35,73 @@ namespace Grpc.Core.Testing
string peer, AuthContext authContext, ContextPropagationToken contextPropagationToken,
Func<Metadata, Task> writeHeadersFunc, Func<WriteOptions> writeOptionsGetter, Action<WriteOptions> writeOptionsSetter)
{
return new ServerCallContext(null, method, host, deadline, requestHeaders, cancellationToken,
writeHeadersFunc, new WriteOptionsHolder(writeOptionsGetter, writeOptionsSetter),
() => peer, () => authContext, () => contextPropagationToken);
return new TestingServerCallContext(method, host, deadline, requestHeaders, cancellationToken, peer,
authContext, contextPropagationToken, writeHeadersFunc, writeOptionsGetter, writeOptionsSetter);
}
private class WriteOptionsHolder : IHasWriteOptions
private class TestingServerCallContext : ServerCallContext
{
Func<WriteOptions> writeOptionsGetter;
Action<WriteOptions> writeOptionsSetter;
private readonly string method;
private readonly string host;
private readonly DateTime deadline;
private readonly Metadata requestHeaders;
private readonly CancellationToken cancellationToken;
private readonly Metadata responseTrailers = new Metadata();
private Status status;
private readonly string peer;
private readonly AuthContext authContext;
private readonly ContextPropagationToken contextPropagationToken;
private readonly Func<Metadata, Task> writeHeadersFunc;
private readonly Func<WriteOptions> writeOptionsGetter;
private readonly Action<WriteOptions> writeOptionsSetter;
public WriteOptionsHolder(Func<WriteOptions> writeOptionsGetter, Action<WriteOptions> writeOptionsSetter)
public TestingServerCallContext(string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
string peer, AuthContext authContext, ContextPropagationToken contextPropagationToken,
Func<Metadata, Task> writeHeadersFunc, Func<WriteOptions> writeOptionsGetter, Action<WriteOptions> writeOptionsSetter)
{
this.method = method;
this.host = host;
this.deadline = deadline;
this.requestHeaders = requestHeaders;
this.cancellationToken = cancellationToken;
this.responseTrailers = new Metadata();
this.status = Status.DefaultSuccess;
this.peer = peer;
this.authContext = authContext;
this.contextPropagationToken = contextPropagationToken;
this.writeHeadersFunc = writeHeadersFunc;
this.writeOptionsGetter = writeOptionsGetter;
this.writeOptionsSetter = writeOptionsSetter;
}
public WriteOptions WriteOptions { get => writeOptionsGetter(); set => writeOptionsSetter(value); }
protected override string MethodCore => method;
protected override string HostCore => host;
protected override string PeerCore => peer;
protected override DateTime DeadlineCore => deadline;
protected override Metadata RequestHeadersCore => requestHeaders;
protected override CancellationToken CancellationTokenCore => cancellationToken;
protected override Metadata ResponseTrailersCore => responseTrailers;
protected override Status StatusCore { get => status; set => status = value; }
protected override WriteOptions WriteOptionsCore { get => writeOptionsGetter(); set => writeOptionsSetter(value); }
protected override AuthContext AuthContextCore => authContext;
protected override ContextPropagationToken CreatePropagationTokenCore(ContextPropagationOptions options)
{
return contextPropagationToken;
}
protected override Task WriteResponseHeadersAsyncCore(Metadata responseHeaders)
{
return writeHeadersFunc(responseHeaders);
}
}
}
}

@ -0,0 +1,110 @@
#region Copyright notice and license
// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion
using System;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core.Internal;
namespace Grpc.Core
{
/// <summary>
/// Default implementation of <c>ServerCallContext</c>.
/// </summary>
internal class DefaultServerCallContext : ServerCallContext
{
private readonly CallSafeHandle callHandle;
private readonly string method;
private readonly string host;
private readonly DateTime deadline;
private readonly Metadata requestHeaders;
private readonly CancellationToken cancellationToken;
private readonly Metadata responseTrailers;
private Status status;
private readonly IServerResponseStream serverResponseStream;
private readonly Lazy<AuthContext> authContext;
/// <summary>
/// Creates a new instance of <c>ServerCallContext</c>.
/// To allow reuse of ServerCallContext API by different gRPC implementations, the implementation of some members is provided externally.
/// To provide state, this <c>ServerCallContext</c> instance and <c>extraData</c> will be passed to the member implementations.
/// </summary>
internal DefaultServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline,
Metadata requestHeaders, CancellationToken cancellationToken, IServerResponseStream serverResponseStream)
{
this.callHandle = callHandle;
this.method = method;
this.host = host;
this.deadline = deadline;
this.requestHeaders = requestHeaders;
this.cancellationToken = cancellationToken;
this.responseTrailers = new Metadata();
this.status = Status.DefaultSuccess;
this.serverResponseStream = serverResponseStream;
// TODO(jtattermusch): avoid unnecessary allocation of factory function and the lazy object
this.authContext = new Lazy<AuthContext>(GetAuthContextEager);
}
protected override ContextPropagationToken CreatePropagationTokenCore(ContextPropagationOptions options)
{
return new ContextPropagationToken(callHandle, deadline, cancellationToken, options);
}
protected override Task WriteResponseHeadersAsyncCore(Metadata responseHeaders)
{
return serverResponseStream.WriteResponseHeadersAsync(responseHeaders);
}
protected override string MethodCore => method;
protected override string HostCore => host;
protected override string PeerCore => callHandle.GetPeer();
protected override DateTime DeadlineCore => deadline;
protected override Metadata RequestHeadersCore => requestHeaders;
protected override CancellationToken CancellationTokenCore => cancellationToken;
protected override Metadata ResponseTrailersCore => responseTrailers;
protected override Status StatusCore
{
get => status;
set => status = value;
}
protected override WriteOptions WriteOptionsCore
{
get => serverResponseStream.WriteOptions;
set => serverResponseStream.WriteOptions = value;
}
protected override AuthContext AuthContextCore => authContext.Value;
private AuthContext GetAuthContextEager()
{
using (var authContextNative = callHandle.GetAuthContext())
{
return authContextNative.ToAuthContext();
}
}
}
}

@ -0,0 +1,38 @@
#region Copyright notice and license
// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion
using System;
using System.Threading.Tasks;
using Grpc.Core.Internal;
namespace Grpc.Core.Internal
{
/// <summary>
/// Exposes non-generic members of <c>ServerReponseStream</c>.
/// </summary>
internal interface IServerResponseStream
{
/// <summary>
/// Asynchronously sends response headers for the current call to the client. See <c>ServerCallContext.WriteResponseHeadersAsync</c> for exact semantics.
/// </summary>
Task WriteResponseHeadersAsync(Metadata responseHeaders);
/// <summary>
/// Gets or sets the write options.
/// </summary>
WriteOptions WriteOptions { get; set; }
}
}

@ -71,7 +71,7 @@ namespace Grpc.Core.Internal
var response = await handler(request, context).ConfigureAwait(false);
status = context.Status;
responseWithFlags = new AsyncCallServer<TRequest, TResponse>.ResponseWithFlags(response, HandlerUtils.GetWriteFlags(context.WriteOptions));
}
}
catch (Exception e)
{
if (!(e is RpcException))
@ -345,14 +345,10 @@ namespace Grpc.Core.Internal
return writeOptions != null ? writeOptions.Flags : default(WriteFlags);
}
public static ServerCallContext NewContext<TRequest, TResponse>(ServerRpcNew newRpc, ServerResponseStream<TRequest, TResponse> serverResponseStream, CancellationToken cancellationToken)
where TRequest : class
where TResponse : class
public static ServerCallContext NewContext(ServerRpcNew newRpc, IServerResponseStream serverResponseStream, CancellationToken cancellationToken)
{
DateTime realtimeDeadline = newRpc.Deadline.ToClockType(ClockType.Realtime).ToDateTime();
return new ServerCallContext(newRpc.Call, newRpc.Method, newRpc.Host, realtimeDeadline,
newRpc.RequestMetadata, cancellationToken, serverResponseStream.WriteResponseHeadersAsync, serverResponseStream);
return new DefaultServerCallContext(newRpc.Call, newRpc.Method, newRpc.Host, realtimeDeadline, newRpc.RequestMetadata, cancellationToken, serverResponseStream);
}
}
}

@ -23,7 +23,7 @@ namespace Grpc.Core.Internal
/// <summary>
/// Writes responses asynchronously to an underlying AsyncCallServer object.
/// </summary>
internal class ServerResponseStream<TRequest, TResponse> : IServerStreamWriter<TResponse>, IHasWriteOptions
internal class ServerResponseStream<TRequest, TResponse> : IServerStreamWriter<TResponse>, IServerResponseStream
where TRequest : class
where TResponse : class
{

@ -20,54 +20,18 @@ using System;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core.Internal;
namespace Grpc.Core
{
/// <summary>
/// Context for a server-side call.
/// </summary>
public class ServerCallContext
public abstract class ServerCallContext
{
private readonly CallSafeHandle callHandle;
private readonly string method;
private readonly string host;
private readonly DateTime deadline;
private readonly Metadata requestHeaders;
private readonly CancellationToken cancellationToken;
private readonly Metadata responseTrailers = new Metadata();
private readonly Func<Metadata, Task> writeHeadersFunc;
private readonly IHasWriteOptions writeOptionsHolder;
private readonly Lazy<AuthContext> authContext;
private readonly Func<string> testingOnlyPeerGetter;
private readonly Func<AuthContext> testingOnlyAuthContextGetter;
private readonly Func<ContextPropagationToken> testingOnlyContextPropagationTokenFactory;
private Status status = Status.DefaultSuccess;
internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder)
: this(callHandle, method, host, deadline, requestHeaders, cancellationToken, writeHeadersFunc, writeOptionsHolder, null, null, null)
{
}
// Additional constructor params should be used for testing only
internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder,
Func<string> testingOnlyPeerGetter, Func<AuthContext> testingOnlyAuthContextGetter, Func<ContextPropagationToken> testingOnlyContextPropagationTokenFactory)
/// <summary>
/// Creates a new instance of <c>ServerCallContext</c>.
/// </summary>
protected ServerCallContext()
{
this.callHandle = callHandle;
this.method = method;
this.host = host;
this.deadline = deadline;
this.requestHeaders = requestHeaders;
this.cancellationToken = cancellationToken;
this.writeHeadersFunc = writeHeadersFunc;
this.writeOptionsHolder = writeOptionsHolder;
this.authContext = new Lazy<AuthContext>(GetAuthContextEager);
this.testingOnlyPeerGetter = testingOnlyPeerGetter;
this.testingOnlyAuthContextGetter = testingOnlyAuthContextGetter;
this.testingOnlyContextPropagationTokenFactory = testingOnlyContextPropagationTokenFactory;
}
/// <summary>
@ -79,7 +43,7 @@ namespace Grpc.Core
/// <returns>The task that finished once response headers have been written.</returns>
public Task WriteResponseHeadersAsync(Metadata responseHeaders)
{
return writeHeadersFunc(responseHeaders);
return WriteResponseHeadersAsyncCore(responseHeaders);
}
/// <summary>
@ -87,94 +51,41 @@ namespace Grpc.Core
/// </summary>
public ContextPropagationToken CreatePropagationToken(ContextPropagationOptions options = null)
{
if (testingOnlyContextPropagationTokenFactory != null)
{
return testingOnlyContextPropagationTokenFactory();
}
return new ContextPropagationToken(callHandle, deadline, cancellationToken, options);
return CreatePropagationTokenCore(options);
}
/// <summary>Name of method called in this RPC.</summary>
public string Method
{
get
{
return this.method;
}
}
public string Method => MethodCore;
/// <summary>Name of host called in this RPC.</summary>
public string Host
{
get
{
return this.host;
}
}
public string Host => HostCore;
/// <summary>Address of the remote endpoint in URI format.</summary>
public string Peer
{
get
{
if (testingOnlyPeerGetter != null)
{
return testingOnlyPeerGetter();
}
// Getting the peer lazily is fine as the native call is guaranteed
// not to be disposed before user-supplied server side handler returns.
// Most users won't need to read this field anyway.
return this.callHandle.GetPeer();
}
}
public string Peer => PeerCore;
/// <summary>Deadline for this RPC.</summary>
public DateTime Deadline
{
get
{
return this.deadline;
}
}
public DateTime Deadline => DeadlineCore;
/// <summary>Initial metadata sent by client.</summary>
public Metadata RequestHeaders
{
get
{
return this.requestHeaders;
}
}
public Metadata RequestHeaders => RequestHeadersCore;
/// <summary>Cancellation token signals when call is cancelled.</summary>
public CancellationToken CancellationToken
{
get
{
return this.cancellationToken;
}
}
public CancellationToken CancellationToken => CancellationTokenCore;
/// <summary>Trailers to send back to client after RPC finishes.</summary>
public Metadata ResponseTrailers
{
get
{
return this.responseTrailers;
}
}
public Metadata ResponseTrailers => ResponseTrailersCore;
/// <summary> Status to send back to client after RPC finishes.</summary>
public Status Status
{
get
{
return this.status;
return StatusCore;
}
set
{
status = value;
StatusCore = value;
}
}
@ -187,12 +98,12 @@ namespace Grpc.Core
{
get
{
return writeOptionsHolder.WriteOptions;
return WriteOptionsCore;
}
set
{
writeOptionsHolder.WriteOptions = value;
WriteOptionsCore = value;
}
}
@ -200,35 +111,31 @@ namespace Grpc.Core
/// Gets the <c>AuthContext</c> associated with this call.
/// Note: Access to AuthContext is an experimental API that can change without any prior notice.
/// </summary>
public AuthContext AuthContext
{
get
{
if (testingOnlyAuthContextGetter != null)
{
return testingOnlyAuthContextGetter();
}
return authContext.Value;
}
}
private AuthContext GetAuthContextEager()
{
using (var authContextNative = callHandle.GetAuthContext())
{
return authContextNative.ToAuthContext();
}
}
}
/// <summary>
/// Allows sharing write options between ServerCallContext and other objects.
/// </summary>
internal interface IHasWriteOptions
{
/// <summary>
/// Gets or sets the write options.
/// </summary>
WriteOptions WriteOptions { get; set; }
public AuthContext AuthContext => AuthContextCore;
/// <summary>Provides implementation of a non-virtual public member.</summary>
protected abstract Task WriteResponseHeadersAsyncCore(Metadata responseHeaders);
/// <summary>Provides implementation of a non-virtual public member.</summary>
protected abstract ContextPropagationToken CreatePropagationTokenCore(ContextPropagationOptions options);
/// <summary>Provides implementation of a non-virtual public member.</summary>
protected abstract string MethodCore { get; }
/// <summary>Provides implementation of a non-virtual public member.</summary>
protected abstract string HostCore { get; }
/// <summary>Provides implementation of a non-virtual public member.</summary>
protected abstract string PeerCore { get; }
/// <summary>Provides implementation of a non-virtual public member.</summary>
protected abstract DateTime DeadlineCore { get; }
/// <summary>Provides implementation of a non-virtual public member.</summary>
protected abstract Metadata RequestHeadersCore { get; }
/// <summary>Provides implementation of a non-virtual public member.</summary>
protected abstract CancellationToken CancellationTokenCore { get; }
/// <summary>Provides implementation of a non-virtual public member.</summary>
protected abstract Metadata ResponseTrailersCore { get; }
/// <summary>Provides implementation of a non-virtual public member.</summary>
protected abstract Status StatusCore { get; set; }
/// <summary>Provides implementation of a non-virtual public member.</summary>
protected abstract WriteOptions WriteOptionsCore { get; set; }
/// <summary>Provides implementation of a non-virtual public member.</summary>
protected abstract AuthContext AuthContextCore { get; }
}
}

@ -599,7 +599,6 @@ const char *kCFStreamVarName = "grpc_cfstream";
dispatch_async(_callQueue, ^{
__weak GRPCCall *weakSelf = self;
[self startReadWithHandler:^(grpc_byte_buffer *message) {
NSLog(@"message received");
if (message == NULL) {
// No more messages from the server
return;
@ -773,7 +772,6 @@ const char *kCFStreamVarName = "grpc_cfstream";
__weak GRPCCall *weakSelf = self;
[self invokeCallWithHeadersHandler:^(NSDictionary *headers) {
// Response headers received.
NSLog(@"response received");
__strong GRPCCall *strongSelf = weakSelf;
if (strongSelf) {
strongSelf.responseHeaders = headers;
@ -781,7 +779,6 @@ const char *kCFStreamVarName = "grpc_cfstream";
}
}
completionHandler:^(NSError *error, NSDictionary *trailers) {
NSLog(@"completion received");
__strong GRPCCall *strongSelf = weakSelf;
if (strongSelf) {
strongSelf.responseTrailers = trailers;
@ -892,14 +889,18 @@ const char *kCFStreamVarName = "grpc_cfstream";
[tokenProvider getTokenWithHandler:^(NSString *token) {
__strong typeof(self) strongSelf = weakSelf;
if (strongSelf) {
BOOL startCall = NO;
@synchronized(strongSelf) {
if (strongSelf->_state == GRXWriterStateNotStarted) {
if (strongSelf->_state != GRXWriterStateFinished) {
startCall = YES;
if (token) {
strongSelf->_fetchedOauth2AccessToken = [token copy];
}
}
}
[strongSelf startCallWithWriteable:writeable];
if (startCall) {
[strongSelf startCallWithWriteable:writeable];
}
}
}];
} else {

@ -318,10 +318,6 @@ static char *roots_filename;
[self testIndividualCase:(char *)"negative_deadline"];
}
- (void)testNetworkStatusChange {
[self testIndividualCase:(char *)"network_status_change"];
}
- (void)testNoOp {
[self testIndividualCase:(char *)"no_op"];
}

@ -22,7 +22,6 @@ import grpc
from grpc import _common
from grpc import _grpcio_metadata
from grpc._cython import cygrpc
from grpc.framework.foundation import callable_util
_LOGGER = logging.getLogger(__name__)
@ -871,9 +870,11 @@ def _deliver(state, initial_connectivity, initial_callbacks):
while True:
for callback in callbacks:
cygrpc.block_if_fork_in_progress(state)
callable_util.call_logging_exceptions(
callback, _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE,
connectivity)
try:
callback(connectivity)
except Exception: # pylint: disable=broad-except
_LOGGER.exception(
_CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE)
with state.lock:
callbacks = _deliveries(state)
if callbacks:
@ -1063,5 +1064,5 @@ class Channel(grpc.Channel):
cygrpc.fork_unregister_channel(self)
# This prevent the failed-at-initializing object removal from failing.
# Though the __init__ failed, the removal will still trigger __del__.
if _moot is not None and hasattr(self, "_connectivity_state"):
if _moot is not None and hasattr(self, '_connectivity_state'):
_moot(self._connectivity_state)

@ -25,7 +25,6 @@ import grpc
from grpc import _common
from grpc import _interceptor
from grpc._cython import cygrpc
from grpc.framework.foundation import callable_util
_LOGGER = logging.getLogger(__name__)
@ -748,8 +747,10 @@ def _process_event_and_continue(state, event):
else:
rpc_state, callbacks = event.tag(event)
for callback in callbacks:
callable_util.call_logging_exceptions(callback,
'Exception calling callback!')
try:
callback()
except Exception: # pylint: disable=broad-except
_LOGGER.exception('Exception calling callback!')
if rpc_state is not None:
with state.lock:
state.rpc_states.remove(rpc_state)
@ -860,9 +861,10 @@ class _Server(grpc.Server):
return _stop(self._state, grace)
def __del__(self):
# We can not grab a lock in __del__(), so set a flag to signal the
# serving daemon thread (if it exists) to initiate shutdown.
self._state.server_deallocated = True
if hasattr(self, '_state'):
# We can not grab a lock in __del__(), so set a flag to signal the
# serving daemon thread (if it exists) to initiate shutdown.
self._state.server_deallocated = True
def create_server(thread_pool, generic_rpc_handlers, interceptors, options,

@ -16,12 +16,14 @@
import collections
import threading
import time
import logging
import six
import grpc
from grpc import _common
from grpc.framework.foundation import callable_util
_LOGGER = logging.getLogger(__name__)
_DONE_CALLBACK_EXCEPTION_LOG_MESSAGE = (
'Exception calling connectivity future "done" callback!')
@ -98,8 +100,10 @@ class _ChannelReadyFuture(grpc.Future):
return
for done_callback in done_callbacks:
callable_util.call_logging_exceptions(
done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self)
try:
done_callback(self)
except Exception: # pylint: disable=broad-except
_LOGGER.exception(_DONE_CALLBACK_EXCEPTION_LOG_MESSAGE)
def cancel(self):
with self._condition:
@ -113,8 +117,10 @@ class _ChannelReadyFuture(grpc.Future):
return False
for done_callback in done_callbacks:
callable_util.call_logging_exceptions(
done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self)
try:
done_callback(self)
except Exception: # pylint: disable=broad-except
_LOGGER.exception(_DONE_CALLBACK_EXCEPTION_LOG_MESSAGE)
return True

@ -115,7 +115,6 @@ CORE_SOURCE_FILES = [
'src/core/lib/iomgr/is_epollexclusive_available.cc',
'src/core/lib/iomgr/load_file.cc',
'src/core/lib/iomgr/lockfree_event.cc',
'src/core/lib/iomgr/network_status_tracker.cc',
'src/core/lib/iomgr/polling_entity.cc',
'src/core/lib/iomgr/pollset.cc',
'src/core/lib/iomgr/pollset_custom.cc',
@ -320,11 +319,13 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/client_channel/client_channel_factory.cc',
'src/core/ext/filters/client_channel/client_channel_plugin.cc',
'src/core/ext/filters/client_channel/connector.cc',
'src/core/ext/filters/client_channel/global_subchannel_pool.cc',
'src/core/ext/filters/client_channel/health/health_check_client.cc',
'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
'src/core/ext/filters/client_channel/http_proxy.cc',
'src/core/ext/filters/client_channel/lb_policy.cc',
'src/core/ext/filters/client_channel/lb_policy_registry.cc',
'src/core/ext/filters/client_channel/local_subchannel_pool.cc',
'src/core/ext/filters/client_channel/parse_address.cc',
'src/core/ext/filters/client_channel/proxy_mapper.cc',
'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
@ -335,7 +336,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_index.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/deadline/deadline_filter.cc',
'src/core/ext/filters/client_channel/health/health.pb.c',
'src/core/tsi/fake_transport_security.cc',

@ -21,7 +21,6 @@ import setuptools
ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
CHANNELZ_PROTO = os.path.join(ROOT_DIR,
'../../proto/grpc/channelz/channelz.proto')
LICENSE = os.path.join(ROOT_DIR, '../../../LICENSE')
class Preprocess(setuptools.Command):
@ -42,8 +41,6 @@ class Preprocess(setuptools.Command):
shutil.copyfile(CHANNELZ_PROTO,
os.path.join(ROOT_DIR,
'grpc_channelz/v1/channelz.proto'))
if os.path.isfile(LICENSE):
shutil.copyfile(LICENSE, os.path.join(ROOT_DIR, 'LICENSE'))
class BuildPackageProtos(setuptools.Command):

@ -20,7 +20,6 @@ import setuptools
ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
HEALTH_PROTO = os.path.join(ROOT_DIR, '../../proto/grpc/health/v1/health.proto')
LICENSE = os.path.join(ROOT_DIR, '../../../LICENSE')
class Preprocess(setuptools.Command):
@ -41,8 +40,6 @@ class Preprocess(setuptools.Command):
shutil.copyfile(HEALTH_PROTO,
os.path.join(ROOT_DIR,
'grpc_health/v1/health.proto'))
if os.path.isfile(LICENSE):
shutil.copyfile(LICENSE, os.path.join(ROOT_DIR, 'LICENSE'))
class BuildPackageProtos(setuptools.Command):

@ -21,7 +21,6 @@ import setuptools
ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
REFLECTION_PROTO = os.path.join(
ROOT_DIR, '../../proto/grpc/reflection/v1alpha/reflection.proto')
LICENSE = os.path.join(ROOT_DIR, '../../../LICENSE')
class Preprocess(setuptools.Command):
@ -43,8 +42,6 @@ class Preprocess(setuptools.Command):
REFLECTION_PROTO,
os.path.join(ROOT_DIR,
'grpc_reflection/v1alpha/reflection.proto'))
if os.path.isfile(LICENSE):
shutil.copyfile(LICENSE, os.path.join(ROOT_DIR, 'LICENSE'))
class BuildPackageProtos(setuptools.Command):

@ -63,20 +63,11 @@ INSTALL_REQUIRES = (
'googleapis-common-protos>=1.5.5',
)
try:
import status_commands as _status_commands
# we are in the build environment, otherwise the above import fails
COMMAND_CLASS = {
# Run preprocess from the repository *before* doing any packaging!
'preprocess': _status_commands.Preprocess,
'build_package_protos': _NoOpCommand,
}
except ImportError:
COMMAND_CLASS = {
# wire up commands to no-op not to break the external dependencies
'preprocess': _NoOpCommand,
'build_package_protos': _NoOpCommand,
}
COMMAND_CLASS = {
# wire up commands to no-op not to break the external dependencies
'preprocess': _NoOpCommand,
'build_package_protos': _NoOpCommand,
}
setuptools.setup(
name='grpcio-status',

@ -1,39 +0,0 @@
# Copyright 2018 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Provides distutils command classes for the GRPC Python setup process."""
import os
import shutil
import setuptools
ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
LICENSE = os.path.join(ROOT_DIR, '../../../LICENSE')
class Preprocess(setuptools.Command):
"""Command to copy LICENSE from root directory."""
description = ''
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
if os.path.isfile(LICENSE):
shutil.copyfile(LICENSE, os.path.join(ROOT_DIR, 'LICENSE'))

@ -50,18 +50,10 @@ INSTALL_REQUIRES = (
'grpcio>={version}'.format(version=grpc_version.VERSION),
)
try:
import testing_commands as _testing_commands
# we are in the build environment, otherwise the above import fails
COMMAND_CLASS = {
# Run preprocess from the repository *before* doing any packaging!
'preprocess': _testing_commands.Preprocess,
}
except ImportError:
COMMAND_CLASS = {
# wire up commands to no-op not to break the external dependencies
'preprocess': _NoOpCommand,
}
COMMAND_CLASS = {
# wire up commands to no-op not to break the external dependencies
'preprocess': _NoOpCommand,
}
setuptools.setup(
name='grpcio-testing',

@ -1,39 +0,0 @@
# Copyright 2018 gRPC Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Provides distutils command classes for the GRPC Python setup process."""
import os
import shutil
import setuptools
ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
LICENSE = os.path.join(ROOT_DIR, '../../../LICENSE')
class Preprocess(setuptools.Command):
"""Command to copy LICENSE from root directory."""
description = ''
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
if os.path.isfile(LICENSE):
shutil.copyfile(LICENSE, os.path.join(ROOT_DIR, 'LICENSE'))

@ -43,8 +43,8 @@
s.add_development_dependency 'rake-compiler-dock', '~> 0.5.1'
s.add_development_dependency 'rspec', '~> 3.6'
s.add_development_dependency 'rubocop', '~> 0.49.1'
s.add_development_dependency 'signet', '~> 0.7.0'
s.add_development_dependency 'googleauth', '>= 0.5.1', '< 0.7'
s.add_development_dependency 'signet', '~> 0.7'
s.add_development_dependency 'googleauth', '>= 0.5.1', '< 0.10'
s.extensions = %w(src/ruby/ext/grpc/extconf.rb)

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

Loading…
Cancel
Save