Merge branch 'master' into feature/supportTVOS

pull/17731/head
Muxi Yan 6 years ago committed by GitHub
commit c3e1c72194
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      .pylintrc
  2. 100
      .pylintrc-examples
  3. 9
      .pylintrc-tests
  4. 26
      BUILD
  5. 737
      CMakeLists.txt
  6. 2249
      Makefile
  7. 6
      Rakefile
  8. 2
      bazel/cc_grpc_library.bzl
  9. 2
      bazel/generate_cc.bzl
  10. 3
      bazel/grpc_build_system.bzl
  11. 21
      bazel/grpc_deps.bzl
  12. 395
      build.yaml
  13. 10
      config.m4
  14. 10
      config.w32
  15. 3
      doc/g_stands_for.md
  16. 5
      doc/python/sphinx/grpc.rst
  17. 272
      etc/roots.pem
  18. 62
      examples/BUILD
  19. 110
      examples/cpp/compression/Makefile
  20. 84
      examples/cpp/compression/README.md
  21. 93
      examples/cpp/compression/greeter_client.cc
  22. 76
      examples/cpp/compression/greeter_server.cc
  23. 134
      examples/cpp/keyvaluestore/caching_interceptor.h
  24. 99
      examples/cpp/keyvaluestore/client.cc
  25. 97
      examples/cpp/keyvaluestore/server.cc
  26. 110
      examples/cpp/load_balancing/Makefile
  27. 64
      examples/cpp/load_balancing/README.md
  28. 90
      examples/cpp/load_balancing/greeter_client.cc
  29. 72
      examples/cpp/load_balancing/greeter_server.cc
  30. 96
      examples/cpp/metadata/Makefile
  31. 66
      examples/cpp/metadata/README.md
  32. 95
      examples/cpp/metadata/greeter_client.cc
  33. 94
      examples/cpp/metadata/greeter_server.cc
  34. 33
      examples/protos/keyvaluestore.proto
  35. 2
      examples/python/helloworld/greeter_client_with_options.py
  36. 6
      examples/python/metadata/README.md
  37. 134
      examples/python/metadata/helloworld_pb2.py
  38. 46
      examples/python/metadata/helloworld_pb2_grpc.py
  39. 48
      examples/python/metadata/metadata_client.py
  40. 56
      examples/python/metadata/metadata_server.py
  41. 5
      examples/ruby/greeter_server.rb
  42. 5
      examples/ruby/route_guide/route_guide_server.rb
  43. 18
      gRPC-C++.podspec
  44. 41
      gRPC-Core.podspec
  45. 2
      gRPC-ProtoRPC.podspec
  46. 2
      gRPC-RxLibrary.podspec
  47. 4
      gRPC.podspec
  48. 18
      grpc.gemspec
  49. 67
      grpc.gyp
  50. 3
      include/grpc/grpc.h
  51. 6
      include/grpc/grpc_security_constants.h
  52. 3
      include/grpc/impl/codegen/compression_types.h
  53. 9
      include/grpc/impl/codegen/grpc_types.h
  54. 5
      include/grpc/impl/codegen/port_platform.h
  55. 93
      include/grpcpp/alarm.h
  56. 116
      include/grpcpp/alarm_impl.h
  57. 11
      include/grpcpp/impl/codegen/byte_buffer.h
  58. 112
      include/grpcpp/impl/codegen/call_op_set.h
  59. 12
      include/grpcpp/impl/codegen/client_callback.h
  60. 7
      include/grpcpp/impl/codegen/client_context.h
  61. 30
      include/grpcpp/impl/codegen/client_interceptor.h
  62. 2
      include/grpcpp/impl/codegen/client_unary_call.h
  63. 161
      include/grpcpp/impl/codegen/interceptor.h
  64. 88
      include/grpcpp/impl/codegen/interceptor_common.h
  65. 4
      include/grpcpp/impl/codegen/method_handler_impl.h
  66. 12
      include/grpcpp/impl/codegen/server_callback.h
  67. 14
      include/grpcpp/impl/codegen/server_context.h
  68. 33
      include/grpcpp/impl/codegen/server_interceptor.h
  69. 2
      include/grpcpp/impl/codegen/server_interface.h
  70. 10
      include/grpcpp/impl/codegen/sync_stream.h
  71. 9
      include/grpcpp/impl/grpc_library.h
  72. 24
      include/grpcpp/support/client_interceptor.h
  73. 24
      include/grpcpp/support/interceptor.h
  74. 24
      include/grpcpp/support/server_interceptor.h
  75. 22
      package.xml
  76. 3
      requirements.bazel.txt
  77. 2
      setup.py
  78. 111
      src/compiler/objective_c_generator.cc
  79. 7
      src/compiler/objective_c_generator.h
  80. 21
      src/compiler/objective_c_plugin.cc
  81. 1068
      src/core/ext/filters/client_channel/client_channel.cc
  82. 2
      src/core/ext/filters/client_channel/client_channel_factory.cc
  83. 4
      src/core/ext/filters/client_channel/client_channel_factory.h
  84. 6
      src/core/ext/filters/client_channel/client_channel_plugin.cc
  85. 177
      src/core/ext/filters/client_channel/global_subchannel_pool.cc
  86. 68
      src/core/ext/filters/client_channel/global_subchannel_pool.h
  87. 2
      src/core/ext/filters/client_channel/lb_policy.cc
  88. 46
      src/core/ext/filters/client_channel/lb_policy.h
  89. 346
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  90. 2
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h
  91. 43
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc
  92. 2
      src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
  93. 30
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
  94. 51
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
  95. 61
      src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
  96. 259
      src/core/ext/filters/client_channel/lb_policy/xds/xds.cc
  97. 2
      src/core/ext/filters/client_channel/lb_policy/xds/xds_channel.h
  98. 43
      src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_secure.cc
  99. 2
      src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.h
  100. 163
      src/core/ext/filters/client_channel/lb_policy_factory.cc
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,3 +1,11 @@
[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
@ -82,3 +90,5 @@ disable=
# 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,

@ -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,

@ -1,3 +1,10 @@
[MASTER]
ignore=
src/python/grpcio_tests/tests/unit/beta,
src/python/grpcio_tests/tests/unit/framework,
src/python/grpcio_tests/tests/unit/framework/common,
src/python/grpcio_tests/tests/unit/framework/foundation,
[VARIABLES]
# TODO(https://github.com/PyCQA/pylint/issues/1345): How does the inspection
@ -115,3 +122,5 @@ disable=
# 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

@ -64,11 +64,11 @@ config_setting(
)
# This should be updated along with build.yaml
g_stands_for = "goose"
g_stands_for = "gold"
core_version = "7.0.0-dev"
version = "1.18.0-dev"
version = "1.19.0-dev"
GPR_PUBLIC_HDRS = [
"include/grpc/support/alloc.h",
@ -204,6 +204,7 @@ GRPCXX_PUBLIC_HDRS = [
"include/grpc++/support/sync_stream.h",
"include/grpc++/support/time.h",
"include/grpcpp/alarm.h",
"include/grpcpp/alarm_impl.h",
"include/grpcpp/channel.h",
"include/grpcpp/client_context.h",
"include/grpcpp/completion_queue.h",
@ -243,10 +244,13 @@ GRPCXX_PUBLIC_HDRS = [
"include/grpcpp/support/byte_buffer.h",
"include/grpcpp/support/channel_arguments.h",
"include/grpcpp/support/client_callback.h",
"include/grpcpp/support/client_interceptor.h",
"include/grpcpp/support/config.h",
"include/grpcpp/support/interceptor.h",
"include/grpcpp/support/proto_buffer_reader.h",
"include/grpcpp/support/proto_buffer_writer.h",
"include/grpcpp/support/server_callback.h",
"include/grpcpp/support/server_interceptor.h",
"include/grpcpp/support/slice.h",
"include/grpcpp/support/status.h",
"include/grpcpp/support/status_code_enum.h",
@ -720,6 +724,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",
@ -730,7 +736,6 @@ grpc_cc_library(
"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",
@ -869,6 +874,7 @@ grpc_cc_library(
"src/core/lib/iomgr/executor.h",
"src/core/lib/iomgr/gethostname.h",
"src/core/lib/iomgr/gevent_util.h",
"src/core/lib/iomgr/grpc_if_nametoindex.h",
"src/core/lib/iomgr/internal_errqueue.h",
"src/core/lib/iomgr/iocp_windows.h",
"src/core/lib/iomgr/iomgr.h",
@ -879,7 +885,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",
@ -1044,21 +1049,24 @@ 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_factory.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",
"src/core/ext/filters/client_channel/request_routing.cc",
"src/core/ext/filters/client_channel/resolver.cc",
"src/core/ext/filters/client_channel/resolver_registry.cc",
"src/core/ext/filters/client_channel/resolver_result_parsing.cc",
"src/core/ext/filters/client_channel/retry_throttle.cc",
"src/core/ext/filters/client_channel/server_address.cc",
"src/core/ext/filters/client_channel/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",
@ -1066,22 +1074,26 @@ 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",
"src/core/ext/filters/client_channel/request_routing.h",
"src/core/ext/filters/client_channel/resolver.h",
"src/core/ext/filters/client_channel/resolver_factory.h",
"src/core/ext/filters/client_channel/resolver_registry.h",
"src/core/ext/filters/client_channel/resolver_result_parsing.h",
"src/core/ext/filters/client_channel/retry_throttle.h",
"src/core/ext/filters/client_channel/server_address.h",
"src/core/ext/filters/client_channel/subchannel.h",
"src/core/ext/filters/client_channel/subchannel_index.h",
"src/core/ext/filters/client_channel/subchannel_pool_interface.h",
],
language = "c++",
deps = [

File diff suppressed because it is too large Load Diff

2249
Makefile

File diff suppressed because it is too large Load Diff

@ -105,7 +105,7 @@ task 'dlls' do
env_comp = "CC=#{opt[:cross]}-gcc "
env_comp += "CXX=#{opt[:cross]}-g++ "
env_comp += "LD=#{opt[:cross]}-gcc "
docker_for_windows "gem update --system --no-ri --no-doc && #{env} #{env_comp} make -j #{out} && #{opt[:cross]}-strip -x -S #{out} && cp #{out} #{opt[:out]}"
docker_for_windows "gem update --system --no-document && #{env} #{env_comp} make -j #{out} && #{opt[:cross]}-strip -x -S #{out} && cp #{out} #{opt[:out]}"
end
end
@ -124,10 +124,10 @@ task 'gem:native' do
"invoked on macos with ruby #{RUBY_VERSION}. The ruby macos artifact " \
"build should be running on ruby 2.5."
end
system "rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
system "rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0:2.2.2 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
else
Rake::Task['dlls'].execute
docker_for_windows "gem update --system --no-ri --no-doc && bundle && rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
docker_for_windows "gem update --system --no-document && bundle && rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0:2.2.2 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
end
end

@ -1,6 +1,6 @@
"""Generates and compiles C++ grpc stubs from proto_library rules."""
load("//:bazel/generate_cc.bzl", "generate_cc")
load("//bazel:generate_cc.bzl", "generate_cc")
def cc_grpc_library(name, srcs, deps, proto_only, well_known_protos, generate_mocks = False, use_external = False, **kwargs):
"""Generates C++ grpc classes from a .proto file.

@ -83,7 +83,7 @@ _generate_cc = rule(
attrs = {
"srcs": attr.label_list(
mandatory = True,
non_empty = True,
allow_empty = False,
providers = ["proto"],
),
"plugin": attr.label(

@ -23,6 +23,8 @@
# each change must be ported from one to the other.
#
load("//bazel:cc_grpc_library.bzl", "cc_grpc_library")
# The set of pollers to test against if a test exercises polling
POLLERS = ["epollex", "epoll1", "poll", "poll-cv"]
@ -111,7 +113,6 @@ def grpc_proto_plugin(name, srcs = [], deps = []):
deps = deps,
)
load("//:bazel/cc_grpc_library.bzl", "cc_grpc_library")
def grpc_proto_library(
name,

@ -93,17 +93,17 @@ def grpc_deps():
native.bind(
name = "opencensus-trace",
actual = "@io_opencensus_cpp//opencensus/trace:trace"
actual = "@io_opencensus_cpp//opencensus/trace:trace",
)
native.bind(
name = "opencensus-stats",
actual = "@io_opencensus_cpp//opencensus/stats:stats"
actual = "@io_opencensus_cpp//opencensus/stats:stats",
)
native.bind(
name = "opencensus-stats-test",
actual = "@io_opencensus_cpp//opencensus/stats:test_utils"
actual = "@io_opencensus_cpp//opencensus/stats:test_utils",
)
if "boringssl" not in native.existing_rules():
@ -124,8 +124,8 @@ def grpc_deps():
if "com_google_protobuf" not in native.existing_rules():
http_archive(
name = "com_google_protobuf",
strip_prefix = "protobuf-48cb18e5c419ddd23d9badcfe4e9df7bde1979b2",
url = "https://github.com/google/protobuf/archive/48cb18e5c419ddd23d9badcfe4e9df7bde1979b2.tar.gz",
strip_prefix = "protobuf-66dc42d891a4fc8e9190c524fd67961688a37bbe",
url = "https://github.com/google/protobuf/archive/66dc42d891a4fc8e9190c524fd67961688a37bbe.tar.gz",
)
if "com_github_nanopb_nanopb" not in native.existing_rules():
@ -177,16 +177,16 @@ def grpc_deps():
if "com_github_bazelbuild_bazeltoolchains" not in native.existing_rules():
http_archive(
name = "com_github_bazelbuild_bazeltoolchains",
strip_prefix = "bazel-toolchains-280edaa6f93623074513d2b426068de42e62ea4d",
strip_prefix = "bazel-toolchains-37419a124bdb9af2fec5b99a973d359b6b899b61",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/280edaa6f93623074513d2b426068de42e62ea4d.tar.gz",
"https://github.com/bazelbuild/bazel-toolchains/archive/280edaa6f93623074513d2b426068de42e62ea4d.tar.gz",
"https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/37419a124bdb9af2fec5b99a973d359b6b899b61.tar.gz",
"https://github.com/bazelbuild/bazel-toolchains/archive/37419a124bdb9af2fec5b99a973d359b6b899b61.tar.gz",
],
sha256 = "50c9df51f80cdf9ff8f2bc27620c155526b9ba67be95e8a686f32ff8898a06e2",
sha256 = "ee854b5de299138c1f4a2edb5573d22b21d975acfc7aa938f36d30b49ef97498",
)
if "io_opencensus_cpp" not in native.existing_rules():
http_archive(
http_archive(
name = "io_opencensus_cpp",
strip_prefix = "opencensus-cpp-fdf0f308b1631bb4a942e32ba5d22536a6170274",
url = "https://github.com/census-instrumentation/opencensus-cpp/archive/fdf0f308b1631bb4a942e32ba5d22536a6170274.tar.gz",
@ -199,7 +199,6 @@ def grpc_deps():
url = "https://github.com/google/upb/archive/9ce4a77f61c134bbed28bfd5be5cd7dc0e80f5e3.tar.gz",
)
# TODO: move some dependencies from "grpc_deps" here?
def grpc_test_only_deps():
"""Internal, not intended for use by packages that are consuming grpc.

File diff suppressed because it is too large Load Diff

@ -128,6 +128,8 @@ if test "$PHP_GRPC" != "no"; then
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 \
@ -139,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 \
@ -344,21 +345,24 @@ 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_factory.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 \
src/core/ext/filters/client_channel/request_routing.cc \
src/core/ext/filters/client_channel/resolver.cc \
src/core/ext/filters/client_channel/resolver_registry.cc \
src/core/ext/filters/client_channel/resolver_result_parsing.cc \
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/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 \

@ -103,6 +103,8 @@ if (PHP_GRPC != "no") {
"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 " +
@ -114,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 " +
@ -319,21 +320,24 @@ 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_factory.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 " +
"src\\core\\ext\\filters\\client_channel\\request_routing.cc " +
"src\\core\\ext\\filters\\client_channel\\resolver.cc " +
"src\\core\\ext\\filters\\client_channel\\resolver_registry.cc " +
"src\\core\\ext\\filters\\client_channel\\resolver_result_parsing.cc " +
"src\\core\\ext\\filters\\client_channel\\retry_throttle.cc " +
"src\\core\\ext\\filters\\client_channel\\server_address.cc " +
"src\\core\\ext\\filters\\client_channel\\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 " +

@ -17,4 +17,5 @@
- 1.15 'g' stands for ['glider'](https://github.com/grpc/grpc/tree/v1.15.x)
- 1.16 'g' stands for ['gao'](https://github.com/grpc/grpc/tree/v1.16.x)
- 1.17 'g' stands for ['gizmo'](https://github.com/grpc/grpc/tree/v1.17.x)
- 1.18 'g' stands for ['goose'](https://github.com/grpc/grpc/tree/master)
- 1.18 'g' stands for ['goose'](https://github.com/grpc/grpc/tree/v1.18.x)
- 1.19 'g' stands for ['gold'](https://github.com/grpc/grpc/tree/master)

@ -19,6 +19,11 @@ Go to `gRPC Python Examples <https://github.com/grpc/grpc/tree/master/examples/p
Module Contents
---------------
Version
^^^^^^^
The version string is available as :code:`grpc.__version__`.
Create Client
^^^^^^^^^^^^^

@ -329,36 +329,6 @@ OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH
QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
-----END CERTIFICATE-----
# Issuer: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association
# Subject: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association
# Label: "Visa eCommerce Root"
# Serial: 25952180776285836048024890241505565794
# MD5 Fingerprint: fc:11:b8:d8:08:93:30:00:6d:23:f9:7e:eb:52:1e:02
# SHA1 Fingerprint: 70:17:9b:86:8c:00:a4:fa:60:91:52:22:3f:9f:3e:32:bd:e0:05:62
# SHA256 Fingerprint: 69:fa:c9:bd:55:fb:0a:c7:8d:53:bb:ee:5c:f1:d5:97:98:9f:d0:aa:ab:20:a2:51:51:bd:f1:73:3e:e7:d1:22
-----BEGIN CERTIFICATE-----
MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr
MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl
cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw
CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h
dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l
cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h
2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E
lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV
ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq
299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t
vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL
dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF
AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR
zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3
LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd
7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw
++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
398znM/jra6O1I7mT1GvFpLgXPYHDw==
-----END CERTIFICATE-----
# Issuer: CN=AAA Certificate Services O=Comodo CA Limited
# Subject: CN=AAA Certificate Services O=Comodo CA Limited
# Label: "Comodo AAA Services root"
@ -4340,3 +4310,245 @@ rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV
57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg
Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
-----END CERTIFICATE-----
# Issuer: CN=GTS Root R1 O=Google Trust Services LLC
# Subject: CN=GTS Root R1 O=Google Trust Services LLC
# Label: "GTS Root R1"
# Serial: 146587175971765017618439757810265552097
# MD5 Fingerprint: 82:1a:ef:d4:d2:4a:f2:9f:e2:3d:97:06:14:70:72:85
# SHA1 Fingerprint: e1:c9:50:e6:ef:22:f8:4c:56:45:72:8b:92:20:60:d7:d5:a7:a3:e8
# SHA256 Fingerprint: 2a:57:54:71:e3:13:40:bc:21:58:1c:bd:2c:f1:3e:15:84:63:20:3e:ce:94:bc:f9:d3:cc:19:6b:f0:9a:54:72
-----BEGIN CERTIFICATE-----
MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBH
MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy
MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl
cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM
f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vX
mX7wCl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7
zUjwTcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0P
fyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtc
vfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4
Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUsp
zBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOO
Rc92wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW
k70paDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+
DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgF
lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
HQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBADiW
Cu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1
d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6Z
XPYfcX3v73svfuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZR
gyFmxhE+885H7pwoHyXa/6xmld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3
d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9bgsiG1eGZbYwE8na6SfZu6W0eX6Dv
J4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq4BjFbkerQUIpm/Zg
DdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWErtXvM
+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyy
F62ARPBopY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9
SQ98POyDGCBDTtWTurQ0sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdws
E3PYJ/HQcu51OyLemGhmW/HGY0dVHLqlCFF1pkgl
-----END CERTIFICATE-----
# Issuer: CN=GTS Root R2 O=Google Trust Services LLC
# Subject: CN=GTS Root R2 O=Google Trust Services LLC
# Label: "GTS Root R2"
# Serial: 146587176055767053814479386953112547951
# MD5 Fingerprint: 44:ed:9a:0e:a4:09:3b:00:f2:ae:4c:a3:c6:61:b0:8b
# SHA1 Fingerprint: d2:73:96:2a:2a:5e:39:9f:73:3f:e1:c7:1e:64:3f:03:38:34:fc:4d
# SHA256 Fingerprint: c4:5d:7b:b0:8e:6d:67:e6:2e:42:35:11:0b:56:4e:5f:78:fd:92:ef:05:8c:84:0a:ea:4e:64:55:d7:58:5c:60
-----BEGIN CERTIFICATE-----
MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBH
MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy
MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl
cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv
CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3Kg
GjSY6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9Bu
XvAuMC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOd
re7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXu
PuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1
mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K
8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqj
x5RWIr9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsR
nTKaG73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0
kzCqgc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9Ok
twIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
HQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBALZp
8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT
vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiT
z9D2PGcDFWEJ+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiA
pJiS4wGWAqoC7o87xdFtCjMwc3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvb
pxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3DaWsYDQvTtN6LwG1BUSw7YhN4ZKJmB
R64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5rn/WkhLx3+WuXrD5R
RaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56GtmwfuNmsk
0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC
5AwiWVIQ7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiF
izoHCBy69Y9Vmhh1fuXsgWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLn
yOd/xCxgXS/Dr55FBcOEArf9LAhST4Ldo/DUhgkC
-----END CERTIFICATE-----
# Issuer: CN=GTS Root R3 O=Google Trust Services LLC
# Subject: CN=GTS Root R3 O=Google Trust Services LLC
# Label: "GTS Root R3"
# Serial: 146587176140553309517047991083707763997
# MD5 Fingerprint: 1a:79:5b:6b:04:52:9c:5d:c7:74:33:1b:25:9a:f9:25
# SHA1 Fingerprint: 30:d4:24:6f:07:ff:db:91:89:8a:0b:e9:49:66:11:eb:8c:5e:46:e5
# SHA256 Fingerprint: 15:d5:b8:77:46:19:ea:7d:54:ce:1c:a6:d0:b0:c4:03:e0:37:a9:17:f1:31:e8:a0:4e:1e:6b:7a:71:ba:bc:e5
-----BEGIN CERTIFICATE-----
MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQsw
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQA
IgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout
736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2A
DDL24CejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
DgQWBBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFuk
fCPAlaUs3L6JbyO5o91lAFJekazInXJ0glMLfalAvWhgxeG4VDvBNhcl2MG9AjEA
njWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOaKaqW04MjyaR7YbPMAuhd
-----END CERTIFICATE-----
# Issuer: CN=GTS Root R4 O=Google Trust Services LLC
# Subject: CN=GTS Root R4 O=Google Trust Services LLC
# Label: "GTS Root R4"
# Serial: 146587176229350439916519468929765261721
# MD5 Fingerprint: 5d:b6:6a:c4:60:17:24:6a:1a:99:a8:4b:ee:5e:b4:26
# SHA1 Fingerprint: 2a:1d:60:27:d9:4a:b1:0a:1c:4d:91:5c:cd:33:a0:cb:3e:2d:54:cb
# SHA256 Fingerprint: 71:cc:a5:39:1f:9e:79:4b:04:80:25:30:b3:63:e1:21:da:8a:30:43:bb:26:66:2f:ea:4d:ca:7f:c9:51:a4:bd
-----BEGIN CERTIFICATE-----
MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA
IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu
hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l
xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0
CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx
sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w==
-----END CERTIFICATE-----
# Issuer: CN=UCA Global G2 Root O=UniTrust
# Subject: CN=UCA Global G2 Root O=UniTrust
# Label: "UCA Global G2 Root"
# Serial: 124779693093741543919145257850076631279
# MD5 Fingerprint: 80:fe:f0:c4:4a:f0:5c:62:32:9f:1c:ba:78:a9:50:f8
# SHA1 Fingerprint: 28:f9:78:16:19:7a:ff:18:25:18:aa:44:fe:c1:a0:ce:5c:b6:4c:8a
# SHA256 Fingerprint: 9b:ea:11:c9:76:fe:01:47:64:c1:be:56:a6:f9:14:b5:a5:60:31:7a:bd:99:88:39:33:82:e5:16:1a:a0:49:3c
-----BEGIN CERTIFICATE-----
MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9
MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH
bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x
CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds
b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr
b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9
kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm
VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R
VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc
C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj
tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY
D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv
j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl
NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6
iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP
O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/
BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV
ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj
L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5
1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl
1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU
b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV
PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj
y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb
EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg
DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI
+Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy
YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX
UB+K+wb1whnw0A==
-----END CERTIFICATE-----
# Issuer: CN=UCA Extended Validation Root O=UniTrust
# Subject: CN=UCA Extended Validation Root O=UniTrust
# Label: "UCA Extended Validation Root"
# Serial: 106100277556486529736699587978573607008
# MD5 Fingerprint: a1:f3:5f:43:c6:34:9b:da:bf:8c:7e:05:53:ad:96:e2
# SHA1 Fingerprint: a3:a1:b0:6f:24:61:23:4a:e3:36:a5:c2:37:fc:a6:ff:dd:f0:d7:3a
# SHA256 Fingerprint: d4:3a:f9:b3:54:73:75:5c:96:84:fc:06:d7:d8:cb:70:ee:5c:28:e7:73:fb:29:4e:b4:1e:e7:17:22:92:4d:24
-----BEGIN CERTIFICATE-----
MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH
MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF
eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx
MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV
BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog
D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS
sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop
O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk
sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi
c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj
VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz
KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/
TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G
sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs
1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD
fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T
AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN
l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR
ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ
VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5
c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp
4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s
t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj
2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO
vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C
xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx
cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM
fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax
-----END CERTIFICATE-----
# Issuer: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036
# Subject: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036
# Label: "Certigna Root CA"
# Serial: 269714418870597844693661054334862075617
# MD5 Fingerprint: 0e:5c:30:62:27:eb:5b:bc:d7:ae:62:ba:e9:d5:df:77
# SHA1 Fingerprint: 2d:0d:52:14:ff:9e:ad:99:24:01:74:20:47:6e:6c:85:27:27:f5:43
# SHA256 Fingerprint: d4:8d:3d:23:ee:db:50:a4:59:e5:51:97:60:1c:27:77:4b:9d:7b:18:c9:4d:5a:05:95:11:a1:02:50:b9:31:68
-----BEGIN CERTIFICATE-----
MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw
WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw
MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x
MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD
VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX
BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO
ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M
CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu
I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm
TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh
C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf
ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz
IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT
Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k
JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5
hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB
GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of
1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov
L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo
dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr
aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq
hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L
6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG
HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6
0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB
lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi
o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1
gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v
faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63
Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh
jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw
3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
-----END CERTIFICATE-----

@ -38,6 +38,11 @@ grpc_proto_library(
srcs = ["protos/route_guide.proto"],
)
grpc_proto_library(
name = "keyvaluestore",
srcs = ["protos/keyvaluestore.proto"],
)
cc_binary(
name = "greeter_client",
srcs = ["cpp/helloworld/greeter_client.cc"],
@ -51,3 +56,60 @@ cc_binary(
defines = ["BAZEL_BUILD"],
deps = [":helloworld", "//:grpc++"],
)
cc_binary(
name = "metadata_client",
srcs = ["cpp/metadata/greeter_client.cc"],
defines = ["BAZEL_BUILD"],
deps = [":helloworld", "//:grpc++"],
)
cc_binary(
name = "metadata_server",
srcs = ["cpp/metadata/greeter_server.cc"],
defines = ["BAZEL_BUILD"],
deps = [":helloworld", "//:grpc++"],
)
cc_binary(
name = "lb_client",
srcs = ["cpp/load_balancing/greeter_client.cc"],
defines = ["BAZEL_BUILD"],
deps = [":helloworld", "//:grpc++"],
)
cc_binary(
name = "lb_server",
srcs = ["cpp/load_balancing/greeter_server.cc"],
defines = ["BAZEL_BUILD"],
deps = [":helloworld", "//:grpc++"],
)
cc_binary(
name = "compression_client",
srcs = ["cpp/compression/greeter_client.cc"],
defines = ["BAZEL_BUILD"],
deps = [":helloworld", "//:grpc++"],
)
cc_binary(
name = "compression_server",
srcs = ["cpp/compression/greeter_server.cc"],
defines = ["BAZEL_BUILD"],
deps = [":helloworld", "//:grpc++"],
)
cc_binary(
name = "keyvaluestore_client",
srcs = ["cpp/keyvaluestore/caching_interceptor.h",
"cpp/keyvaluestore/client.cc"],
defines = ["BAZEL_BUILD"],
deps = [":keyvaluestore", "//:grpc++"],
)
cc_binary(
name = "keyvaluestore_server",
srcs = ["cpp/keyvaluestore/server.cc"],
defines = ["BAZEL_BUILD"],
deps = [":keyvaluestore", "//:grpc++"],
)

@ -0,0 +1,110 @@
#
# 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.
#
HOST_SYSTEM = $(shell uname | cut -f 1 -d_)
SYSTEM ?= $(HOST_SYSTEM)
CXX = g++
CPPFLAGS += `pkg-config --cflags protobuf grpc`
CXXFLAGS += -std=c++11
ifeq ($(SYSTEM),Darwin)
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
-lgrpc++_reflection\
-ldl
else
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
-Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed\
-ldl
endif
PROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`
PROTOS_PATH = ../../protos
vpath %.proto $(PROTOS_PATH)
all: system-check greeter_client greeter_server
greeter_client: helloworld.pb.o helloworld.grpc.pb.o greeter_client.o
$(CXX) $^ $(LDFLAGS) -o $@
greeter_server: helloworld.pb.o helloworld.grpc.pb.o greeter_server.o
$(CXX) $^ $(LDFLAGS) -o $@
.PRECIOUS: %.grpc.pb.cc
%.grpc.pb.cc: %.proto
$(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $<
.PRECIOUS: %.pb.cc
%.pb.cc: %.proto
$(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $<
clean:
rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server
# The following is to test your system and ensure a smoother experience.
# They are by no means necessary to actually compile a grpc-enabled software.
PROTOC_CMD = which $(PROTOC)
PROTOC_CHECK_CMD = $(PROTOC) --version | grep -q libprotoc.3
PLUGIN_CHECK_CMD = which $(GRPC_CPP_PLUGIN)
HAS_PROTOC = $(shell $(PROTOC_CMD) > /dev/null && echo true || echo false)
ifeq ($(HAS_PROTOC),true)
HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false)
endif
HAS_PLUGIN = $(shell $(PLUGIN_CHECK_CMD) > /dev/null && echo true || echo false)
SYSTEM_OK = false
ifeq ($(HAS_VALID_PROTOC),true)
ifeq ($(HAS_PLUGIN),true)
SYSTEM_OK = true
endif
endif
system-check:
ifneq ($(HAS_VALID_PROTOC),true)
@echo " DEPENDENCY ERROR"
@echo
@echo "You don't have protoc 3.0.0 installed in your path."
@echo "Please install Google protocol buffers 3.0.0 and its compiler."
@echo "You can find it here:"
@echo
@echo " https://github.com/google/protobuf/releases/tag/v3.0.0"
@echo
@echo "Here is what I get when trying to evaluate your version of protoc:"
@echo
-$(PROTOC) --version
@echo
@echo
endif
ifneq ($(HAS_PLUGIN),true)
@echo " DEPENDENCY ERROR"
@echo
@echo "You don't have the grpc c++ protobuf plugin installed in your path."
@echo "Please install grpc. You can find it here:"
@echo
@echo " https://github.com/grpc/grpc"
@echo
@echo "Here is what I get when trying to detect if you have the plugin:"
@echo
-which $(GRPC_CPP_PLUGIN)
@echo
@echo
endif
ifneq ($(SYSTEM_OK),true)
@false
endif

@ -0,0 +1,84 @@
# gRPC C++ Message Compression Tutorial
### Prerequisite
Make sure you have run the [hello world example](../helloworld) or understood the basics of gRPC. We will not dive into the details that have been discussed in the hello world example.
### Get the tutorial source code
The example code for this and our other examples lives in the `examples` directory. Clone this repository to your local machine by running the following command:
```sh
$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
```
Change your current directory to examples/cpp/compression
```sh
$ cd examples/cpp/compression/
```
### Generating gRPC code
To generate the client and server side interfaces:
```sh
$ make helloworld.grpc.pb.cc helloworld.pb.cc
```
Which internally invokes the proto-compiler as:
```sh
$ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto
$ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
```
### Writing a client and a server
The client and the server can be based on the hello world example.
Additionally, we can configure the compression settings.
In the client, set the default compression algorithm of the channel via the channel arg.
```cpp
ChannelArguments args;
// Set the default compression algorithm for the channel.
args.SetCompressionAlgorithm(GRPC_COMPRESS_GZIP);
GreeterClient greeter(grpc::CreateCustomChannel(
"localhost:50051", grpc::InsecureChannelCredentials(), args));
```
Each call's compression configuration can be overwritten by client context.
```cpp
// Overwrite the call's compression algorithm to DEFLATE.
context.set_compression_algorithm(GRPC_COMPRESS_DEFLATE);
```
In the server, set the default compression algorithm via the server builder.
```cpp
ServerBuilder builder;
// Set the default compression algorithm for the server.
builder.SetDefaultCompressionAlgorithm(GRPC_COMPRESS_GZIP);
```
Each call's compression configuration can be overwritten by server context.
```cpp
// Overwrite the call's compression algorithm to DEFLATE.
context->set_compression_algorithm(GRPC_COMPRESS_DEFLATE);
```
For a working example, refer to [greeter_client.cc](greeter_client.cc) and [greeter_server.cc](greeter_server.cc).
Build and run the (compressing) client and the server by the following commands.
```sh
make
./greeter_server
```
```sh
./greeter_client
```

@ -0,0 +1,93 @@
/*
*
* 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 <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#endif
using grpc::Channel;
using grpc::ChannelArguments;
using grpc::ClientContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
class GreeterClient {
public:
GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}
// Assembles the client's payload, sends it and presents the response back
// from the server.
std::string SayHello(const std::string& user) {
// Data we are sending to the server.
HelloRequest request;
request.set_name(user);
// Container for the data we expect from the server.
HelloReply reply;
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context;
// Overwrite the call's compression algorithm to DEFLATE.
context.set_compression_algorithm(GRPC_COMPRESS_DEFLATE);
// The actual RPC.
Status status = stub_->SayHello(&context, request, &reply);
// Act upon its status.
if (status.ok()) {
return reply.message();
} else {
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RPC failed";
}
}
private:
std::unique_ptr<Greeter::Stub> stub_;
};
int main(int argc, char** argv) {
// Instantiate the client. It requires a channel, out of which the actual RPCs
// 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()).
ChannelArguments args;
// Set the default compression algorithm for the channel.
args.SetCompressionAlgorithm(GRPC_COMPRESS_GZIP);
GreeterClient greeter(grpc::CreateCustomChannel(
"localhost:50051", grpc::InsecureChannelCredentials(), args));
std::string user("world");
std::string reply = greeter.SayHello(user);
std::cout << "Greeter received: " << reply << std::endl;
return 0;
}

@ -0,0 +1,76 @@
/*
*
* 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 <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#endif
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
// Overwrite the call's compression algorithm to DEFLATE.
context->set_compression_algorithm(GRPC_COMPRESS_DEFLATE);
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
return Status::OK;
}
};
void RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;
ServerBuilder builder;
// Set the default compression algorithm for the server.
builder.SetDefaultCompressionAlgorithm(GRPC_COMPRESS_GZIP);
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
server->Wait();
}
int main(int argc, char** argv) {
RunServer();
return 0;
}

@ -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);
}
};

@ -0,0 +1,99 @@
/*
*
* 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 <iostream>
#include <memory>
#include <string>
#include <vector>
#include <grpcpp/grpcpp.h>
#include "caching_interceptor.h"
#ifdef BAZEL_BUILD
#include "examples/protos/keyvaluestore.grpc.pb.h"
#else
#include "keyvaluestore.grpc.pb.h"
#endif
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using keyvaluestore::KeyValueStore;
using keyvaluestore::Request;
using keyvaluestore::Response;
class KeyValueStoreClient {
public:
KeyValueStoreClient(std::shared_ptr<Channel> channel)
: stub_(KeyValueStore::NewStub(channel)) {}
// Requests each key in the vector and displays the key and its corresponding
// value as a pair
void GetValues(const std::vector<std::string>& keys) {
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context;
auto stream = stub_->GetValues(&context);
for (const auto& key : keys) {
// Key we are sending to the server.
Request request;
request.set_key(key);
stream->Write(request);
// Get the value for the sent key
Response response;
stream->Read(&response);
std::cout << key << " : " << response.value() << "\n";
}
stream->WritesDone();
Status status = stream->Finish();
if (!status.ok()) {
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
std::cout << "RPC failed";
}
}
private:
std::unique_ptr<KeyValueStore::Stub> stub_;
};
int main(int argc, char** argv) {
// Instantiate the client. It requires a channel, out of which the actual RPCs
// 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()).
// 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;
}

@ -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 <iostream>
#include <memory>
#include <string>
#include <vector>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/keyvaluestore.grpc.pb.h"
#else
#include "keyvaluestore.grpc.pb.h"
#endif
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::ServerReaderWriter;
using grpc::Status;
using keyvaluestore::KeyValueStore;
using keyvaluestore::Request;
using keyvaluestore::Response;
struct kv_pair {
const char* key;
const char* value;
};
static const kv_pair kvs_map[] = {
{"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"},
{"key4", "value4"}, {"key5", "value5"},
};
const char* get_value_from_map(const char* key) {
for (size_t i = 0; i < sizeof(kvs_map) / sizeof(kv_pair); ++i) {
if (strcmp(key, kvs_map[i].key) == 0) {
return kvs_map[i].value;
}
}
return "";
}
// Logic and data behind the server's behavior.
class KeyValueStoreServiceImpl final : public KeyValueStore::Service {
Status GetValues(ServerContext* context,
ServerReaderWriter<Response, Request>* stream) override {
Request request;
while (stream->Read(&request)) {
Response response;
response.set_value(get_value_from_map(request.key().c_str()));
stream->Write(response);
}
return Status::OK;
}
};
void RunServer() {
std::string server_address("0.0.0.0:50051");
KeyValueStoreServiceImpl service;
ServerBuilder builder;
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case, it corresponds to an *synchronous* service.
builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
server->Wait();
}
int main(int argc, char** argv) {
RunServer();
return 0;
}

@ -0,0 +1,110 @@
#
# 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.
#
HOST_SYSTEM = $(shell uname | cut -f 1 -d_)
SYSTEM ?= $(HOST_SYSTEM)
CXX = g++
CPPFLAGS += `pkg-config --cflags protobuf grpc`
CXXFLAGS += -std=c++11
ifeq ($(SYSTEM),Darwin)
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
-lgrpc++_reflection\
-ldl
else
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
-Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed\
-ldl
endif
PROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`
PROTOS_PATH = ../../protos
vpath %.proto $(PROTOS_PATH)
all: system-check greeter_client greeter_server
greeter_client: helloworld.pb.o helloworld.grpc.pb.o greeter_client.o
$(CXX) $^ $(LDFLAGS) -o $@
greeter_server: helloworld.pb.o helloworld.grpc.pb.o greeter_server.o
$(CXX) $^ $(LDFLAGS) -o $@
.PRECIOUS: %.grpc.pb.cc
%.grpc.pb.cc: %.proto
$(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $<
.PRECIOUS: %.pb.cc
%.pb.cc: %.proto
$(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $<
clean:
rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server
# The following is to test your system and ensure a smoother experience.
# They are by no means necessary to actually compile a grpc-enabled software.
PROTOC_CMD = which $(PROTOC)
PROTOC_CHECK_CMD = $(PROTOC) --version | grep -q libprotoc.3
PLUGIN_CHECK_CMD = which $(GRPC_CPP_PLUGIN)
HAS_PROTOC = $(shell $(PROTOC_CMD) > /dev/null && echo true || echo false)
ifeq ($(HAS_PROTOC),true)
HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false)
endif
HAS_PLUGIN = $(shell $(PLUGIN_CHECK_CMD) > /dev/null && echo true || echo false)
SYSTEM_OK = false
ifeq ($(HAS_VALID_PROTOC),true)
ifeq ($(HAS_PLUGIN),true)
SYSTEM_OK = true
endif
endif
system-check:
ifneq ($(HAS_VALID_PROTOC),true)
@echo " DEPENDENCY ERROR"
@echo
@echo "You don't have protoc 3.0.0 installed in your path."
@echo "Please install Google protocol buffers 3.0.0 and its compiler."
@echo "You can find it here:"
@echo
@echo " https://github.com/google/protobuf/releases/tag/v3.0.0"
@echo
@echo "Here is what I get when trying to evaluate your version of protoc:"
@echo
-$(PROTOC) --version
@echo
@echo
endif
ifneq ($(HAS_PLUGIN),true)
@echo " DEPENDENCY ERROR"
@echo
@echo "You don't have the grpc c++ protobuf plugin installed in your path."
@echo "Please install grpc. You can find it here:"
@echo
@echo " https://github.com/grpc/grpc"
@echo
@echo "Here is what I get when trying to detect if you have the plugin:"
@echo
-which $(GRPC_CPP_PLUGIN)
@echo
@echo
endif
ifneq ($(SYSTEM_OK),true)
@false
endif

@ -0,0 +1,64 @@
# gRPC C++ Load Balancing Tutorial
### Prerequisite
Make sure you have run the [hello world example](../helloworld) or understood the basics of gRPC. We will not dive into the details that have been discussed in the hello world example.
### Get the tutorial source code
The example code for this and our other examples lives in the `examples` directory. Clone this repository to your local machine by running the following command:
```sh
$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
```
Change your current directory to examples/cpp/load_balancing
```sh
$ cd examples/cpp/load_balancing/
```
### Generating gRPC code
To generate the client and server side interfaces:
```sh
$ make helloworld.grpc.pb.cc helloworld.pb.cc
```
Which internally invokes the proto-compiler as:
```sh
$ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto
$ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
```
### Writing a client and a server
The client and the server can be based on the hello world example.
Additionally, we can configure the load balancing policy. (To see what load balancing policies are available, check out [this folder](https://github.com/grpc/grpc/tree/master/src/core/ext/filters/client_channel/lb_policy).)
In the client, set the load balancing policy of the channel via the channel arg (to, for example, Round Robin).
```cpp
ChannelArguments args;
// Set the load balancing policy for the channel.
args.SetLoadBalancingPolicyName("round_robin");
GreeterClient greeter(grpc::CreateCustomChannel(
"localhost:50051", grpc::InsecureChannelCredentials(), args));
```
For a working example, refer to [greeter_client.cc](greeter_client.cc) and [greeter_server.cc](greeter_server.cc).
Build and run the client and the server with the following commands.
```sh
make
./greeter_server
```
```sh
./greeter_client
```
(Note that the case in this example is trivial because there is only one server resolved from the name.)

@ -0,0 +1,90 @@
/*
*
* 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 <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#endif
using grpc::Channel;
using grpc::ChannelArguments;
using grpc::ClientContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
class GreeterClient {
public:
GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}
// Assembles the client's payload, sends it and presents the response back
// from the server.
std::string SayHello(const std::string& user) {
// Data we are sending to the server.
HelloRequest request;
request.set_name(user);
// Container for the data we expect from the server.
HelloReply reply;
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context;
// The actual RPC.
Status status = stub_->SayHello(&context, request, &reply);
// Act upon its status.
if (status.ok()) {
return reply.message();
} else {
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RPC failed";
}
}
private:
std::unique_ptr<Greeter::Stub> stub_;
};
int main(int argc, char** argv) {
// Instantiate the client. It requires a channel, out of which the actual RPCs
// 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()).
ChannelArguments args;
// Set the load balancing policy for the channel.
args.SetLoadBalancingPolicyName("round_robin");
GreeterClient greeter(grpc::CreateCustomChannel(
"localhost:50051", grpc::InsecureChannelCredentials(), args));
std::string user("world");
std::string reply = greeter.SayHello(user);
std::cout << "Greeter received: " << reply << std::endl;
return 0;
}

@ -0,0 +1,72 @@
/*
*
* 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 <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#endif
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
return Status::OK;
}
};
void RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;
ServerBuilder builder;
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
server->Wait();
}
int main(int argc, char** argv) {
RunServer();
return 0;
}

@ -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.
#
HOST_SYSTEM = $(shell uname | cut -f 1 -d_)
SYSTEM ?= $(HOST_SYSTEM)
CXX = g++
CPPFLAGS += `pkg-config --cflags protobuf grpc`
CXXFLAGS += -std=c++11
ifeq ($(SYSTEM),Darwin)
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
-lgrpc++_reflection\
-ldl
else
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
-Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed\
-ldl
endif
PROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`
PROTOS_PATH = ../../protos
vpath %.proto $(PROTOS_PATH)
all: system-check greeter_client greeter_server
greeter_client: helloworld.pb.o helloworld.grpc.pb.o greeter_client.o
$(CXX) $^ $(LDFLAGS) -o $@
greeter_server: helloworld.pb.o helloworld.grpc.pb.o greeter_server.o
$(CXX) $^ $(LDFLAGS) -o $@
.PRECIOUS: %.grpc.pb.cc
%.grpc.pb.cc: %.proto
$(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $<
.PRECIOUS: %.pb.cc
%.pb.cc: %.proto
$(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $<
clean:
rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server
# The following is to test your system and ensure a smoother experience.
# They are by no means necessary to actually compile a grpc-enabled software.
PROTOC_CMD = which $(PROTOC)
PROTOC_CHECK_CMD = $(PROTOC) --version | grep -q libprotoc.3
PLUGIN_CHECK_CMD = which $(GRPC_CPP_PLUGIN)
HAS_PROTOC = $(shell $(PROTOC_CMD) > /dev/null && echo true || echo false)
ifeq ($(HAS_PROTOC),true)
HAS_VALID_PROTOC = $(shell $(PROTOC_CHECK_CMD) 2> /dev/null && echo true || echo false)
endif
HAS_PLUGIN = $(shell $(PLUGIN_CHECK_CMD) > /dev/null && echo true || echo false)
SYSTEM_OK = false
ifeq ($(HAS_VALID_PROTOC),true)
ifeq ($(HAS_PLUGIN),true)
SYSTEM_OK = true
endif
endif
system-check:
ifneq ($(HAS_VALID_PROTOC),true)
@echo " DEPENDENCY ERROR"
@echo
@echo "You don't have protoc 3.0.0 installed in your path."
@echo "Please install Google protocol buffers 3.0.0 and its compiler."
@echo "You can find it here:"
@echo
@echo " https://github.com/google/protobuf/releases/tag/v3.0.0"
@echo
@echo "Here is what I get when trying to evaluate your version of protoc:"
@echo
-$(PROTOC) --version
@echo
@echo
endif
ifneq ($(HAS_PLUGIN),true)
@echo " DEPENDENCY ERROR"
@echo
@echo "You don't have the grpc c++ protobuf plugin installed in your path."
@echo "Please install grpc. You can find it here:"
@echo
@echo " https://github.com/grpc/grpc"
@echo
@echo "Here is what I get when trying to detect if you have the plugin:"
@echo
-which $(GRPC_CPP_PLUGIN)
@echo
@echo
endif
ifneq ($(SYSTEM_OK),true)
@false
endif

@ -0,0 +1,66 @@
# Metadata Example
## Overview
This example shows you how to add custom headers on the client and server and
how to access them.
Custom metadata must follow the "Custom-Metadata" format listed in
https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md, with the
exception of binary headers, which don't have to be base64 encoded.
### Get the tutorial source code
The example code for this and our other examples lives in the `examples` directory. Clone this repository to your local machine by running the following command:
```sh
$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
```
Change your current directory to examples/cpp/metadata
```sh
$ cd examples/cpp/metadata
```
### Generating gRPC code
To generate the client and server side interfaces:
```sh
$ make helloworld.grpc.pb.cc helloworld.pb.cc
```
Which internally invokes the proto-compiler as:
```sh
$ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto
$ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
```
### Try it!
Build client and server:
```sh
$ make
```
Run the server, which will listen on port 50051:
```sh
$ ./greeter_server
```
Run the client (in a different terminal):
```sh
$ ./greeter_client
```
If things go smoothly, you will see in the client terminal:
"Client received initial metadata from server: initial metadata value"
"Client received trailing metadata from server: trailing metadata value"
"Client received message: Hello World"
And in the server terminal:
"Header key: custom-bin , value: 01234567"
"Header key: custom-header , value: Custom Value"
"Header key: user-agent , value: grpc-c++/1.16.0-dev grpc-c/6.0.0-dev (linux; chttp2; gao)"
We did not add the user-agent metadata as a custom header. This shows how
the gRPC framework adds some headers under the hood that may show up in the
metadata map.

@ -0,0 +1,95 @@
/*
*
* 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 <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#endif
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
class CustomHeaderClient {
public:
CustomHeaderClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}
// Assembles the client's payload, sends it and presents the response back
// from the server.
std::string SayHello(const std::string& user) {
// Data we are sending to the server.
HelloRequest request;
request.set_name(user);
// Container for the data we expect from the server.
HelloReply reply;
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context;
// Setting custom metadata to be sent to the server
context.AddMetadata("custom-header", "Custom Value");
// Setting custom binary metadata
char bytes[8] = {'\0', '\1', '\2', '\3',
'\4', '\5', '\6', '\7'};
context.AddMetadata("custom-bin", grpc::string(bytes, 8));
// The actual RPC.
Status status = stub_->SayHello(&context, request, &reply);
// Act upon its status.
if (status.ok()) {
std::cout << "Client received initial metadata from server: " << context.GetServerInitialMetadata().find("custom-server-metadata")->second << std::endl;
std::cout << "Client received trailing metadata from server: " << context.GetServerTrailingMetadata().find("custom-trailing-metadata")->second << std::endl;
return reply.message();
} else {
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RPC failed";
}
}
private:
std::unique_ptr<Greeter::Stub> stub_;
};
int main(int argc, char** argv) {
// Instantiate the client. It requires a channel, out of which the actual RPCs
// 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()).
CustomHeaderClient greeter(grpc::CreateChannel(
"localhost:50051", grpc::InsecureChannelCredentials()));
std::string user("world");
std::string reply = greeter.SayHello(user);
std::cout << "Client received message: " << reply << std::endl;
return 0;
}

@ -0,0 +1,94 @@
/*
*
* 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 <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#endif
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello ");
// Get the client's initial metadata
std::cout << "Client metadata: " << std::endl;
const std::multimap<grpc::string_ref, grpc::string_ref> metadata = context->client_metadata();
for (auto iter = metadata.begin(); iter != metadata.end(); ++iter) {
std::cout << "Header key: " << iter->first << ", value: ";
// Check for binary value
size_t isbin = iter->first.find("-bin");
if ((isbin != std::string::npos) && (isbin + 4 == iter->first.size())) {
std::cout << std::hex;
for (auto c : iter->second) {
std::cout << static_cast<unsigned int>(c);
}
std::cout << std::dec;
} else {
std::cout << iter->second;
}
std::cout << std::endl;
}
context->AddInitialMetadata("custom-server-metadata", "initial metadata value");
context->AddTrailingMetadata("custom-trailing-metadata", "trailing metadata value");
reply->set_message(prefix + request->name());
return Status::OK;
}
};
void RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;
ServerBuilder builder;
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
server->Wait();
}
int main(int argc, char** argv) {
RunServer();
return 0;
}

@ -0,0 +1,33 @@
// 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.
syntax = "proto3";
package keyvaluestore;
// A simple key-value storage service
service KeyValueStore {
// Provides a value for each key request
rpc GetValues (stream Request) returns (stream Response) {}
}
// The request message containing the key
message Request {
string key = 1;
}
// The response message containing the value associated with the key
message Response {
string value = 1;
}

@ -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

@ -0,0 +1,6 @@
An example showing how to add custom HTTP2 headers (or [metadata](https://grpc.io/grpc/python/glossary.html) in gRPC glossary)
HTTP2 supports initial headers and trailing headers, which gRPC utilizes both of them ([learn more](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md)).
More complete documentation lives at [grpc.io](https://grpc.io/docs/tutorials/basic/python.html).
For API reference please see [API](https://grpc.io/grpc/python/grpc.html).

@ -0,0 +1,134 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: helloworld.proto
import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name='helloworld.proto',
package='helloworld',
syntax='proto3',
serialized_pb=_b('\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3')
)
_HELLOREQUEST = _descriptor.Descriptor(
name='HelloRequest',
full_name='helloworld.HelloRequest',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='name', full_name='helloworld.HelloRequest.name', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=32,
serialized_end=60,
)
_HELLOREPLY = _descriptor.Descriptor(
name='HelloReply',
full_name='helloworld.HelloReply',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='message', full_name='helloworld.HelloReply.message', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=62,
serialized_end=91,
)
DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST
DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict(
DESCRIPTOR = _HELLOREQUEST,
__module__ = 'helloworld_pb2'
# @@protoc_insertion_point(class_scope:helloworld.HelloRequest)
))
_sym_db.RegisterMessage(HelloRequest)
HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), dict(
DESCRIPTOR = _HELLOREPLY,
__module__ = 'helloworld_pb2'
# @@protoc_insertion_point(class_scope:helloworld.HelloReply)
))
_sym_db.RegisterMessage(HelloReply)
DESCRIPTOR.has_options = True
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW'))
_GREETER = _descriptor.ServiceDescriptor(
name='Greeter',
full_name='helloworld.Greeter',
file=DESCRIPTOR,
index=0,
options=None,
serialized_start=93,
serialized_end=166,
methods=[
_descriptor.MethodDescriptor(
name='SayHello',
full_name='helloworld.Greeter.SayHello',
index=0,
containing_service=None,
input_type=_HELLOREQUEST,
output_type=_HELLOREPLY,
options=None,
),
])
_sym_db.RegisterServiceDescriptor(_GREETER)
DESCRIPTOR.services_by_name['Greeter'] = _GREETER
# @@protoc_insertion_point(module_scope)

@ -0,0 +1,46 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
import grpc
import helloworld_pb2 as helloworld__pb2
class GreeterStub(object):
"""The greeting service definition.
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.SayHello = channel.unary_unary(
'/helloworld.Greeter/SayHello',
request_serializer=helloworld__pb2.HelloRequest.SerializeToString,
response_deserializer=helloworld__pb2.HelloReply.FromString,
)
class GreeterServicer(object):
"""The greeting service definition.
"""
def SayHello(self, request, context):
"""Sends a greeting
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_GreeterServicer_to_server(servicer, server):
rpc_method_handlers = {
'SayHello': grpc.unary_unary_rpc_method_handler(
servicer.SayHello,
request_deserializer=helloworld__pb2.HelloRequest.FromString,
response_serializer=helloworld__pb2.HelloReply.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'helloworld.Greeter', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))

@ -0,0 +1,48 @@
# 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.
"""Example gRPC client that gets/sets metadata (HTTP2 headers)"""
from __future__ import print_function
import logging
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
def run():
# NOTE(gRPC Python Team): .close() is possible on a channel and should be
# used in circumstances in which the with statement does not fit the needs
# of the code.
with grpc.insecure_channel('localhost:50051') as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
response, call = stub.SayHello.with_call(
helloworld_pb2.HelloRequest(name='you'),
metadata=(
('initial-metadata-1', 'The value should be str'),
('binary-metadata-bin',
b'With -bin surffix, the value can be bytes'),
('accesstoken', 'gRPC Python is great'),
))
print("Greeter client received: " + response.message)
for key, value in call.trailing_metadata():
print('Greeter client received trailing metadata: key=%s value=%s' %
(key, value))
if __name__ == '__main__':
logging.basicConfig()
run()

@ -0,0 +1,56 @@
# 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.
"""Example gRPC server that gets/sets metadata (HTTP2 headers)"""
from __future__ import print_function
from concurrent import futures
import time
import logging
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
class Greeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
for key, value in context.invocation_metadata():
print('Received initial metadata: key=%s value=%s' % (key, value))
context.set_trailing_metadata((
('checksum-bin', b'I agree'),
('retry', 'false'),
))
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port('[::]:50051')
server.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
logging.basicConfig()
serve()

@ -39,7 +39,10 @@ def main
s = GRPC::RpcServer.new
s.add_http2_port('0.0.0.0:50051', :this_port_is_insecure)
s.handle(GreeterServer)
s.run_till_terminated
# Runs the server with SIGHUP, SIGINT and SIGQUIT signal handlers to
# gracefully shutdown.
# User could also choose to run server via call to run_till_terminated
s.run_till_terminated_or_interrupted([1, 'int', 'SIGQUIT'])
end
main

@ -172,7 +172,10 @@ def main
s.add_http2_port(port, :this_port_is_insecure)
GRPC.logger.info("... running insecurely on #{port}")
s.handle(ServerImpl.new(feature_db))
s.run_till_terminated
# Runs the server with SIGHUP, SIGINT and SIGQUIT signal handlers to
# gracefully shutdown.
# User could also choose to run server via call to run_till_terminated
s.run_till_terminated_or_interrupted([1, 'int', 'SIGQUIT'])
end
main

@ -23,7 +23,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-C++'
# TODO (mxyan): use version that match gRPC version when pod is stabilized
# version = '1.18.0-dev'
# version = '1.19.0-dev'
version = '0.0.8-dev'
s.version = version
s.summary = 'gRPC C++ library'
@ -31,7 +31,7 @@ Pod::Spec.new do |s|
s.license = 'Apache License, Version 2.0'
s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' }
grpc_version = '1.18.0-dev'
grpc_version = '1.19.0-dev'
s.source = {
:git => 'https://github.com/grpc/grpc.git',
@ -80,6 +80,7 @@ Pod::Spec.new do |s|
ss.header_mappings_dir = 'include/grpcpp'
ss.source_files = 'include/grpcpp/alarm.h',
'include/grpcpp/alarm_impl.h',
'include/grpcpp/channel.h',
'include/grpcpp/client_context.h',
'include/grpcpp/completion_queue.h',
@ -117,10 +118,13 @@ Pod::Spec.new do |s|
'include/grpcpp/support/byte_buffer.h',
'include/grpcpp/support/channel_arguments.h',
'include/grpcpp/support/client_callback.h',
'include/grpcpp/support/client_interceptor.h',
'include/grpcpp/support/config.h',
'include/grpcpp/support/interceptor.h',
'include/grpcpp/support/proto_buffer_reader.h',
'include/grpcpp/support/proto_buffer_writer.h',
'include/grpcpp/support/server_callback.h',
'include/grpcpp/support/server_interceptor.h',
'include/grpcpp/support/slice.h',
'include/grpcpp/support/status.h',
'include/grpcpp/support/status_code_enum.h',
@ -344,22 +348,26 @@ 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',
'src/core/ext/filters/client_channel/request_routing.h',
'src/core/ext/filters/client_channel/resolver.h',
'src/core/ext/filters/client_channel/resolver_factory.h',
'src/core/ext/filters/client_channel/resolver_registry.h',
'src/core/ext/filters/client_channel/resolver_result_parsing.h',
'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/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',
@ -419,6 +427,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/exec_ctx.h',
'src/core/lib/iomgr/executor.h',
'src/core/lib/iomgr/gethostname.h',
'src/core/lib/iomgr/grpc_if_nametoindex.h',
'src/core/lib/iomgr/internal_errqueue.h',
'src/core/lib/iomgr/iocp_windows.h',
'src/core/lib/iomgr/iomgr.h',
@ -429,7 +438,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',
@ -612,6 +620,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/exec_ctx.h',
'src/core/lib/iomgr/executor.h',
'src/core/lib/iomgr/gethostname.h',
'src/core/lib/iomgr/grpc_if_nametoindex.h',
'src/core/lib/iomgr/internal_errqueue.h',
'src/core/lib/iomgr/iocp_windows.h',
'src/core/lib/iomgr/iomgr.h',
@ -622,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',

@ -22,7 +22,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-Core'
version = '1.18.0-dev'
version = '1.19.0-dev'
s.version = version
s.summary = 'Core cross-platform gRPC library, written in C'
s.homepage = 'https://grpc.io'
@ -95,7 +95,7 @@ Pod::Spec.new do |s|
}
s.default_subspecs = 'Interface', 'Implementation'
s.compiler_flags = '-DGRPC_ARES=0', '-DPB_FIELD_16BIT'
s.compiler_flags = '-DGRPC_ARES=0', '-DPB_FIELD_32BIT'
s.libraries = 'c++'
# Like many other C libraries, gRPC-Core has its public headers under `include/<libname>/` and its
@ -342,22 +342,26 @@ 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',
'src/core/ext/filters/client_channel/request_routing.h',
'src/core/ext/filters/client_channel/resolver.h',
'src/core/ext/filters/client_channel/resolver_factory.h',
'src/core/ext/filters/client_channel/resolver_registry.h',
'src/core/ext/filters/client_channel/resolver_result_parsing.h',
'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/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',
@ -417,6 +421,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/exec_ctx.h',
'src/core/lib/iomgr/executor.h',
'src/core/lib/iomgr/gethostname.h',
'src/core/lib/iomgr/grpc_if_nametoindex.h',
'src/core/lib/iomgr/internal_errqueue.h',
'src/core/lib/iomgr/iocp_windows.h',
'src/core/lib/iomgr/iomgr.h',
@ -427,7 +432,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',
@ -571,6 +575,8 @@ Pod::Spec.new do |s|
'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',
@ -582,7 +588,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',
@ -784,21 +789,24 @@ 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_factory.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',
'src/core/ext/filters/client_channel/request_routing.cc',
'src/core/ext/filters/client_channel/resolver.cc',
'src/core/ext/filters/client_channel/resolver_registry.cc',
'src/core/ext/filters/client_channel/resolver_result_parsing.cc',
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/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',
@ -962,22 +970,26 @@ 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',
'src/core/ext/filters/client_channel/request_routing.h',
'src/core/ext/filters/client_channel/resolver.h',
'src/core/ext/filters/client_channel/resolver_factory.h',
'src/core/ext/filters/client_channel/resolver_registry.h',
'src/core/ext/filters/client_channel/resolver_result_parsing.h',
'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/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',
@ -1037,6 +1049,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/exec_ctx.h',
'src/core/lib/iomgr/executor.h',
'src/core/lib/iomgr/gethostname.h',
'src/core/lib/iomgr/grpc_if_nametoindex.h',
'src/core/lib/iomgr/internal_errqueue.h',
'src/core/lib/iomgr/iocp_windows.h',
'src/core/lib/iomgr/iomgr.h',
@ -1047,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',
@ -1198,15 +1210,14 @@ Pod::Spec.new do |s|
ss.dependency "#{s.name}/Interface", version
ss.dependency "#{s.name}/Implementation", version
ss.source_files = 'test/core/util/test_config.cc',
'test/core/util/test_config.h',
'test/core/end2end/data/client_certs.cc',
ss.source_files = 'test/core/end2end/data/client_certs.cc',
'test/core/end2end/data/server1_cert.cc',
'test/core/end2end/data/server1_key.cc',
'test/core/end2end/data/test_root_cert.cc',
'test/core/security/oauth2_utils.cc',
'test/core/end2end/cq_verifier.cc',
'test/core/end2end/fixtures/http_proxy_fixture.cc',
'test/core/end2end/fixtures/local_util.cc',
'test/core/end2end/fixtures/proxy.cc',
'test/core/iomgr/endpoint_tests.cc',
'test/core/util/debugger_macros.cc',
@ -1223,6 +1234,8 @@ Pod::Spec.new do |s|
'test/core/util/slice_splitter.cc',
'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',
@ -1233,6 +1246,7 @@ Pod::Spec.new do |s|
'test/core/security/oauth2_utils.h',
'test/core/end2end/cq_verifier.h',
'test/core/end2end/fixtures/http_proxy_fixture.h',
'test/core/end2end/fixtures/local_util.h',
'test/core/end2end/fixtures/proxy.h',
'test/core/iomgr/endpoint_tests.h',
'test/core/util/debugger_macros.h',
@ -1247,6 +1261,8 @@ Pod::Spec.new do |s|
'test/core/util/port_server_client.h',
'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',
@ -1291,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',

@ -21,7 +21,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-ProtoRPC'
version = '1.18.0-dev'
version = '1.19.0-dev'
s.version = version
s.summary = 'RPC library for Protocol Buffers, based on gRPC'
s.homepage = 'https://grpc.io'

@ -21,7 +21,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-RxLibrary'
version = '1.18.0-dev'
version = '1.19.0-dev'
s.version = version
s.summary = 'Reactive Extensions library for iOS/OSX.'
s.homepage = 'https://grpc.io'

@ -20,7 +20,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC'
version = '1.18.0-dev'
version = '1.19.0-dev'
s.version = version
s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'https://grpc.io'
@ -59,7 +59,7 @@ Pod::Spec.new do |s|
ss.source_files = "#{src_dir}/*.{h,m}", "#{src_dir}/**/*.{h,m}"
ss.exclude_files = "#{src_dir}/GRPCCall+GID.{h,m}"
ss.private_header_files = "#{src_dir}/private/*.h"
ss.private_header_files = "#{src_dir}/private/*.h", "#{src_dir}/internal/*.h"
ss.dependency 'gRPC-Core', version
end

@ -276,22 +276,26 @@ 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 )
s.files += %w( src/core/ext/filters/client_channel/request_routing.h )
s.files += %w( src/core/ext/filters/client_channel/resolver.h )
s.files += %w( src/core/ext/filters/client_channel/resolver_factory.h )
s.files += %w( src/core/ext/filters/client_channel/resolver_registry.h )
s.files += %w( src/core/ext/filters/client_channel/resolver_result_parsing.h )
s.files += %w( src/core/ext/filters/client_channel/retry_throttle.h )
s.files += %w( src/core/ext/filters/client_channel/server_address.h )
s.files += %w( src/core/ext/filters/client_channel/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 )
@ -351,6 +355,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/exec_ctx.h )
s.files += %w( src/core/lib/iomgr/executor.h )
s.files += %w( src/core/lib/iomgr/gethostname.h )
s.files += %w( src/core/lib/iomgr/grpc_if_nametoindex.h )
s.files += %w( src/core/lib/iomgr/internal_errqueue.h )
s.files += %w( src/core/lib/iomgr/iocp_windows.h )
s.files += %w( src/core/lib/iomgr/iomgr.h )
@ -361,7 +366,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 )
@ -505,6 +509,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/gethostname_fallback.cc )
s.files += %w( src/core/lib/iomgr/gethostname_host_name_max.cc )
s.files += %w( src/core/lib/iomgr/gethostname_sysconf.cc )
s.files += %w( src/core/lib/iomgr/grpc_if_nametoindex_posix.cc )
s.files += %w( src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc )
s.files += %w( src/core/lib/iomgr/internal_errqueue.cc )
s.files += %w( src/core/lib/iomgr/iocp_windows.cc )
s.files += %w( src/core/lib/iomgr/iomgr.cc )
@ -516,7 +522,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 )
@ -721,21 +726,24 @@ 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_factory.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 )
s.files += %w( src/core/ext/filters/client_channel/request_routing.cc )
s.files += %w( src/core/ext/filters/client_channel/resolver.cc )
s.files += %w( src/core/ext/filters/client_channel/resolver_registry.cc )
s.files += %w( src/core/ext/filters/client_channel/resolver_result_parsing.cc )
s.files += %w( src/core/ext/filters/client_channel/retry_throttle.cc )
s.files += %w( src/core/ext/filters/client_channel/server_address.cc )
s.files += %w( src/core/ext/filters/client_channel/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 )

@ -258,16 +258,6 @@
'src/core/lib/profiling/stap_timers.cc',
],
},
{
'target_name': 'gpr_test_util',
'type': 'static_library',
'dependencies': [
'gpr',
],
'sources': [
'test/core/util/test_config.cc',
],
},
{
'target_name': 'grpc',
'type': 'static_library',
@ -320,6 +310,8 @@
'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',
@ -331,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',
@ -536,21 +527,24 @@
'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_factory.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',
'src/core/ext/filters/client_channel/request_routing.cc',
'src/core/ext/filters/client_channel/resolver.cc',
'src/core/ext/filters/client_channel/resolver_registry.cc',
'src/core/ext/filters/client_channel/resolver_result_parsing.cc',
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/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',
@ -604,7 +598,6 @@
'target_name': 'grpc_test_util',
'type': 'static_library',
'dependencies': [
'gpr_test_util',
'gpr',
'grpc',
],
@ -617,6 +610,7 @@
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'test/core/end2end/cq_verifier.cc',
'test/core/end2end/fixtures/http_proxy_fixture.cc',
'test/core/end2end/fixtures/local_util.cc',
'test/core/end2end/fixtures/proxy.cc',
'test/core/iomgr/endpoint_tests.cc',
'test/core/util/debugger_macros.cc',
@ -633,6 +627,8 @@
'test/core/util/slice_splitter.cc',
'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',
@ -680,6 +676,8 @@
'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',
@ -691,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',
@ -795,21 +792,24 @@
'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_factory.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',
'src/core/ext/filters/client_channel/request_routing.cc',
'src/core/ext/filters/client_channel/resolver.cc',
'src/core/ext/filters/client_channel/resolver_registry.cc',
'src/core/ext/filters/client_channel/resolver_result_parsing.cc',
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/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',
@ -850,13 +850,13 @@
'type': 'static_library',
'dependencies': [
'gpr',
'gpr_test_util',
'grpc_unsecure',
],
'sources': [
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'test/core/end2end/cq_verifier.cc',
'test/core/end2end/fixtures/http_proxy_fixture.cc',
'test/core/end2end/fixtures/local_util.cc',
'test/core/end2end/fixtures/proxy.cc',
'test/core/iomgr/endpoint_tests.cc',
'test/core/util/debugger_macros.cc',
@ -873,6 +873,8 @@
'test/core/util/slice_splitter.cc',
'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',
@ -920,6 +922,8 @@
'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',
@ -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,21 +1038,24 @@
'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_factory.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',
'src/core/ext/filters/client_channel/request_routing.cc',
'src/core/ext/filters/client_channel/resolver.cc',
'src/core/ext/filters/client_channel/resolver_registry.cc',
'src/core/ext/filters/client_channel/resolver_result_parsing.cc',
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/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',
@ -1138,6 +1144,8 @@
'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',
@ -1149,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',
@ -1288,21 +1295,24 @@
'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_factory.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',
'src/core/ext/filters/client_channel/request_routing.cc',
'src/core/ext/filters/client_channel/resolver.cc',
'src/core/ext/filters/client_channel/resolver_registry.cc',
'src/core/ext/filters/client_channel/resolver_result_parsing.cc',
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/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',
@ -1351,7 +1361,6 @@
'test_tcp_server',
'grpc_test_util',
'grpc',
'gpr_test_util',
'gpr',
],
'sources': [
@ -1364,7 +1373,6 @@
'dependencies': [
'grpc_test_util',
'grpc',
'gpr_test_util',
'gpr',
],
'sources': [
@ -1681,7 +1689,6 @@
'grpc_test_util',
'grpc++',
'grpc',
'gpr_test_util',
'gpr',
'grpc++_test_config',
],
@ -1716,7 +1723,6 @@
'grpc_test_util',
'grpc++',
'grpc',
'gpr_test_util',
'gpr',
'grpc++_test_config',
],
@ -2669,7 +2675,6 @@
'dependencies': [
'grpc_test_util_unsecure',
'grpc_unsecure',
'gpr_test_util',
'gpr',
],
'sources': [
@ -2682,7 +2687,6 @@
'dependencies': [
'grpc_test_util',
'grpc',
'gpr_test_util',
'gpr',
],
'sources': [
@ -2723,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',
@ -2774,7 +2777,6 @@
'dependencies': [
'grpc_test_util_unsecure',
'grpc_unsecure',
'gpr_test_util',
'gpr',
],
'sources': [
@ -2814,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',

@ -511,7 +511,8 @@ GRPCAPI char* grpc_channelz_get_server(intptr_t server_id);
/* Gets all server sockets that exist in the server. */
GRPCAPI char* grpc_channelz_get_server_sockets(intptr_t server_id,
intptr_t start_socket_id);
intptr_t start_socket_id,
intptr_t max_results);
/* Returns a single Channel, or else a NOT_FOUND code. The returned string
is allocated and must be freed by the application. */

@ -106,10 +106,10 @@ typedef enum {
} grpc_ssl_client_certificate_request_type;
/**
* Type of local connection for which local channel/server credentials will be
* applied. It only supports UDS for now.
* Type of local connections for which local channel/server credentials will be
* applied. It supports UDS and local TCP connections.
*/
typedef enum { UDS = 0 } grpc_local_connect_type;
typedef enum { UDS = 0, LOCAL_TCP } grpc_local_connect_type;
#ifdef __cplusplus
}

@ -52,7 +52,8 @@ extern "C" {
"grpc.compression_enabled_algorithms_bitset"
/** \} */
/** The various compression algorithms supported by gRPC */
/** The various compression algorithms supported by gRPC (not sorted by
* compression level) */
typedef enum {
GRPC_COMPRESS_NONE = 0,
GRPC_COMPRESS_DEFLATE,

@ -163,7 +163,7 @@ typedef struct {
/** Maximum time that a channel may exist. Int valued, milliseconds.
* INT_MAX means unlimited. */
#define GRPC_ARG_MAX_CONNECTION_AGE_MS "grpc.max_connection_age_ms"
/** Grace period after the chennel reaches its max age. Int valued,
/** Grace period after the channel reaches its max age. Int valued,
milliseconds. INT_MAX means unlimited. */
#define GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS "grpc.max_connection_age_grace_ms"
/** Enable/disable support for per-message compression. Defaults to 1, unless
@ -355,6 +355,13 @@ typedef struct {
* 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. */
#define GRPC_ARG_CHANNEL_ID "grpc.channel_id"
/** \} */
/** Result of a grpc call. If the caller satisfies the prerequisites of a

@ -121,6 +121,7 @@
#else /* _LP64 */
#define GPR_ARCH_32 1
#endif /* _LP64 */
#include <linux/version.h>
#elif defined(ANDROID) || defined(__ANDROID__)
#define GPR_PLATFORM_STRING "android"
#define GPR_ANDROID 1
@ -465,6 +466,10 @@ typedef unsigned __int64 uint64_t;
#define GRPC_ARES 1
#endif
#ifndef GRPC_IF_NAMETOINDEX
#define GRPC_IF_NAMETOINDEX 1
#endif
#ifndef GRPC_MUST_USE_RESULT
#if defined(__GNUC__) && !defined(__MINGW32__)
#define GRPC_MUST_USE_RESULT __attribute__((warn_unused_result))

@ -1,6 +1,6 @@
/*
*
* Copyright 2015 gRPC authors.
* 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.
@ -16,99 +16,14 @@
*
*/
/// An Alarm posts the user provided tag to its associated completion queue upon
/// expiry or cancellation.
#ifndef GRPCPP_ALARM_H
#define GRPCPP_ALARM_H
#include <functional>
#include <grpc/grpc.h>
#include <grpcpp/impl/codegen/completion_queue.h>
#include <grpcpp/impl/codegen/completion_queue_tag.h>
#include <grpcpp/impl/codegen/grpc_library.h>
#include <grpcpp/impl/codegen/time.h>
#include <grpcpp/impl/grpc_library.h>
#include <grpcpp/alarm_impl.h>
namespace grpc {
/// A thin wrapper around \a grpc_alarm (see / \a / src/core/surface/alarm.h).
class Alarm : private GrpcLibraryCodegen {
public:
/// Create an unset completion queue alarm
Alarm();
/// Destroy the given completion queue alarm, cancelling it in the process.
~Alarm();
/// DEPRECATED: Create and set a completion queue alarm instance associated to
/// \a cq.
/// This form is deprecated because it is inherently racy.
/// \internal We rely on the presence of \a cq for grpc initialization. If \a
/// cq were ever to be removed, a reference to a static
/// internal::GrpcLibraryInitializer instance would need to be introduced
/// here. \endinternal.
template <typename T>
Alarm(CompletionQueue* cq, const T& deadline, void* tag) : Alarm() {
SetInternal(cq, TimePoint<T>(deadline).raw_time(), tag);
}
/// Trigger an alarm instance on completion queue \a cq at the specified time.
/// Once the alarm expires (at \a deadline) or it's cancelled (see \a Cancel),
/// an event with tag \a tag will be added to \a cq. If the alarm expired, the
/// event's success bit will be true, false otherwise (ie, upon cancellation).
template <typename T>
void Set(CompletionQueue* cq, const T& deadline, void* tag) {
SetInternal(cq, TimePoint<T>(deadline).raw_time(), tag);
}
/// Alarms aren't copyable.
Alarm(const Alarm&) = delete;
Alarm& operator=(const Alarm&) = delete;
/// Alarms are movable.
Alarm(Alarm&& rhs) : alarm_(rhs.alarm_) { rhs.alarm_ = nullptr; }
Alarm& operator=(Alarm&& rhs) {
alarm_ = rhs.alarm_;
rhs.alarm_ = nullptr;
return *this;
}
/// Cancel a completion queue alarm. Calling this function over an alarm that
/// has already fired has no effect.
void Cancel();
/// NOTE: class experimental_type is not part of the public API of this class
/// TODO(vjpai): Move these contents to the public API of Alarm when
/// they are no longer experimental
class experimental_type {
public:
explicit experimental_type(Alarm* alarm) : alarm_(alarm) {}
/// Set an alarm to invoke callback \a f. The argument to the callback
/// states whether the alarm expired at \a deadline (true) or was cancelled
/// (false)
template <typename T>
void Set(const T& deadline, std::function<void(bool)> f) {
alarm_->SetInternal(TimePoint<T>(deadline).raw_time(), std::move(f));
}
private:
Alarm* alarm_;
};
/// NOTE: The function experimental() is not stable public API. It is a view
/// to the experimental components of this class. It may be changed or removed
/// at any time.
experimental_type experimental() { return experimental_type(this); }
private:
void SetInternal(CompletionQueue* cq, gpr_timespec deadline, void* tag);
void SetInternal(gpr_timespec deadline, std::function<void(bool)> f);
internal::CompletionQueueTag* alarm_;
};
} // namespace grpc
typedef ::grpc_impl::Alarm Alarm;
}
#endif // GRPCPP_ALARM_H

@ -0,0 +1,116 @@
/*
*
* 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.
*
*/
/// An Alarm posts the user provided tag to its associated completion queue upon
/// expiry or cancellation.
#ifndef GRPCPP_ALARM_IMPL_H
#define GRPCPP_ALARM_IMPL_H
#include <functional>
#include <grpc/grpc.h>
#include <grpcpp/impl/codegen/completion_queue.h>
#include <grpcpp/impl/codegen/completion_queue_tag.h>
#include <grpcpp/impl/codegen/grpc_library.h>
#include <grpcpp/impl/codegen/time.h>
#include <grpcpp/impl/grpc_library.h>
namespace grpc_impl {
/// A thin wrapper around \a grpc_alarm (see / \a / src/core/surface/alarm.h).
class Alarm : private ::grpc::GrpcLibraryCodegen {
public:
/// Create an unset completion queue alarm
Alarm();
/// Destroy the given completion queue alarm, cancelling it in the process.
~Alarm();
/// DEPRECATED: Create and set a completion queue alarm instance associated to
/// \a cq.
/// This form is deprecated because it is inherently racy.
/// \internal We rely on the presence of \a cq for grpc initialization. If \a
/// cq were ever to be removed, a reference to a static
/// internal::GrpcLibraryInitializer instance would need to be introduced
/// here. \endinternal.
template <typename T>
Alarm(::grpc::CompletionQueue* cq, const T& deadline, void* tag) : Alarm() {
SetInternal(cq, ::grpc::TimePoint<T>(deadline).raw_time(), tag);
}
/// Trigger an alarm instance on completion queue \a cq at the specified time.
/// Once the alarm expires (at \a deadline) or it's cancelled (see \a Cancel),
/// an event with tag \a tag will be added to \a cq. If the alarm expired, the
/// event's success bit will be true, false otherwise (ie, upon cancellation).
template <typename T>
void Set(::grpc::CompletionQueue* cq, const T& deadline, void* tag) {
SetInternal(cq, ::grpc::TimePoint<T>(deadline).raw_time(), tag);
}
/// Alarms aren't copyable.
Alarm(const Alarm&) = delete;
Alarm& operator=(const Alarm&) = delete;
/// Alarms are movable.
Alarm(Alarm&& rhs) : alarm_(rhs.alarm_) { rhs.alarm_ = nullptr; }
Alarm& operator=(Alarm&& rhs) {
alarm_ = rhs.alarm_;
rhs.alarm_ = nullptr;
return *this;
}
/// Cancel a completion queue alarm. Calling this function over an alarm that
/// has already fired has no effect.
void Cancel();
/// NOTE: class experimental_type is not part of the public API of this class
/// TODO(vjpai): Move these contents to the public API of Alarm when
/// they are no longer experimental
class experimental_type {
public:
explicit experimental_type(Alarm* alarm) : alarm_(alarm) {}
/// Set an alarm to invoke callback \a f. The argument to the callback
/// states whether the alarm expired at \a deadline (true) or was cancelled
/// (false)
template <typename T>
void Set(const T& deadline, std::function<void(bool)> f) {
alarm_->SetInternal(::grpc::TimePoint<T>(deadline).raw_time(),
std::move(f));
}
private:
Alarm* alarm_;
};
/// NOTE: The function experimental() is not stable public API. It is a view
/// to the experimental components of this class. It may be changed or removed
/// at any time.
experimental_type experimental() { return experimental_type(this); }
private:
void SetInternal(::grpc::CompletionQueue* cq, gpr_timespec deadline,
void* tag);
void SetInternal(gpr_timespec deadline, std::function<void(bool)> f);
::grpc::internal::CompletionQueueTag* alarm_;
};
} // namespace grpc_impl
#endif // GRPCPP_ALARM_IMPL_H

@ -93,7 +93,9 @@ class ByteBuffer final {
}
/// Constuct a byte buffer by referencing elements of existing buffer
/// \a buf. Wrapper of core function grpc_byte_buffer_copy
/// \a buf. Wrapper of core function grpc_byte_buffer_copy . This is not
/// a deep copy; it is just a referencing. As a result, its performance is
/// size-independent.
ByteBuffer(const ByteBuffer& buf);
~ByteBuffer() {
@ -102,6 +104,9 @@ class ByteBuffer final {
}
}
/// Wrapper of core function grpc_byte_buffer_copy . This is not
/// a deep copy; it is just a referencing. As a result, its performance is
/// size-independent.
ByteBuffer& operator=(const ByteBuffer&);
/// Dump (read) the buffer contents into \a slices.
@ -117,7 +122,9 @@ class ByteBuffer final {
/// Make a duplicate copy of the internals of this byte
/// buffer so that we have our own owned version of it.
/// bbuf.Duplicate(); is equivalent to bbuf=bbuf; but is actually readable
/// bbuf.Duplicate(); is equivalent to bbuf=bbuf; but is actually readable.
/// This is not a deep copy; it is a referencing and its performance
/// is size-independent.
void Duplicate() {
buffer_ = g_core_codegen_interface->grpc_byte_buffer_copy(buffer_);
}

@ -303,9 +303,29 @@ class CallOpSendMessage {
template <class M>
Status SendMessage(const M& message) GRPC_MUST_USE_RESULT;
/// Send \a message using \a options for the write. The \a options are cleared
/// after use. This form of SendMessage allows gRPC to reference \a message
/// beyond the lifetime of SendMessage.
template <class M>
Status SendMessagePtr(const M* message,
WriteOptions options) GRPC_MUST_USE_RESULT;
/// This form of SendMessage allows gRPC to reference \a message beyond the
/// lifetime of SendMessage.
template <class M>
Status SendMessagePtr(const M* message) GRPC_MUST_USE_RESULT;
protected:
void AddOp(grpc_op* ops, size_t* nops) {
if (!send_buf_.Valid() || hijacked_) return;
if (msg_ == nullptr && !send_buf_.Valid()) return;
if (hijacked_) {
serializer_ = nullptr;
return;
}
if (msg_ != nullptr) {
GPR_CODEGEN_ASSERT(serializer_(msg_).ok());
}
serializer_ = nullptr;
grpc_op* op = &ops[(*nops)++];
op->op = GRPC_OP_SEND_MESSAGE;
op->flags = write_options_.flags();
@ -314,43 +334,77 @@ class CallOpSendMessage {
// Flags are per-message: clear them after use.
write_options_.Clear();
}
void FinishOp(bool* status) { send_buf_.Clear(); }
void FinishOp(bool* status) {
if (msg_ == nullptr && !send_buf_.Valid()) return;
if (hijacked_ && failed_send_) {
// Hijacking interceptor failed this Op
*status = false;
} else if (!*status) {
// This Op was passed down to core and the Op failed
failed_send_ = true;
}
}
void SetInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
if (!send_buf_.Valid()) return;
if (msg_ == nullptr && !send_buf_.Valid()) return;
interceptor_methods->AddInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_SEND_MESSAGE);
interceptor_methods->SetSendMessage(&send_buf_);
interceptor_methods->SetSendMessage(&send_buf_, &msg_, &failed_send_,
serializer_);
}
void SetFinishInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {}
InterceptorBatchMethodsImpl* interceptor_methods) {
if (msg_ != nullptr || send_buf_.Valid()) {
interceptor_methods->AddInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_SEND_MESSAGE);
}
send_buf_.Clear();
msg_ = nullptr;
// The contents of the SendMessage value that was previously set
// has had its references stolen by core's operations
interceptor_methods->SetSendMessage(nullptr, nullptr, &failed_send_,
nullptr);
}
void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
hijacked_ = true;
}
private:
const void* msg_ = nullptr; // The original non-serialized message
bool hijacked_ = false;
bool failed_send_ = false;
ByteBuffer send_buf_;
WriteOptions write_options_;
std::function<Status(const void*)> serializer_;
};
template <class M>
Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) {
write_options_ = options;
bool own_buf;
// TODO(vjpai): Remove the void below when possible
// The void in the template parameter below should not be needed
// (since it should be implicit) but is needed due to an observed
// difference in behavior between clang and gcc for certain internal users
Status result = SerializationTraits<M, void>::Serialize(
message, send_buf_.bbuf_ptr(), &own_buf);
if (!own_buf) {
send_buf_.Duplicate();
}
return result;
serializer_ = [this](const void* message) {
bool own_buf;
send_buf_.Clear();
// TODO(vjpai): Remove the void below when possible
// The void in the template parameter below should not be needed
// (since it should be implicit) but is needed due to an observed
// difference in behavior between clang and gcc for certain internal users
Status result = SerializationTraits<M, void>::Serialize(
*static_cast<const M*>(message), send_buf_.bbuf_ptr(), &own_buf);
if (!own_buf) {
send_buf_.Duplicate();
}
return result;
};
// Serialize immediately only if we do not have access to the message pointer
if (msg_ == nullptr) {
Status result = serializer_(&message);
serializer_ = nullptr;
return result;
}
return Status();
}
template <class M>
@ -358,6 +412,19 @@ Status CallOpSendMessage::SendMessage(const M& message) {
return SendMessage(message, WriteOptions());
}
template <class M>
Status CallOpSendMessage::SendMessagePtr(const M* message,
WriteOptions options) {
msg_ = message;
return SendMessage(*message, options);
}
template <class M>
Status CallOpSendMessage::SendMessagePtr(const M* message) {
msg_ = message;
return SendMessage(*message, WriteOptions());
}
template <class R>
class CallOpRecvMessage {
public:
@ -406,14 +473,16 @@ class CallOpRecvMessage {
void SetInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
interceptor_methods->SetRecvMessage(message_);
if (message_ == nullptr) return;
interceptor_methods->SetRecvMessage(message_, &got_message);
}
void SetFinishInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
if (!got_message) return;
if (message_ == nullptr) return;
interceptor_methods->AddInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
if (!got_message) interceptor_methods->SetRecvMessage(nullptr, nullptr);
}
void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
hijacked_ = true;
@ -501,20 +570,23 @@ class CallOpGenericRecvMessage {
void SetInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
interceptor_methods->SetRecvMessage(message_);
if (!deserialize_) return;
interceptor_methods->SetRecvMessage(message_, &got_message);
}
void SetFinishInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
if (!got_message) return;
if (!deserialize_) return;
interceptor_methods->AddInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
if (!got_message) interceptor_methods->SetRecvMessage(nullptr, nullptr);
}
void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
hijacked_ = true;
if (!deserialize_) return;
interceptor_methods->AddInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_RECV_MESSAGE);
got_message = true;
}
private:

@ -73,7 +73,7 @@ class CallbackUnaryCallImpl {
CallbackWithStatusTag(call.call(), on_completion, ops);
// TODO(vjpai): Unify code with sync API as much as possible
Status s = ops->SendMessage(*request);
Status s = ops->SendMessagePtr(request);
if (!s.ok()) {
tag->force_run(s);
return;
@ -340,13 +340,13 @@ class ClientCallbackReaderWriterImpl
context_->initial_metadata_flags());
start_corked_ = false;
}
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*msg).ok());
if (options.is_last_message()) {
options.set_buffer_hint();
write_ops_.ClientSendClose();
}
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg, options).ok());
callbacks_outstanding_++;
if (started_) {
call_.PerformOps(&write_ops_);
@ -524,7 +524,7 @@ class ClientCallbackReaderImpl
: context_(context), call_(call), reactor_(reactor) {
this->BindReactor(reactor);
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(start_ops_.SendMessage(*request).ok());
GPR_CODEGEN_ASSERT(start_ops_.SendMessagePtr(request).ok());
start_ops_.ClientSendClose();
}
@ -649,13 +649,13 @@ class ClientCallbackWriterImpl
context_->initial_metadata_flags());
start_corked_ = false;
}
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*msg).ok());
if (options.is_last_message()) {
options.set_buffer_hint();
write_ops_.ClientSendClose();
}
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg, options).ok());
callbacks_outstanding_++;
if (started_) {
call_.PerformOps(&write_ops_);

@ -200,6 +200,13 @@ class ClientContext {
/// end in "-bin".
/// \param meta_value The metadata value. If its value is binary, the key name
/// must end in "-bin".
///
/// Metadata must conform to the following format:
/// Custom-Metadata -> Binary-Header / ASCII-Header
/// Binary-Header -> {Header-Name "-bin" } {binary value}
/// ASCII-Header -> Header-Name ASCII-Value
/// Header-Name -> 1*( %x30-39 / %x61-7A / "_" / "-" / ".") ; 0-9 a-z _ - .
/// ASCII-Value -> 1*( %x20-%x7E ) ; space and printable ASCII
void AddMetadata(const grpc::string& meta_key,
const grpc::string& meta_value);

@ -38,9 +38,17 @@ class InterceptorBatchMethodsImpl;
namespace experimental {
class ClientRpcInfo;
// A factory interface for creation of client interceptors. A vector of
// factories can be provided at channel creation which will be used to create a
// new vector of client interceptors per RPC. Client interceptor authors should
// create a subclass of ClientInterceptorFactorInterface which creates objects
// of their interceptors.
class ClientInterceptorFactoryInterface {
public:
virtual ~ClientInterceptorFactoryInterface() {}
// Returns a pointer to an Interceptor object on successful creation, nullptr
// otherwise. If nullptr is returned, this server interceptor factory is
// ignored for the purposes of that RPC.
virtual Interceptor* CreateClientInterceptor(ClientRpcInfo* info) = 0;
};
} // namespace experimental
@ -50,11 +58,16 @@ extern experimental::ClientInterceptorFactoryInterface*
g_global_client_interceptor_factory;
}
/// ClientRpcInfo represents the state of a particular RPC as it
/// appears to an interceptor. It is created and owned by the library and
/// passed to the CreateClientInterceptor method of the application's
/// ClientInterceptorFactoryInterface implementation
namespace experimental {
class ClientRpcInfo {
public:
// TODO(yashykt): Stop default-constructing ClientRpcInfo and remove UNKNOWN
// from the list of possible Types.
/// Type categorizes RPCs by unary or streaming type
enum class Type {
UNARY,
CLIENT_STREAMING,
@ -65,13 +78,23 @@ class ClientRpcInfo {
~ClientRpcInfo(){};
// Delete copy constructor but allow default move constructor
ClientRpcInfo(const ClientRpcInfo&) = delete;
ClientRpcInfo(ClientRpcInfo&&) = default;
// Getter methods
/// Return the fully-specified method name
const char* method() const { return method_; }
/// Return a pointer to the channel on which the RPC is being sent
ChannelInterface* channel() { return channel_; }
/// Return a pointer to the underlying ClientContext structure associated
/// with the RPC to support features that apply to it
grpc::ClientContext* client_context() { return ctx_; }
/// Return the type of the RPC (unary or a streaming flavor)
Type type() const { return type_; }
private:
@ -120,8 +143,11 @@ class ClientRpcInfo {
}
for (auto it = creators.begin() + interceptor_pos; it != creators.end();
++it) {
interceptors_.push_back(std::unique_ptr<experimental::Interceptor>(
(*it)->CreateClientInterceptor(this)));
auto* interceptor = (*it)->CreateClientInterceptor(this);
if (interceptor != nullptr) {
interceptors_.push_back(
std::unique_ptr<experimental::Interceptor>(interceptor));
}
}
if (internal::g_global_client_interceptor_factory != nullptr) {
interceptors_.push_back(std::unique_ptr<experimental::Interceptor>(

@ -57,7 +57,7 @@ class BlockingUnaryCallImpl {
CallOpRecvInitialMetadata, CallOpRecvMessage<OutputMessage>,
CallOpClientSendClose, CallOpClientRecvStatus>
ops;
status_ = ops.SendMessage(request);
status_ = ops.SendMessagePtr(&request);
if (!status_.ok()) {
return;
}

@ -31,99 +31,168 @@ class ChannelInterface;
class Status;
namespace experimental {
class InterceptedMessage {
public:
template <class M>
bool Extract(M* msg); // returns false if definitely invalid extraction
template <class M>
M* MutableExtract();
uint64_t length(); // length on wire
};
/// An enumeration of different possible points at which the \a Intercept
/// method of the \a Interceptor interface may be called. Any given call
/// to \a Intercept will include one or more of these hook points, and
/// each hook point makes certain types of information available to the
/// interceptor.
/// In these enumeration names, PRE_SEND means that an interception has taken
/// place between the time the application provided a certain type of data
/// (e.g., initial metadata, status) and the time that that data goes to the
/// other side. POST_SEND means that the data has been committed for going to
/// the other side (even if it has not yet been received at the other side).
/// PRE_RECV means an interception between the time that a certain
/// operation has been requested and it is available. POST_RECV means that a
/// result is available but has not yet been passed back to the application.
enum class InterceptionHookPoints {
/* The first two in this list are for clients and servers */
/// The first three in this list are for clients and servers
PRE_SEND_INITIAL_METADATA,
PRE_SEND_MESSAGE,
PRE_SEND_STATUS /* server only */,
PRE_SEND_CLOSE /* client only */,
/* The following three are for hijacked clients only and can only be
registered by the global interceptor */
POST_SEND_MESSAGE,
PRE_SEND_STATUS, // server only
PRE_SEND_CLOSE, // client only: WritesDone for stream; after write in unary
/// The following three are for hijacked clients only and can only be
/// registered by the global interceptor
PRE_RECV_INITIAL_METADATA,
PRE_RECV_MESSAGE,
PRE_RECV_STATUS,
/* The following two are for all clients and servers */
/// The following two are for all clients and servers
POST_RECV_INITIAL_METADATA,
POST_RECV_MESSAGE,
POST_RECV_STATUS /* client only */,
POST_RECV_CLOSE /* server only */,
/* This is a special hook point available to both clients and servers when
TryCancel() is performed.
- No other hook points will be present along with this.
- It is illegal for an interceptor to block/delay this operation.
- ALL interceptors see this hook point irrespective of whether the RPC was
hijacked or not. */
POST_RECV_STATUS, // client only
POST_RECV_CLOSE, // server only
/// This is a special hook point available to both clients and servers when
/// TryCancel() is performed.
/// - No other hook points will be present along with this.
/// - It is illegal for an interceptor to block/delay this operation.
/// - ALL interceptors see this hook point irrespective of whether the
/// RPC was hijacked or not.
PRE_SEND_CANCEL,
NUM_INTERCEPTION_HOOKS
};
/// Class that is passed as an argument to the \a Intercept method
/// of the application's \a Interceptor interface implementation. It has five
/// purposes:
/// 1. Indicate which hook points are present at a specific interception
/// 2. Allow an interceptor to inform the library that an RPC should
/// continue to the next stage of its processing (which may be another
/// interceptor or the main path of the library)
/// 3. Allow an interceptor to hijack the processing of the RPC (only for
/// client-side RPCs with PRE_SEND_INITIAL_METADATA) so that it does not
/// proceed with normal processing beyond that stage
/// 4. Access the relevant fields of an RPC at each interception point
/// 5. Set some fields of an RPC at each interception point, when possible
class InterceptorBatchMethods {
public:
virtual ~InterceptorBatchMethods(){};
// Queries to check whether the current batch has an interception hook point
// of type \a type
/// Determine whether the current batch has an interception hook point
/// of type \a type
virtual bool QueryInterceptionHookPoint(InterceptionHookPoints type) = 0;
// Calling this will signal that the interceptor is done intercepting the
// current batch of the RPC.
// Proceed is a no-op if the batch contains PRE_SEND_CANCEL. Simply returning
// from the Intercept method does the job of continuing the RPC in this case.
/// Signal that the interceptor is done intercepting the current batch of the
/// RPC. Every interceptor must either call Proceed or Hijack on each
/// interception. In most cases, only Proceed will be used. Explicit use of
/// Proceed is what enables interceptors to delay the processing of RPCs
/// while they perform other work.
/// Proceed is a no-op if the batch contains PRE_SEND_CANCEL. Simply returning
/// from the Intercept method does the job of continuing the RPC in this case.
/// This is because PRE_SEND_CANCEL is always in a separate batch and is not
/// allowed to be delayed.
virtual void Proceed() = 0;
// Calling this indicates that the interceptor has hijacked the RPC (only
// valid if the batch contains send_initial_metadata on the client side)
/// Indicate that the interceptor has hijacked the RPC (only valid if the
/// batch contains send_initial_metadata on the client side). Later
/// interceptors in the interceptor list will not be called. Later batches
/// on the same RPC will go through interception, but only up to the point
/// of the hijacking interceptor.
virtual void Hijack() = 0;
// Returns a modifable ByteBuffer holding serialized form of the message to be
// sent
virtual ByteBuffer* GetSendMessage() = 0;
// Returns a modifiable multimap of the initial metadata to be sent
/// Returns a modifable ByteBuffer holding the serialized form of the message
/// that is going to be sent. Valid for PRE_SEND_MESSAGE interceptions.
/// A return value of nullptr indicates that this ByteBuffer is not valid.
virtual ByteBuffer* GetSerializedSendMessage() = 0;
/// Returns a non-modifiable pointer to the non-serialized form of the message
/// to be sent. Valid for PRE_SEND_MESSAGE interceptions. A return value of
/// nullptr indicates that this field is not valid. Also note that this is
/// only supported for sync and callback APIs at the present moment.
virtual const void* GetSendMessage() = 0;
/// Overwrites the message to be sent with \a message. \a message should be in
/// the non-serialized form expected by the method. Valid for PRE_SEND_MESSAGE
/// interceptions. Note that the interceptor is responsible for maintaining
/// the life of the message for the duration on the send operation, i.e., till
/// POST_SEND_MESSAGE.
virtual void ModifySendMessage(const void* message) = 0;
/// Checks whether the SEND MESSAGE op succeeded. Valid for POST_SEND_MESSAGE
/// interceptions.
virtual bool GetSendMessageStatus() = 0;
/// Returns a modifiable multimap of the initial metadata to be sent. Valid
/// for PRE_SEND_INITIAL_METADATA interceptions. A value of nullptr indicates
/// that this field is not valid.
virtual std::multimap<grpc::string, grpc::string>*
GetSendInitialMetadata() = 0;
// Returns the status to be sent
/// Returns the status to be sent. Valid for PRE_SEND_STATUS interceptions.
virtual Status GetSendStatus() = 0;
// Modifies the status with \a status
/// Overwrites the status with \a status. Valid for PRE_SEND_STATUS
/// interceptions.
virtual void ModifySendStatus(const Status& status) = 0;
// Returns a modifiable multimap of the trailing metadata to be sent
/// Returns a modifiable multimap of the trailing metadata to be sent. Valid
/// for PRE_SEND_STATUS interceptions. A value of nullptr indicates
/// that this field is not valid.
virtual std::multimap<grpc::string, grpc::string>*
GetSendTrailingMetadata() = 0;
// Returns a pointer to the modifiable received message. Note that the message
// is already deserialized
/// Returns a pointer to the modifiable received message. Note that the
/// message is already deserialized but the type is not set; the interceptor
/// should static_cast to the appropriate type before using it. This is valid
/// for POST_RECV_MESSAGE interceptions; nullptr for not valid
virtual void* GetRecvMessage() = 0;
// Returns a modifiable multimap of the received initial metadata
/// Returns a modifiable multimap of the received initial metadata.
/// Valid for POST_RECV_INITIAL_METADATA interceptions; nullptr if not valid
virtual std::multimap<grpc::string_ref, grpc::string_ref>*
GetRecvInitialMetadata() = 0;
// Returns a modifiable view of the received status
/// Returns a modifiable view of the received status on POST_RECV_STATUS
/// interceptions; nullptr if not valid.
virtual Status* GetRecvStatus() = 0;
// Returns a modifiable multimap of the received trailing metadata
/// Returns a modifiable multimap of the received trailing metadata on
/// POST_RECV_STATUS interceptions; nullptr if not valid
virtual std::multimap<grpc::string_ref, grpc::string_ref>*
GetRecvTrailingMetadata() = 0;
// Gets an intercepted channel. When a call is started on this interceptor,
// only interceptors after the current interceptor are created from the
// factory objects registered with the channel.
/// Gets an intercepted channel. When a call is started on this interceptor,
/// only interceptors after the current interceptor are created from the
/// factory objects registered with the channel. This allows calls to be
/// started from interceptors without infinite regress through the interceptor
/// list.
virtual std::unique_ptr<ChannelInterface> GetInterceptedChannel() = 0;
/// On a hijacked RPC, an interceptor can decide to fail a PRE_RECV_MESSAGE
/// op. This would be a signal to the reader that there will be no more
/// messages, or the stream has failed or been cancelled.
virtual void FailHijackedRecvMessage() = 0;
/// On a hijacked RPC/ to-be hijacked RPC, this can be called to fail a SEND
/// MESSAGE op
virtual void FailHijackedSendMessage() = 0;
};
/// Interface for an interceptor. Interceptor authors must create a class
/// that derives from this parent class.
class Interceptor {
public:
virtual ~Interceptor() {}
/// The one public method of an Interceptor interface. Override this to
/// trigger the desired actions at the hook points described above.
virtual void Intercept(InterceptorBatchMethods* methods) = 0;
};

@ -79,7 +79,26 @@ class InterceptorBatchMethodsImpl
hooks_[static_cast<size_t>(type)] = true;
}
ByteBuffer* GetSendMessage() override { return send_message_; }
ByteBuffer* GetSerializedSendMessage() override {
GPR_CODEGEN_ASSERT(orig_send_message_ != nullptr);
if (*orig_send_message_ != nullptr) {
GPR_CODEGEN_ASSERT(serializer_(*orig_send_message_).ok());
*orig_send_message_ = nullptr;
}
return send_message_;
}
const void* GetSendMessage() override {
GPR_CODEGEN_ASSERT(orig_send_message_ != nullptr);
return *orig_send_message_;
}
void ModifySendMessage(const void* message) override {
GPR_CODEGEN_ASSERT(orig_send_message_ != nullptr);
*orig_send_message_ = message;
}
bool GetSendMessageStatus() override { return !*fail_send_message_; }
std::multimap<grpc::string, grpc::string>* GetSendInitialMetadata() override {
return send_initial_metadata_;
@ -110,12 +129,25 @@ class InterceptorBatchMethodsImpl
Status* GetRecvStatus() override { return recv_status_; }
void FailHijackedSendMessage() override {
GPR_CODEGEN_ASSERT(hooks_[static_cast<size_t>(
experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)]);
*fail_send_message_ = true;
}
std::multimap<grpc::string_ref, grpc::string_ref>* GetRecvTrailingMetadata()
override {
return recv_trailing_metadata_->map();
}
void SetSendMessage(ByteBuffer* buf) { send_message_ = buf; }
void SetSendMessage(ByteBuffer* buf, const void** msg,
bool* fail_send_message,
std::function<Status(const void*)> serializer) {
send_message_ = buf;
orig_send_message_ = msg;
fail_send_message_ = fail_send_message;
serializer_ = serializer;
}
void SetSendInitialMetadata(
std::multimap<grpc::string, grpc::string>* metadata) {
@ -134,7 +166,10 @@ class InterceptorBatchMethodsImpl
send_trailing_metadata_ = metadata;
}
void SetRecvMessage(void* message) { recv_message_ = message; }
void SetRecvMessage(void* message, bool* got_message) {
recv_message_ = message;
got_message_ = got_message;
}
void SetRecvInitialMetadata(MetadataMap* map) {
recv_initial_metadata_ = map;
@ -157,6 +192,12 @@ class InterceptorBatchMethodsImpl
info->channel(), current_interceptor_index_ + 1));
}
void FailHijackedRecvMessage() override {
GPR_CODEGEN_ASSERT(hooks_[static_cast<size_t>(
experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)]);
*got_message_ = false;
}
// Clears all state
void ClearState() {
reverse_ = false;
@ -334,6 +375,9 @@ class InterceptorBatchMethodsImpl
std::function<void(void)> callback_;
ByteBuffer* send_message_ = nullptr;
bool* fail_send_message_ = nullptr;
const void** orig_send_message_ = nullptr;
std::function<Status(const void*)> serializer_;
std::multimap<grpc::string, grpc::string>* send_initial_metadata_;
@ -345,6 +389,7 @@ class InterceptorBatchMethodsImpl
std::multimap<grpc::string, grpc::string>* send_trailing_metadata_ = nullptr;
void* recv_message_ = nullptr;
bool* got_message_ = nullptr;
MetadataMap* recv_initial_metadata_ = nullptr;
@ -379,13 +424,36 @@ class CancelInterceptorBatchMethods
"Cancel notification");
}
ByteBuffer* GetSendMessage() override {
ByteBuffer* GetSerializedSendMessage() override {
GPR_CODEGEN_ASSERT(false &&
"It is illegal to call GetSendMessage on a method which "
"has a Cancel notification");
return nullptr;
}
bool GetSendMessageStatus() override {
GPR_CODEGEN_ASSERT(
false &&
"It is illegal to call GetSendMessageStatus on a method which "
"has a Cancel notification");
return false;
}
const void* GetSendMessage() override {
GPR_CODEGEN_ASSERT(
false &&
"It is illegal to call GetOriginalSendMessage on a method which "
"has a Cancel notification");
return nullptr;
}
void ModifySendMessage(const void* message) override {
GPR_CODEGEN_ASSERT(
false &&
"It is illegal to call ModifySendMessage on a method which "
"has a Cancel notification");
}
std::multimap<grpc::string, grpc::string>* GetSendInitialMetadata() override {
GPR_CODEGEN_ASSERT(false &&
"It is illegal to call GetSendInitialMetadata on a "
@ -451,6 +519,18 @@ class CancelInterceptorBatchMethods
"method which has a Cancel notification");
return std::unique_ptr<ChannelInterface>(nullptr);
}
void FailHijackedRecvMessage() override {
GPR_CODEGEN_ASSERT(false &&
"It is illegal to call FailHijackedRecvMessage on a "
"method which has a Cancel notification");
}
void FailHijackedSendMessage() override {
GPR_CODEGEN_ASSERT(false &&
"It is illegal to call FailHijackedSendMessage on a "
"method which has a Cancel notification");
}
};
} // namespace internal
} // namespace grpc

@ -79,7 +79,7 @@ class RpcMethodHandler : public MethodHandler {
ops.set_compression_level(param.server_context->compression_level());
}
if (status.ok()) {
status = ops.SendMessage(rsp);
status = ops.SendMessagePtr(&rsp);
}
ops.ServerSendStatus(&param.server_context->trailing_metadata_, status);
param.call->PerformOps(&ops);
@ -139,7 +139,7 @@ class ClientStreamingHandler : public MethodHandler {
}
}
if (status.ok()) {
status = ops.SendMessage(rsp);
status = ops.SendMessagePtr(&rsp);
}
ops.ServerSendStatus(&param.server_context->trailing_metadata_, status);
param.call->PerformOps(&ops);

@ -320,7 +320,7 @@ class CallbackUnaryHandler : public MethodHandler {
// The response is dropped if the status is not OK.
if (s.ok()) {
finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_,
finish_ops_.SendMessage(resp_));
finish_ops_.SendMessagePtr(&resp_));
} else {
finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
}
@ -449,7 +449,7 @@ class CallbackClientStreamingHandler : public MethodHandler {
// The response is dropped if the status is not OK.
if (s.ok()) {
finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_,
finish_ops_.SendMessage(resp_));
finish_ops_.SendMessagePtr(&resp_));
} else {
finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
}
@ -642,7 +642,7 @@ class CallbackServerStreamingHandler : public MethodHandler {
ctx_->sent_initial_metadata_ = true;
}
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*resp, options).ok());
GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(resp, options).ok());
call_.PerformOps(&write_ops_);
}
@ -652,7 +652,7 @@ class CallbackServerStreamingHandler : public MethodHandler {
// Don't send any message if the status is bad
if (s.ok()) {
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(*resp, options).ok());
GPR_CODEGEN_ASSERT(finish_ops_.SendMessagePtr(resp, options).ok());
}
Finish(std::move(s));
}
@ -804,7 +804,7 @@ class CallbackBidiHandler : public MethodHandler {
ctx_->sent_initial_metadata_ = true;
}
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*resp, options).ok());
GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(resp, options).ok());
call_.PerformOps(&write_ops_);
}
@ -813,7 +813,7 @@ class CallbackBidiHandler : public MethodHandler {
// Don't send any message if the status is bad
if (s.ok()) {
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(*resp, options).ok());
GPR_CODEGEN_ASSERT(finish_ops_.SendMessagePtr(resp, options).ok());
}
Finish(std::move(s));
}

@ -131,6 +131,13 @@ class ServerContext {
/// end in "-bin".
/// \param value The metadata value. If its value is binary, the key name
/// must end in "-bin".
///
/// Metadata must conform to the following format:
/// Custom-Metadata -> Binary-Header / ASCII-Header
/// Binary-Header -> {Header-Name "-bin" } {binary value}
/// ASCII-Header -> Header-Name ASCII-Value
/// Header-Name -> 1*( %x30-39 / %x61-7A / "_" / "-" / ".") ; 0-9 a-z _ - .
/// ASCII-Value -> 1*( %x20-%x7E ) ; space and printable ASCII
void AddInitialMetadata(const grpc::string& key, const grpc::string& value);
/// Add the (\a key, \a value) pair to the initial metadata
@ -145,6 +152,13 @@ class ServerContext {
/// it must end in "-bin".
/// \param value The metadata value. If its value is binary, the key name
/// must end in "-bin".
///
/// Metadata must conform to the following format:
/// Custom-Metadata -> Binary-Header / ASCII-Header
/// Binary-Header -> {Header-Name "-bin" } {binary value}
/// ASCII-Header -> Header-Name ASCII-Value
/// Header-Name -> 1*( %x30-39 / %x61-7A / "_" / "-" / ".") ; 0-9 a-z _ - .
/// ASCII-Value -> 1*( %x20-%x7E ) ; space and printable ASCII
void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
/// IsCancelled is always safe to call when using sync or callback API.

@ -37,25 +37,47 @@ class InterceptorBatchMethodsImpl;
namespace experimental {
class ServerRpcInfo;
// A factory interface for creation of server interceptors. A vector of
// factories can be provided to ServerBuilder which will be used to create a new
// vector of server interceptors per RPC. Server interceptor authors should
// create a subclass of ServerInterceptorFactorInterface which creates objects
// of their interceptors.
class ServerInterceptorFactoryInterface {
public:
virtual ~ServerInterceptorFactoryInterface() {}
// Returns a pointer to an Interceptor object on successful creation, nullptr
// otherwise. If nullptr is returned, this server interceptor factory is
// ignored for the purposes of that RPC.
virtual Interceptor* CreateServerInterceptor(ServerRpcInfo* info) = 0;
};
/// ServerRpcInfo represents the state of a particular RPC as it
/// appears to an interceptor. It is created and owned by the library and
/// passed to the CreateServerInterceptor method of the application's
/// ServerInterceptorFactoryInterface implementation
class ServerRpcInfo {
public:
/// Type categorizes RPCs by unary or streaming type
enum class Type { UNARY, CLIENT_STREAMING, SERVER_STREAMING, BIDI_STREAMING };
~ServerRpcInfo(){};
// Delete all copy and move constructors and assignments
ServerRpcInfo(const ServerRpcInfo&) = delete;
ServerRpcInfo(ServerRpcInfo&&) = default;
ServerRpcInfo& operator=(ServerRpcInfo&&) = default;
ServerRpcInfo& operator=(const ServerRpcInfo&) = delete;
ServerRpcInfo(ServerRpcInfo&&) = delete;
ServerRpcInfo& operator=(ServerRpcInfo&&) = delete;
// Getter methods
/// Return the fully-specified method name
const char* method() const { return method_; }
/// Return the type of the RPC (unary or a streaming flavor)
Type type() const { return type_; }
/// Return a pointer to the underlying ServerContext structure associated
/// with the RPC to support features that apply to it
grpc::ServerContext* server_context() { return ctx_; }
private:
@ -90,8 +112,11 @@ class ServerRpcInfo {
std::unique_ptr<experimental::ServerInterceptorFactoryInterface>>&
creators) {
for (const auto& creator : creators) {
interceptors_.push_back(std::unique_ptr<experimental::Interceptor>(
creator->CreateServerInterceptor(this)));
auto* interceptor = creator->CreateServerInterceptor(this);
if (interceptor != nullptr) {
interceptors_.push_back(
std::unique_ptr<experimental::Interceptor>(interceptor));
}
}
}

@ -272,7 +272,7 @@ class ServerInterface : public internal::CallHook {
/* Set interception point for recv message */
interceptor_methods_.AddInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
interceptor_methods_.SetRecvMessage(request_);
interceptor_methods_.SetRecvMessage(request_, nullptr);
return RegisteredAsyncRequest::FinalizeResult(tag, status);
}

@ -253,7 +253,7 @@ class ClientReader final : public ClientReaderInterface<R> {
ops.SendInitialMetadata(&context->send_initial_metadata_,
context->initial_metadata_flags());
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok());
GPR_CODEGEN_ASSERT(ops.SendMessagePtr(&request).ok());
ops.ClientSendClose();
call_.PerformOps(&ops);
cq_.Pluck(&ops);
@ -331,7 +331,7 @@ class ClientWriter : public ClientWriterInterface<W> {
context_->initial_metadata_flags());
context_->set_initial_metadata_corked(false);
}
if (!ops.SendMessage(msg, options).ok()) {
if (!ops.SendMessagePtr(&msg, options).ok()) {
return false;
}
@ -502,7 +502,7 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
context_->initial_metadata_flags());
context_->set_initial_metadata_corked(false);
}
if (!ops.SendMessage(msg, options).ok()) {
if (!ops.SendMessagePtr(&msg, options).ok()) {
return false;
}
@ -656,7 +656,7 @@ class ServerWriter final : public ServerWriterInterface<W> {
options.set_buffer_hint();
}
if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) {
if (!ctx_->pending_ops_.SendMessagePtr(&msg, options).ok()) {
return false;
}
if (!ctx_->sent_initial_metadata_) {
@ -734,7 +734,7 @@ class ServerReaderWriterBody final {
if (options.is_last_message()) {
options.set_buffer_hint();
}
if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) {
if (!ctx_->pending_ops_.SendMessagePtr(&msg, options).ok()) {
return false;
}
if (!ctx_->sent_initial_metadata_) {

@ -35,18 +35,17 @@ class GrpcLibrary final : public GrpcLibraryInterface {
void shutdown() override { grpc_shutdown(); }
};
static GrpcLibrary g_gli;
static CoreCodegen g_core_codegen;
/// Instantiating this class ensures the proper initialization of gRPC.
class GrpcLibraryInitializer final {
public:
GrpcLibraryInitializer() {
if (grpc::g_glip == nullptr) {
grpc::g_glip = &g_gli;
static auto* const g_gli = new GrpcLibrary();
grpc::g_glip = g_gli;
}
if (grpc::g_core_codegen_interface == nullptr) {
grpc::g_core_codegen_interface = &g_core_codegen;
static auto* const g_core_codegen = new CoreCodegen();
grpc::g_core_codegen_interface = g_core_codegen;
}
}

@ -0,0 +1,24 @@
/*
*
* Copyright 2015 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPCPP_SUPPORT_CLIENT_INTERCEPTOR_H
#define GRPCPP_SUPPORT_CLIENT_INTERCEPTOR_H
#include <grpcpp/impl/codegen/client_interceptor.h>
#endif // GRPCPP_SUPPORT_CLIENT_INTERCEPTOR_H

@ -0,0 +1,24 @@
/*
*
* Copyright 2015 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPCPP_SUPPORT_INTERCEPTOR_H
#define GRPCPP_SUPPORT_INTERCEPTOR_H
#include <grpcpp/impl/codegen/interceptor.h>
#endif // GRPCPP_SUPPORT_INTERCEPTOR_H

@ -0,0 +1,24 @@
/*
*
* Copyright 2015 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPCPP_SUPPORT_SERVER_INTERCEPTOR_H
#define GRPCPP_SUPPORT_SERVER_INTERCEPTOR_H
#include <grpcpp/impl/codegen/server_interceptor.h>
#endif // GRPCPP_SUPPORT_SERVER_INTERCEPTOR_H

@ -13,8 +13,8 @@
<date>2018-01-19</date>
<time>16:06:07</time>
<version>
<release>1.18.0dev</release>
<api>1.18.0dev</api>
<release>1.19.0dev</release>
<api>1.19.0dev</api>
</version>
<stability>
<release>beta</release>
@ -281,22 +281,26 @@
<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" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/request_routing.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_registry.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_result_parsing.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/server_address.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/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" />
@ -356,6 +360,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/executor.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/gethostname.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/grpc_if_nametoindex.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/internal_errqueue.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iocp_windows.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.h" role="src" />
@ -366,7 +371,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" />
@ -510,6 +514,8 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/gethostname_fallback.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/gethostname_host_name_max.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/gethostname_sysconf.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/grpc_if_nametoindex_posix.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/internal_errqueue.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iocp_windows.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.cc" role="src" />
@ -521,7 +527,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" />
@ -726,21 +731,24 @@
<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_factory.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" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/request_routing.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_registry.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_result_parsing.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/server_address.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/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" />

@ -9,7 +9,8 @@ futures>=2.2.0
google-auth>=1.0.0
oauth2client==4.1.0
requests>=2.14.2
urllib3==1.22
urllib3>=1.23
chardet==3.0.4
certifi==2017.4.17
idna==2.7
googleapis-common-protos==1.5.5

@ -160,7 +160,7 @@ if EXTRA_ENV_COMPILE_ARGS is None:
EXTRA_ENV_COMPILE_ARGS += ' -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
elif "darwin" in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden -fno-wrapv -fno-exceptions'
EXTRA_ENV_COMPILE_ARGS += ' -DPB_FIELD_16BIT'
EXTRA_ENV_COMPILE_ARGS += ' -DPB_FIELD_32BIT'
if EXTRA_ENV_LINK_ARGS is None:
EXTRA_ENV_LINK_ARGS = ''

@ -113,6 +113,29 @@ void PrintAdvancedSignature(Printer* printer, const MethodDescriptor* method,
PrintMethodSignature(printer, method, vars);
}
void PrintV2Signature(Printer* printer, const MethodDescriptor* method,
map< ::grpc::string, ::grpc::string> vars) {
if (method->client_streaming()) {
vars["return_type"] = "GRPCStreamingProtoCall *";
} else {
vars["return_type"] = "GRPCUnaryProtoCall *";
}
vars["method_name"] =
grpc_generator::LowercaseFirstLetter(vars["method_name"]);
PrintAllComments(method, printer);
printer->Print(vars, "- ($return_type$)$method_name$With");
if (method->client_streaming()) {
printer->Print("ResponseHandler:(id<GRPCProtoResponseHandler>)handler");
} else {
printer->Print(vars,
"Message:($request_class$ *)message "
"responseHandler:(id<GRPCProtoResponseHandler>)handler");
}
printer->Print(" callOptions:(GRPCCallOptions *_Nullable)callOptions");
}
inline map< ::grpc::string, ::grpc::string> GetMethodVars(
const MethodDescriptor* method) {
map< ::grpc::string, ::grpc::string> res;
@ -135,6 +158,16 @@ void PrintMethodDeclarations(Printer* printer, const MethodDescriptor* method) {
printer->Print(";\n\n\n");
}
void PrintV2MethodDeclarations(Printer* printer,
const MethodDescriptor* method) {
map< ::grpc::string, ::grpc::string> vars = GetMethodVars(method);
PrintProtoRpcDeclarationAsPragma(printer, method, vars);
PrintV2Signature(printer, method, vars);
printer->Print(";\n\n");
}
void PrintSimpleImplementation(Printer* printer, const MethodDescriptor* method,
map< ::grpc::string, ::grpc::string> vars) {
printer->Print("{\n");
@ -177,6 +210,25 @@ void PrintAdvancedImplementation(Printer* printer,
printer->Print("}\n");
}
void PrintV2Implementation(Printer* printer, const MethodDescriptor* method,
map< ::grpc::string, ::grpc::string> vars) {
printer->Print(" {\n");
if (method->client_streaming()) {
printer->Print(vars, " return [self RPCToMethod:@\"$method_name$\"\n");
printer->Print(" responseHandler:handler\n");
printer->Print(" callOptions:callOptions\n");
printer->Print(
vars, " responseClass:[$response_class$ class]];\n}\n\n");
} else {
printer->Print(vars, " return [self RPCToMethod:@\"$method_name$\"\n");
printer->Print(" message:message\n");
printer->Print(" responseHandler:handler\n");
printer->Print(" callOptions:callOptions\n");
printer->Print(
vars, " responseClass:[$response_class$ class]];\n}\n\n");
}
}
void PrintMethodImplementations(Printer* printer,
const MethodDescriptor* method) {
map< ::grpc::string, ::grpc::string> vars = GetMethodVars(method);
@ -184,12 +236,16 @@ void PrintMethodImplementations(Printer* printer,
PrintProtoRpcDeclarationAsPragma(printer, method, vars);
// TODO(jcanizales): Print documentation from the method.
printer->Print("// Deprecated methods.\n");
PrintSimpleSignature(printer, method, vars);
PrintSimpleImplementation(printer, method, vars);
printer->Print("// Returns a not-yet-started RPC object.\n");
PrintAdvancedSignature(printer, method, vars);
PrintAdvancedImplementation(printer, method, vars);
PrintV2Signature(printer, method, vars);
PrintV2Implementation(printer, method, vars);
}
} // namespace
@ -231,6 +287,25 @@ void PrintMethodImplementations(Printer* printer,
return output;
}
::grpc::string GetV2Protocol(const ServiceDescriptor* service) {
::grpc::string output;
// Scope the output stream so it closes and finalizes output to the string.
grpc::protobuf::io::StringOutputStream output_stream(&output);
Printer printer(&output_stream, '$');
map< ::grpc::string, ::grpc::string> vars = {
{"service_class", ServiceClassName(service) + "2"}};
printer.Print(vars, "@protocol $service_class$ <NSObject>\n\n");
for (int i = 0; i < service->method_count(); i++) {
PrintV2MethodDeclarations(&printer, service->method(i));
}
printer.Print("@end\n\n");
return output;
}
::grpc::string GetInterface(const ServiceDescriptor* service) {
::grpc::string output;
@ -248,10 +323,16 @@ void PrintMethodImplementations(Printer* printer,
" */\n");
printer.Print(vars,
"@interface $service_class$ :"
" GRPCProtoService<$service_class$>\n");
" GRPCProtoService<$service_class$, $service_class$2>\n");
printer.Print(
"- (instancetype)initWithHost:(NSString *)host"
"- (instancetype)initWithHost:(NSString *)host "
"callOptions:(GRPCCallOptions "
"*_Nullable)callOptions"
" NS_DESIGNATED_INITIALIZER;\n");
printer.Print("- (instancetype)initWithHost:(NSString *)host;\n");
printer.Print(
"+ (instancetype)serviceWithHost:(NSString *)host "
"callOptions:(GRPCCallOptions *_Nullable)callOptions;\n");
printer.Print("+ (instancetype)serviceWithHost:(NSString *)host;\n");
printer.Print("@end\n");
@ -272,13 +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"
" return [super initWithHost:host\n"
" packageName:@\"$package$\"\n"
" serviceName:@\"$service_name$\"\n"
" callOptions:callOptions];\n"
"}\n\n"
"- (instancetype)initWithHost:(NSString *)host {\n"
" self = [super initWithHost:host\n"
" return [super initWithHost:host\n"
" packageName:@\"$package$\"\n"
" serviceName:@\"$service_name$\"];\n"
" return self;\n"
"}\n\n");
"}\n\n"
"#pragma clang diagnostic pop\n\n");
printer.Print(
"// Override superclass initializer to disallow different"
@ -287,12 +378,22 @@ 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(
"#pragma mark - Class Methods\n\n"
"+ (instancetype)serviceWithHost:(NSString *)host {\n"
" return [[self alloc] initWithHost:host];\n"
"}\n\n"
"+ (instancetype)serviceWithHost:(NSString *)host "
"callOptions:(GRPCCallOptions *_Nullable)callOptions {\n"
" return [[self alloc] initWithHost:host callOptions:callOptions];\n"
"}\n\n");
printer.Print("#pragma mark - Method Implementations\n\n");

@ -32,9 +32,14 @@ using ::grpc::string;
string GetAllMessageClasses(const FileDescriptor* file);
// Returns the content to be included defining the @protocol segment at the
// insertion point of the generated implementation file.
// insertion point of the generated implementation file. This interface is
// legacy and for backwards compatibility.
string GetProtocol(const ServiceDescriptor* service);
// Returns the content to be included defining the @protocol segment at the
// insertion point of the generated implementation file.
string GetV2Protocol(const ServiceDescriptor* service);
// Returns the content to be included defining the @interface segment at the
// insertion point of the generated implementation file.
string GetInterface(const ServiceDescriptor* service);

@ -93,7 +93,13 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
SystemImport("RxLibrary/GRXWriteable.h") +
SystemImport("RxLibrary/GRXWriter.h");
::grpc::string forward_declarations = "@class GRPCProtoCall;\n\n";
::grpc::string forward_declarations =
"@class GRPCProtoCall;\n"
"@class GRPCUnaryProtoCall;\n"
"@class GRPCStreamingProtoCall;\n"
"@class GRPCCallOptions;\n"
"@protocol GRPCProtoResponseHandler;\n"
"\n";
::grpc::string class_declarations =
grpc_objective_c_generator::GetAllMessageClasses(file);
@ -103,6 +109,12 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
class_imports += ImportProtoHeaders(file->dependency(i), " ");
}
::grpc::string ng_protocols;
for (int i = 0; i < file->service_count(); i++) {
const grpc::protobuf::ServiceDescriptor* service = file->service(i);
ng_protocols += grpc_objective_c_generator::GetV2Protocol(service);
}
::grpc::string protocols;
for (int i = 0; i < file->service_count(); i++) {
const grpc::protobuf::ServiceDescriptor* service = file->service(i);
@ -120,9 +132,10 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
PreprocIfNot(kProtocolOnly, system_imports) + "\n" +
class_declarations + "\n" +
PreprocIfNot(kForwardDeclare, class_imports) + "\n" +
forward_declarations + "\n" + kNonNullBegin + "\n" + protocols +
"\n" + PreprocIfNot(kProtocolOnly, interfaces) + "\n" +
kNonNullEnd + "\n");
forward_declarations + "\n" + kNonNullBegin + "\n" +
ng_protocols + protocols + "\n" +
PreprocIfNot(kProtocolOnly, interfaces) + "\n" + kNonNullEnd +
"\n");
}
{

File diff suppressed because it is too large Load Diff

@ -30,7 +30,7 @@ void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory) {
}
grpc_subchannel* grpc_client_channel_factory_create_subchannel(
grpc_client_channel_factory* factory, const grpc_subchannel_args* args) {
grpc_client_channel_factory* factory, const grpc_channel_args* args) {
return factory->vtable->create_subchannel(factory, args);
}

@ -49,7 +49,7 @@ struct grpc_client_channel_factory_vtable {
void (*ref)(grpc_client_channel_factory* factory);
void (*unref)(grpc_client_channel_factory* factory);
grpc_subchannel* (*create_subchannel)(grpc_client_channel_factory* factory,
const grpc_subchannel_args* args);
const grpc_channel_args* args);
grpc_channel* (*create_client_channel)(grpc_client_channel_factory* factory,
const char* target,
grpc_client_channel_type type,
@ -61,7 +61,7 @@ void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory);
/** Create a new grpc_subchannel */
grpc_subchannel* grpc_client_channel_factory_create_subchannel(
grpc_client_channel_factory* factory, const grpc_subchannel_args* args);
grpc_client_channel_factory* factory, const grpc_channel_args* args);
/** Create a new grpc_channel */
grpc_channel* grpc_client_channel_factory_create_channel(

@ -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(
@ -30,6 +31,7 @@ LoadBalancingPolicy::LoadBalancingPolicy(const 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_(*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,9 +54,11 @@ 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_LB_ADDRESSES channel arg.
/// GRPC_ARG_SERVER_ADDRESS_LIST channel arg.
grpc_channel_args* args = nullptr;
/// Load balancing config from the resolver.
grpc_json* lb_config = nullptr;
@ -65,26 +68,34 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
struct PickState {
/// Initial metadata associated with the picking call.
grpc_metadata_batch* initial_metadata = nullptr;
/// Bitmask used for selective cancelling. See
/// Pointer to bitmask used for selective cancelling. See
/// \a CancelMatchingPicksLocked() and \a GRPC_INITIAL_METADATA_* in
/// grpc_types.h.
uint32_t initial_metadata_flags = 0;
uint32_t* initial_metadata_flags = nullptr;
/// Storage for LB token in \a initial_metadata, or nullptr if not used.
grpc_linked_mdelem lb_token_mdelem_storage;
/// 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;
/// Will be populated with context to pass to the subchannel call, if
/// needed.
grpc_call_context_element subchannel_call_context[GRPC_CONTEXT_COUNT] = {};
/// Upon success, \a *user_data will be set to whatever opaque information
/// may need to be propagated from the LB policy, or nullptr if not needed.
// TODO(roth): As part of revamping our metadata APIs, try to find a
// way to clean this up and C++-ify it.
void** user_data = nullptr;
/// Next pointer. For internal use by LB policy.
PickState* next = nullptr;
};
@ -93,9 +104,12 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
LoadBalancingPolicy(const LoadBalancingPolicy&) = delete;
LoadBalancingPolicy& operator=(const LoadBalancingPolicy&) = delete;
/// Returns the name of the LB policy.
virtual const char* name() const GRPC_ABSTRACT;
/// Updates the policy with a new set of \a args and a new \a lb_config from
/// the resolver. Note that the LB policy gets the set of addresses from the
/// GRPC_ARG_LB_ADDRESSES channel arg.
/// GRPC_ARG_SERVER_ADDRESS_LIST channel arg.
virtual void UpdateLocked(const grpc_channel_args& args,
grpc_json* lb_config) GRPC_ABSTRACT;
@ -173,6 +187,12 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
grpc_pollset_set* interested_parties() const { return interested_parties_; }
/// Returns a pointer to the subchannel pool of type
/// RefCountedPtr<SubchannelPoolInterface>.
RefCountedPtr<SubchannelPoolInterface>* subchannel_pool() {
return &subchannel_pool_;
}
GRPC_ABSTRACT_BASE_CLASS
protected:
@ -206,16 +226,12 @@ 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.
grpc_closure* request_reresolution_;
// Dummy classes needed for alignment issues.
// See https://github.com/grpc/grpc/issues/16032 for context.
// TODO(ncteisen): remove this as soon as the issue is resolved.
channelz::ChildRefsList dummy_list_foo;
channelz::ChildRefsList dummy_list_bar;
};
} // namespace grpc_core

@ -84,7 +84,7 @@
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
#include "src/core/ext/filters/client_channel/subchannel_index.h"
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
@ -113,15 +113,21 @@
#define GRPC_GRPCLB_RECONNECT_JITTER 0.2
#define GRPC_GRPCLB_DEFAULT_FALLBACK_TIMEOUT_MS 10000
#define GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN "grpc.grpclb_address_lb_token"
namespace grpc_core {
TraceFlag grpc_lb_glb_trace(false, "glb");
namespace {
constexpr char kGrpclb[] = "grpclb";
class GrpcLb : public LoadBalancingPolicy {
public:
GrpcLb(const grpc_lb_addresses* addresses, const Args& args);
explicit GrpcLb(const Args& args);
const char* name() const override { return kGrpclb; }
void UpdateLocked(const grpc_channel_args& args,
grpc_json* lb_config) override;
@ -161,9 +167,6 @@ class GrpcLb : public LoadBalancingPolicy {
// Our on_complete closure and the original one.
grpc_closure on_complete;
grpc_closure* original_on_complete;
// The LB token associated with the pick. This is set via user_data in
// the pick.
grpc_mdelem lb_token;
// Stats for client-side load reporting.
RefCountedPtr<GrpcLbClientStats> client_stats;
// Next pending pick.
@ -293,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?
@ -329,7 +331,7 @@ class GrpcLb : public LoadBalancingPolicy {
// 0 means not using fallback.
int lb_fallback_timeout_ms_ = 0;
// The backend addresses from the resolver.
grpc_lb_addresses* fallback_backend_addresses_ = nullptr;
UniquePtr<ServerAddressList> fallback_backend_addresses_;
// Fallback timer.
bool fallback_timer_callback_pending_ = false;
grpc_timer lb_fallback_timer_;
@ -349,7 +351,7 @@ class GrpcLb : public LoadBalancingPolicy {
// serverlist parsing code
//
// vtable for LB tokens in grpc_lb_addresses
// vtable for LB token channel arg.
void* lb_token_copy(void* token) {
return token == nullptr
? nullptr
@ -361,38 +363,13 @@ void lb_token_destroy(void* token) {
}
}
int lb_token_cmp(void* token1, void* token2) {
if (token1 > token2) return 1;
if (token1 < token2) return -1;
// Always indicate a match, since we don't want this channel arg to
// affect the subchannel's key in the index.
return 0;
}
const grpc_lb_user_data_vtable lb_token_vtable = {
const grpc_arg_pointer_vtable lb_token_arg_vtable = {
lb_token_copy, lb_token_destroy, lb_token_cmp};
// Returns the backend addresses extracted from the given addresses.
grpc_lb_addresses* ExtractBackendAddresses(const grpc_lb_addresses* addresses) {
// First pass: count the number of backend addresses.
size_t num_backends = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (!addresses->addresses[i].is_balancer) {
++num_backends;
}
}
// Second pass: actually populate the addresses and (empty) LB tokens.
grpc_lb_addresses* backend_addresses =
grpc_lb_addresses_create(num_backends, &lb_token_vtable);
size_t num_copied = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (addresses->addresses[i].is_balancer) continue;
const grpc_resolved_address* addr = &addresses->addresses[i].address;
grpc_lb_addresses_set_address(backend_addresses, num_copied, &addr->addr,
addr->len, false /* is_balancer */,
nullptr /* balancer_name */,
(void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload);
++num_copied;
}
return backend_addresses;
}
bool IsServerValid(const grpc_grpclb_server* server, size_t idx, bool log) {
if (server->drop) return false;
const grpc_grpclb_ip_address* ip = &server->ip_address;
@ -440,30 +417,16 @@ void ParseServer(const grpc_grpclb_server* server,
}
// Returns addresses extracted from \a serverlist.
grpc_lb_addresses* ProcessServerlist(const grpc_grpclb_serverlist* serverlist) {
size_t num_valid = 0;
/* first pass: count how many are valid in order to allocate the necessary
* memory in a single block */
ServerAddressList ProcessServerlist(const grpc_grpclb_serverlist* serverlist) {
ServerAddressList addresses;
for (size_t i = 0; i < serverlist->num_servers; ++i) {
if (IsServerValid(serverlist->servers[i], i, true)) ++num_valid;
}
grpc_lb_addresses* lb_addresses =
grpc_lb_addresses_create(num_valid, &lb_token_vtable);
/* second pass: actually populate the addresses and LB tokens (aka user data
* to the outside world) to be read by the RR policy during its creation.
* Given that the validity tests are very cheap, they are performed again
* instead of marking the valid ones during the first pass, as this would
* incurr in an allocation due to the arbitrary number of server */
size_t addr_idx = 0;
for (size_t sl_idx = 0; sl_idx < serverlist->num_servers; ++sl_idx) {
const grpc_grpclb_server* server = serverlist->servers[sl_idx];
if (!IsServerValid(serverlist->servers[sl_idx], sl_idx, false)) continue;
GPR_ASSERT(addr_idx < num_valid);
/* address processing */
const grpc_grpclb_server* server = serverlist->servers[i];
if (!IsServerValid(serverlist->servers[i], i, false)) continue;
// Address processing.
grpc_resolved_address addr;
ParseServer(server, &addr);
/* lb token processing */
void* user_data;
// LB token processing.
grpc_mdelem lb_token;
if (server->has_load_balance_token) {
const size_t lb_token_max_length =
GPR_ARRAY_SIZE(server->load_balance_token);
@ -471,9 +434,7 @@ grpc_lb_addresses* ProcessServerlist(const grpc_grpclb_serverlist* serverlist) {
strnlen(server->load_balance_token, lb_token_max_length);
grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer(
server->load_balance_token, lb_token_length);
user_data =
(void*)grpc_mdelem_from_slices(GRPC_MDSTR_LB_TOKEN, lb_token_mdstr)
.payload;
lb_token = grpc_mdelem_from_slices(GRPC_MDSTR_LB_TOKEN, lb_token_mdstr);
} else {
char* uri = grpc_sockaddr_to_uri(&addr);
gpr_log(GPR_INFO,
@ -481,15 +442,18 @@ grpc_lb_addresses* ProcessServerlist(const grpc_grpclb_serverlist* serverlist) {
"be used instead",
uri);
gpr_free(uri);
user_data = (void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
lb_token = GRPC_MDELEM_LB_TOKEN_EMPTY;
}
grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
false /* is_balancer */,
nullptr /* balancer_name */, user_data);
++addr_idx;
}
GPR_ASSERT(addr_idx == num_valid);
return lb_addresses;
// Add address.
grpc_arg arg = grpc_channel_arg_pointer_create(
const_cast<char*>(GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN),
(void*)lb_token.payload, &lb_token_arg_vtable);
grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1);
addresses.emplace_back(addr, args);
// Clean up.
GRPC_MDELEM_UNREF(lb_token);
}
return addresses;
}
//
@ -565,8 +529,7 @@ void GrpcLb::BalancerCallState::Orphan() {
void GrpcLb::BalancerCallState::StartQuery() {
GPR_ASSERT(lb_call_ != nullptr);
if (grpc_lb_glb_trace.enabled()) {
gpr_log(GPR_INFO,
"[grpclb %p] Starting LB call (lb_calld: %p, lb_call: %p)",
gpr_log(GPR_INFO, "[grpclb %p] lb_calld=%p: Starting LB call %p",
grpclb_policy_.get(), this, lb_call_);
}
// Create the ops.
@ -710,8 +673,9 @@ void GrpcLb::BalancerCallState::SendClientLoadReportLocked() {
grpc_call_error call_error = grpc_call_start_batch_and_execute(
lb_call_, &op, 1, &client_load_report_closure_);
if (GPR_UNLIKELY(call_error != GRPC_CALL_OK)) {
gpr_log(GPR_ERROR, "[grpclb %p] call_error=%d", grpclb_policy_.get(),
call_error);
gpr_log(GPR_ERROR,
"[grpclb %p] lb_calld=%p call_error=%d sending client load report",
grpclb_policy_.get(), this, call_error);
GPR_ASSERT(GRPC_CALL_OK == call_error);
}
}
@ -772,15 +736,17 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
&initial_response->client_stats_report_interval));
if (grpc_lb_glb_trace.enabled()) {
gpr_log(GPR_INFO,
"[grpclb %p] Received initial LB response message; "
"client load reporting interval = %" PRId64 " milliseconds",
grpclb_policy, lb_calld->client_stats_report_interval_);
"[grpclb %p] lb_calld=%p: Received initial LB response "
"message; client load reporting interval = %" PRId64
" milliseconds",
grpclb_policy, lb_calld,
lb_calld->client_stats_report_interval_);
}
} else if (grpc_lb_glb_trace.enabled()) {
gpr_log(GPR_INFO,
"[grpclb %p] Received initial LB response message; client load "
"reporting NOT enabled",
grpclb_policy);
"[grpclb %p] lb_calld=%p: Received initial LB response message; "
"client load reporting NOT enabled",
grpclb_policy, lb_calld);
}
grpc_grpclb_initial_response_destroy(initial_response);
lb_calld->seen_initial_response_ = true;
@ -790,15 +756,17 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
GPR_ASSERT(lb_calld->lb_call_ != nullptr);
if (grpc_lb_glb_trace.enabled()) {
gpr_log(GPR_INFO,
"[grpclb %p] Serverlist with %" PRIuPTR " servers received",
grpclb_policy, serverlist->num_servers);
"[grpclb %p] lb_calld=%p: Serverlist with %" PRIuPTR
" servers received",
grpclb_policy, lb_calld, serverlist->num_servers);
for (size_t i = 0; i < serverlist->num_servers; ++i) {
grpc_resolved_address addr;
ParseServer(serverlist->servers[i], &addr);
char* ipport;
grpc_sockaddr_to_string(&ipport, &addr, false);
gpr_log(GPR_INFO, "[grpclb %p] Serverlist[%" PRIuPTR "]: %s",
grpclb_policy, i, ipport);
gpr_log(GPR_INFO,
"[grpclb %p] lb_calld=%p: Serverlist[%" PRIuPTR "]: %s",
grpclb_policy, lb_calld, i, ipport);
gpr_free(ipport);
}
}
@ -818,9 +786,9 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
if (grpc_grpclb_serverlist_equals(grpclb_policy->serverlist_, serverlist)) {
if (grpc_lb_glb_trace.enabled()) {
gpr_log(GPR_INFO,
"[grpclb %p] Incoming server list identical to current, "
"ignoring.",
grpclb_policy);
"[grpclb %p] lb_calld=%p: Incoming server list identical to "
"current, ignoring.",
grpclb_policy, lb_calld);
}
grpc_grpclb_destroy_serverlist(serverlist);
} else { // New serverlist.
@ -829,8 +797,7 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
grpc_grpclb_destroy_serverlist(grpclb_policy->serverlist_);
} else {
// Dispose of the fallback.
grpc_lb_addresses_destroy(grpclb_policy->fallback_backend_addresses_);
grpclb_policy->fallback_backend_addresses_ = nullptr;
grpclb_policy->fallback_backend_addresses_.reset();
if (grpclb_policy->fallback_timer_callback_pending_) {
grpc_timer_cancel(&grpclb_policy->lb_fallback_timer_);
}
@ -847,8 +814,9 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked(
char* response_slice_str =
grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX);
gpr_log(GPR_ERROR,
"[grpclb %p] Invalid LB response received: '%s'. Ignoring.",
grpclb_policy, response_slice_str);
"[grpclb %p] lb_calld=%p: Invalid LB response received: '%s'. "
"Ignoring.",
grpclb_policy, lb_calld, response_slice_str);
gpr_free(response_slice_str);
}
grpc_slice_unref_internal(response_slice);
@ -879,9 +847,9 @@ void GrpcLb::BalancerCallState::OnBalancerStatusReceivedLocked(
char* status_details =
grpc_slice_to_c_string(lb_calld->lb_call_status_details_);
gpr_log(GPR_INFO,
"[grpclb %p] Status from LB server received. Status = %d, details "
"= '%s', (lb_calld: %p, lb_call: %p), error '%s'",
grpclb_policy, lb_calld->lb_call_status_, status_details, lb_calld,
"[grpclb %p] lb_calld=%p: Status from LB server received. "
"Status = %d, details = '%s', (lb_call: %p), error '%s'",
grpclb_policy, lb_calld, lb_calld->lb_call_status_, status_details,
lb_calld->lb_call_, grpc_error_string(error));
gpr_free(status_details);
}
@ -910,31 +878,25 @@ void GrpcLb::BalancerCallState::OnBalancerStatusReceivedLocked(
// helper code for creating balancer channel
//
grpc_lb_addresses* ExtractBalancerAddresses(
const grpc_lb_addresses* addresses) {
size_t num_grpclb_addrs = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
}
// There must be at least one balancer address, or else the
// client_channel would not have chosen this LB policy.
GPR_ASSERT(num_grpclb_addrs > 0);
grpc_lb_addresses* lb_addresses =
grpc_lb_addresses_create(num_grpclb_addrs, nullptr);
size_t lb_addresses_idx = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (!addresses->addresses[i].is_balancer) continue;
if (GPR_UNLIKELY(addresses->addresses[i].user_data != nullptr)) {
gpr_log(GPR_ERROR,
"This LB policy doesn't support user data. It will be ignored");
ServerAddressList ExtractBalancerAddresses(const ServerAddressList& addresses) {
ServerAddressList balancer_addresses;
for (size_t i = 0; i < addresses.size(); ++i) {
if (addresses[i].IsBalancer()) {
// Strip out the is_balancer channel arg, since we don't want to
// recursively use the grpclb policy in the channel used to talk to
// the balancers. Note that we do NOT strip out the balancer_name
// channel arg, since we need that to set the authority correctly
// to talk to the balancers.
static const char* args_to_remove[] = {
GRPC_ARG_ADDRESS_IS_BALANCER,
};
balancer_addresses.emplace_back(
addresses[i].address(),
grpc_channel_args_copy_and_remove(addresses[i].args(), args_to_remove,
GPR_ARRAY_SIZE(args_to_remove)));
}
grpc_lb_addresses_set_address(
lb_addresses, lb_addresses_idx++, addresses->addresses[i].address.addr,
addresses->addresses[i].address.len, false /* is balancer */,
addresses->addresses[i].balancer_name, nullptr /* user data */);
}
GPR_ASSERT(num_grpclb_addrs == lb_addresses_idx);
return lb_addresses;
return balancer_addresses;
}
/* Returns the channel args for the LB channel, used to create a bidirectional
@ -946,10 +908,10 @@ grpc_lb_addresses* ExtractBalancerAddresses(
* above the grpclb policy.
* - \a args: other args inherited from the grpclb policy. */
grpc_channel_args* BuildBalancerChannelArgs(
const grpc_lb_addresses* addresses,
const ServerAddressList& addresses,
FakeResolverResponseGenerator* response_generator,
const grpc_channel_args* args) {
grpc_lb_addresses* lb_addresses = ExtractBalancerAddresses(addresses);
ServerAddressList balancer_addresses = ExtractBalancerAddresses(addresses);
// Channel args to remove.
static const char* args_to_remove[] = {
// LB policy name, since we want to use the default (pick_first) in
@ -967,7 +929,7 @@ grpc_channel_args* BuildBalancerChannelArgs(
// is_balancer=true. We need the LB channel to return addresses with
// is_balancer=false so that it does not wind up recursively using the
// grpclb LB policy, as per the special case logic in client_channel.c.
GRPC_ARG_LB_ADDRESSES,
GRPC_ARG_SERVER_ADDRESS_LIST,
// The fake resolver response generator, because we are replacing it
// with the one from the grpclb policy, used to propagate updates to
// the LB channel.
@ -983,10 +945,10 @@ grpc_channel_args* BuildBalancerChannelArgs(
};
// Channel args to add.
const grpc_arg args_to_add[] = {
// New LB addresses.
// New address list.
// Note that we pass these in both when creating the LB channel
// and via the fake resolver. The latter is what actually gets used.
grpc_lb_addresses_create_channel_arg(lb_addresses),
CreateServerAddressListChannelArg(&balancer_addresses),
// The fake resolver response generator, which we use to inject
// address updates into the LB channel.
grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
@ -1004,18 +966,14 @@ grpc_channel_args* BuildBalancerChannelArgs(
args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), args_to_add,
GPR_ARRAY_SIZE(args_to_add));
// Make any necessary modifications for security.
new_args = grpc_lb_policy_grpclb_modify_lb_channel_args(new_args);
// Clean up.
grpc_lb_addresses_destroy(lb_addresses);
return new_args;
return grpc_lb_policy_grpclb_modify_lb_channel_args(new_args);
}
//
// ctor and dtor
//
GrpcLb::GrpcLb(const grpc_lb_addresses* addresses,
const LoadBalancingPolicy::Args& args)
GrpcLb::GrpcLb(const LoadBalancingPolicy::Args& args)
: LoadBalancingPolicy(args),
response_generator_(MakeRefCounted<FakeResolverResponseGenerator>()),
lb_call_backoff_(
@ -1027,8 +985,6 @@ GrpcLb::GrpcLb(const grpc_lb_addresses* addresses,
.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));
@ -1065,17 +1021,12 @@ GrpcLb::GrpcLb(const grpc_lb_addresses* addresses,
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_);
}
if (fallback_backend_addresses_ != nullptr) {
grpc_lb_addresses_destroy(fallback_backend_addresses_);
}
grpc_subchannel_index_unref();
}
void GrpcLb::ShutdownLocked() {
@ -1095,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");
@ -1122,7 +1072,6 @@ void GrpcLb::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) {
while ((pp = pending_picks_) != nullptr) {
pending_picks_ = pp->next;
pp->pick->on_complete = pp->original_on_complete;
pp->pick->user_data = nullptr;
grpc_error* error = GRPC_ERROR_NONE;
if (new_policy->PickLocked(pp->pick, &error)) {
// Synchronous return; schedule closure.
@ -1184,7 +1133,7 @@ void GrpcLb::CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
pending_picks_ = nullptr;
while (pp != nullptr) {
PendingPick* next = pp->next;
if ((pp->pick->initial_metadata_flags & initial_metadata_flags_mask) ==
if ((*pp->pick->initial_metadata_flags & initial_metadata_flags_mask) ==
initial_metadata_flags_eq) {
// Note: pp is deleted in this callback.
GRPC_CLOSURE_SCHED(&pp->on_complete,
@ -1254,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);
}
}
@ -1276,9 +1223,27 @@ void GrpcLb::NotifyOnStateChangeLocked(grpc_connectivity_state* current,
notify);
}
// Returns the backend addresses extracted from the given addresses.
UniquePtr<ServerAddressList> ExtractBackendAddresses(
const ServerAddressList& addresses) {
void* lb_token = (void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
grpc_arg arg = grpc_channel_arg_pointer_create(
const_cast<char*>(GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN), lb_token,
&lb_token_arg_vtable);
auto backend_addresses = MakeUnique<ServerAddressList>();
for (size_t i = 0; i < addresses.size(); ++i) {
if (!addresses[i].IsBalancer()) {
backend_addresses->emplace_back(
addresses[i].address(),
grpc_channel_args_copy_and_add(addresses[i].args(), &arg, 1));
}
}
return backend_addresses;
}
void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
if (GPR_UNLIKELY(arg == nullptr || arg->type != GRPC_ARG_POINTER)) {
const ServerAddressList* addresses = FindServerAddressListChannelArg(&args);
if (addresses == nullptr) {
// Ignore this update.
gpr_log(
GPR_ERROR,
@ -1286,13 +1251,8 @@ void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
this);
return;
}
const grpc_lb_addresses* addresses =
static_cast<const grpc_lb_addresses*>(arg->value.pointer.p);
// Update fallback address list.
if (fallback_backend_addresses_ != nullptr) {
grpc_lb_addresses_destroy(fallback_backend_addresses_);
}
fallback_backend_addresses_ = ExtractBackendAddresses(addresses);
fallback_backend_addresses_ = ExtractBackendAddresses(*addresses);
// Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args,
// since we use this to trigger the client_load_reporting filter.
static const char* args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME};
@ -1303,17 +1263,20 @@ void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
&args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1);
// Construct args for balancer channel.
grpc_channel_args* lb_channel_args =
BuildBalancerChannelArgs(addresses, response_generator_.get(), &args);
BuildBalancerChannelArgs(*addresses, response_generator_.get(), &args);
// Create balancer channel if needed.
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
@ -1509,12 +1472,17 @@ void DestroyClientStats(void* arg) {
}
void GrpcLb::PendingPickSetMetadataAndContext(PendingPick* pp) {
/* if connected_subchannel is nullptr, no pick has been made by the RR
* policy (e.g., all addresses failed to connect). There won't be any
* user_data/token available */
// If connected_subchannel is nullptr, no pick has been made by the RR
// policy (e.g., all addresses failed to connect). There won't be any
// LB token available.
if (pp->pick->connected_subchannel != nullptr) {
if (GPR_LIKELY(!GRPC_MDISNULL(pp->lb_token))) {
AddLbTokenToInitialMetadata(GRPC_MDELEM_REF(pp->lb_token),
const grpc_arg* arg =
grpc_channel_args_find(pp->pick->connected_subchannel->args(),
GRPC_ARG_GRPCLB_ADDRESS_LB_TOKEN);
if (arg != nullptr) {
grpc_mdelem lb_token = {
reinterpret_cast<uintptr_t>(arg->value.pointer.p)};
AddLbTokenToInitialMetadata(GRPC_MDELEM_REF(lb_token),
&pp->pick->lb_token_mdelem_storage,
pp->pick->initial_metadata);
} else {
@ -1598,12 +1566,10 @@ bool GrpcLb::PickFromRoundRobinPolicyLocked(bool force_async, PendingPick* pp,
return true;
}
}
// Set client_stats and user_data.
// Set client_stats.
if (lb_calld_ != nullptr && lb_calld_->client_stats() != nullptr) {
pp->client_stats = lb_calld_->client_stats()->Ref();
}
GPR_ASSERT(pp->pick->user_data == nullptr);
pp->pick->user_data = (void**)&pp->lb_token;
// Pick via the RR policy.
bool pick_done = rr_policy_->PickLocked(pp->pick, error);
if (pick_done) {
@ -1631,6 +1597,10 @@ void GrpcLb::CreateRoundRobinPolicyLocked(const Args& args) {
this);
return;
}
if (grpc_lb_glb_trace.enabled()) {
gpr_log(GPR_INFO, "[grpclb %p] Created new RR policy %p", this,
rr_policy_.get());
}
// TODO(roth): We currently track this ref manually. Once the new
// ClosureRef API is done, pass the RefCountedPtr<> along with the closure.
auto self = Ref(DEBUG_LOCATION, "on_rr_reresolution_requested");
@ -1668,10 +1638,11 @@ void GrpcLb::CreateRoundRobinPolicyLocked(const Args& args) {
}
grpc_channel_args* GrpcLb::CreateRoundRobinPolicyArgsLocked() {
grpc_lb_addresses* addresses;
ServerAddressList tmp_addresses;
ServerAddressList* addresses = &tmp_addresses;
bool is_backend_from_grpclb_load_balancer = false;
if (serverlist_ != nullptr) {
addresses = ProcessServerlist(serverlist_);
tmp_addresses = ProcessServerlist(serverlist_);
is_backend_from_grpclb_load_balancer = true;
} else {
// If CreateOrUpdateRoundRobinPolicyLocked() is invoked when we haven't
@ -1680,14 +1651,14 @@ grpc_channel_args* GrpcLb::CreateRoundRobinPolicyArgsLocked() {
// empty, in which case the new round_robin policy will keep the requested
// picks pending.
GPR_ASSERT(fallback_backend_addresses_ != nullptr);
addresses = grpc_lb_addresses_copy(fallback_backend_addresses_);
addresses = fallback_backend_addresses_.get();
}
GPR_ASSERT(addresses != nullptr);
// Replace the LB addresses in the channel args that we pass down to
// Replace the server address list in the channel args that we pass down to
// the subchannel.
static const char* keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
static const char* keys_to_remove[] = {GRPC_ARG_SERVER_ADDRESS_LIST};
grpc_arg args_to_add[3] = {
grpc_lb_addresses_create_channel_arg(addresses),
CreateServerAddressListChannelArg(addresses),
// A channel arg indicating if the target is a backend inferred from a
// grpclb load balancer.
grpc_channel_arg_integer_create(
@ -1704,7 +1675,6 @@ grpc_channel_args* GrpcLb::CreateRoundRobinPolicyArgsLocked() {
grpc_channel_args* args = grpc_channel_args_copy_and_add_and_remove(
args_, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add,
num_args_to_add);
grpc_lb_addresses_destroy(addresses);
return args;
}
@ -1723,11 +1693,8 @@ void GrpcLb::CreateOrUpdateRoundRobinPolicyLocked() {
lb_policy_args.combiner = combiner();
lb_policy_args.client_channel_factory = client_channel_factory();
lb_policy_args.args = args;
lb_policy_args.subchannel_pool = subchannel_pool();
CreateRoundRobinPolicyLocked(lb_policy_args);
if (grpc_lb_glb_trace.enabled()) {
gpr_log(GPR_INFO, "[grpclb %p] Created new RR policy %p", this,
rr_policy_.get());
}
}
grpc_channel_args_destroy(args);
}
@ -1837,22 +1804,21 @@ class GrpcLbFactory : public LoadBalancingPolicyFactory {
OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
const LoadBalancingPolicy::Args& args) const override {
/* Count the number of gRPC-LB addresses. There must be at least one. */
const grpc_arg* arg =
grpc_channel_args_find(args.args, GRPC_ARG_LB_ADDRESSES);
if (arg == nullptr || arg->type != GRPC_ARG_POINTER) {
return nullptr;
}
grpc_lb_addresses* addresses =
static_cast<grpc_lb_addresses*>(arg->value.pointer.p);
size_t num_grpclb_addrs = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
const ServerAddressList* addresses =
FindServerAddressListChannelArg(args.args);
if (addresses == nullptr) return nullptr;
bool found_balancer = false;
for (size_t i = 0; i < addresses->size(); ++i) {
if ((*addresses)[i].IsBalancer()) {
found_balancer = true;
break;
}
}
if (num_grpclb_addrs == 0) return nullptr;
return OrphanablePtr<LoadBalancingPolicy>(New<GrpcLb>(addresses, args));
if (!found_balancer) return nullptr;
return OrphanablePtr<LoadBalancingPolicy>(New<GrpcLb>(args));
}
const char* name() const override { return "grpclb"; }
const char* name() const override { return kGrpclb; }
};
} // namespace

@ -21,7 +21,7 @@
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include <grpc/impl/codegen/grpc_types.h>
/// Makes any necessary modifications to \a args for use in the grpclb
/// balancer channel.

@ -26,6 +26,7 @@
#include <grpc/support/string_util.h>
#include "src/core/ext/filters/client_channel/client_channel.h"
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
@ -42,22 +43,23 @@ int BalancerNameCmp(const grpc_core::UniquePtr<char>& a,
}
RefCountedPtr<TargetAuthorityTable> CreateTargetAuthorityTable(
grpc_lb_addresses* addresses) {
const ServerAddressList& addresses) {
TargetAuthorityTable::Entry* target_authority_entries =
static_cast<TargetAuthorityTable::Entry*>(gpr_zalloc(
sizeof(*target_authority_entries) * addresses->num_addresses));
for (size_t i = 0; i < addresses->num_addresses; ++i) {
static_cast<TargetAuthorityTable::Entry*>(
gpr_zalloc(sizeof(*target_authority_entries) * addresses.size()));
for (size_t i = 0; i < addresses.size(); ++i) {
char* addr_str;
GPR_ASSERT(grpc_sockaddr_to_string(
&addr_str, &addresses->addresses[i].address, true) > 0);
GPR_ASSERT(
grpc_sockaddr_to_string(&addr_str, &addresses[i].address(), true) > 0);
target_authority_entries[i].key = grpc_slice_from_copied_string(addr_str);
target_authority_entries[i].value.reset(
gpr_strdup(addresses->addresses[i].balancer_name));
gpr_free(addr_str);
char* balancer_name = grpc_channel_arg_get_string(grpc_channel_args_find(
addresses[i].args(), GRPC_ARG_ADDRESS_BALANCER_NAME));
target_authority_entries[i].value.reset(gpr_strdup(balancer_name));
}
RefCountedPtr<TargetAuthorityTable> target_authority_table =
TargetAuthorityTable::Create(addresses->num_addresses,
target_authority_entries, BalancerNameCmp);
TargetAuthorityTable::Create(addresses.size(), target_authority_entries,
BalancerNameCmp);
gpr_free(target_authority_entries);
return target_authority_table;
}
@ -72,13 +74,12 @@ grpc_channel_args* grpc_lb_policy_grpclb_modify_lb_channel_args(
grpc_arg args_to_add[2];
size_t num_args_to_add = 0;
// Add arg for targets info table.
const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_LB_ADDRESSES);
GPR_ASSERT(arg != nullptr);
GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
grpc_lb_addresses* addresses =
static_cast<grpc_lb_addresses*>(arg->value.pointer.p);
grpc_core::ServerAddressList* addresses =
grpc_core::FindServerAddressListChannelArg(args);
GPR_ASSERT(addresses != nullptr);
grpc_core::RefCountedPtr<grpc_core::TargetAuthorityTable>
target_authority_table = grpc_core::CreateTargetAuthorityTable(addresses);
target_authority_table =
grpc_core::CreateTargetAuthorityTable(*addresses);
args_to_add[num_args_to_add++] =
grpc_core::CreateTargetAuthorityTableChannelArg(
target_authority_table.get());
@ -87,22 +88,18 @@ grpc_channel_args* grpc_lb_policy_grpclb_modify_lb_channel_args(
// bearer token credentials.
grpc_channel_credentials* channel_credentials =
grpc_channel_credentials_find_in_args(args);
grpc_channel_credentials* creds_sans_call_creds = nullptr;
grpc_core::RefCountedPtr<grpc_channel_credentials> creds_sans_call_creds;
if (channel_credentials != nullptr) {
creds_sans_call_creds =
grpc_channel_credentials_duplicate_without_call_credentials(
channel_credentials);
channel_credentials->duplicate_without_call_credentials();
GPR_ASSERT(creds_sans_call_creds != nullptr);
args_to_remove[num_args_to_remove++] = GRPC_ARG_CHANNEL_CREDENTIALS;
args_to_add[num_args_to_add++] =
grpc_channel_credentials_to_arg(creds_sans_call_creds);
grpc_channel_credentials_to_arg(creds_sans_call_creds.get());
}
grpc_channel_args* result = grpc_channel_args_copy_and_add_and_remove(
args, args_to_remove, num_args_to_remove, args_to_add, num_args_to_add);
// Clean up.
grpc_channel_args_destroy(args);
if (creds_sans_call_creds != nullptr) {
grpc_channel_credentials_unref(creds_sans_call_creds);
}
return result;
}

@ -25,7 +25,7 @@
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h"
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#define GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH 128

@ -24,8 +24,8 @@
#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/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"
@ -42,10 +42,14 @@ namespace {
// pick_first LB policy
//
constexpr char kPickFirst[] = "pick_first";
class PickFirst : public LoadBalancingPolicy {
public:
explicit PickFirst(const Args& args);
const char* name() const override { return kPickFirst; }
void UpdateLocked(const grpc_channel_args& args,
grpc_json* lb_config) override;
bool PickLocked(PickState* pick, grpc_error** error) override;
@ -75,11 +79,9 @@ class PickFirst : public LoadBalancingPolicy {
PickFirstSubchannelData(
SubchannelList<PickFirstSubchannelList, PickFirstSubchannelData>*
subchannel_list,
const grpc_lb_user_data_vtable* user_data_vtable,
const grpc_lb_address& address, grpc_subchannel* subchannel,
const ServerAddress& address, grpc_subchannel* subchannel,
grpc_combiner* combiner)
: SubchannelData(subchannel_list, user_data_vtable, address, subchannel,
combiner) {}
: SubchannelData(subchannel_list, address, subchannel, combiner) {}
void ProcessConnectivityChangeLocked(
grpc_connectivity_state connectivity_state, grpc_error* error) override;
@ -95,7 +97,7 @@ class PickFirst : public LoadBalancingPolicy {
PickFirstSubchannelData> {
public:
PickFirstSubchannelList(PickFirst* policy, TraceFlag* tracer,
const grpc_lb_addresses* addresses,
const ServerAddressList& addresses,
grpc_combiner* combiner,
grpc_client_channel_factory* client_channel_factory,
const grpc_channel_args& args)
@ -161,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() {
@ -173,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) {
@ -235,7 +235,7 @@ void PickFirst::CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
pending_picks_ = nullptr;
while (pick != nullptr) {
PickState* next = pick->next;
if ((pick->initial_metadata_flags & initial_metadata_flags_mask) ==
if ((*pick->initial_metadata_flags & initial_metadata_flags_mask) ==
initial_metadata_flags_eq) {
GRPC_CLOSURE_SCHED(pick->on_complete,
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
@ -337,8 +337,8 @@ void PickFirst::UpdateChildRefsLocked() {
void PickFirst::UpdateLocked(const grpc_channel_args& args,
grpc_json* lb_config) {
AutoChildRefsUpdater guard(this);
const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
if (arg == nullptr || arg->type != GRPC_ARG_POINTER) {
const ServerAddressList* addresses = FindServerAddressListChannelArg(&args);
if (addresses == nullptr) {
if (subchannel_list_ == nullptr) {
// If we don't have a current subchannel list, go into TRANSIENT FAILURE.
grpc_connectivity_state_set(
@ -354,19 +354,17 @@ void PickFirst::UpdateLocked(const grpc_channel_args& args,
}
return;
}
const grpc_lb_addresses* addresses =
static_cast<const grpc_lb_addresses*>(arg->value.pointer.p);
if (grpc_lb_pick_first_trace.enabled()) {
gpr_log(GPR_INFO,
"Pick First %p received update with %" PRIuPTR " addresses", this,
addresses->num_addresses);
addresses->size());
}
grpc_arg new_arg = grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1);
grpc_channel_args* new_args =
grpc_channel_args_copy_and_add(&args, &new_arg, 1);
auto subchannel_list = MakeOrphanable<PickFirstSubchannelList>(
this, &grpc_lb_pick_first_trace, addresses, combiner(),
this, &grpc_lb_pick_first_trace, *addresses, combiner(),
client_channel_factory(), *new_args);
grpc_channel_args_destroy(new_args);
if (subchannel_list->num_subchannels() == 0) {
@ -625,7 +623,7 @@ class PickFirstFactory : public LoadBalancingPolicyFactory {
return OrphanablePtr<LoadBalancingPolicy>(New<PickFirst>(args));
}
const char* name() const override { return "pick_first"; }
const char* name() const override { return kPickFirst; }
};
} // namespace

@ -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"
@ -53,10 +52,14 @@ namespace {
// round_robin LB policy
//
constexpr char kRoundRobin[] = "round_robin";
class RoundRobin : public LoadBalancingPolicy {
public:
explicit RoundRobin(const Args& args);
const char* name() const override { return kRoundRobin; }
void UpdateLocked(const grpc_channel_args& args,
grpc_json* lb_config) override;
bool PickLocked(PickState* pick, grpc_error** error) override;
@ -82,8 +85,6 @@ class RoundRobin : public LoadBalancingPolicy {
// Data for a particular subchannel in a subchannel list.
// This subclass adds the following functionality:
// - Tracks user_data associated with each address, which will be
// returned along with picks that select the subchannel.
// - Tracks the previous connectivity state of the subchannel, so that
// we know how many subchannels are in each state.
class RoundRobinSubchannelData
@ -93,26 +94,9 @@ class RoundRobin : public LoadBalancingPolicy {
RoundRobinSubchannelData(
SubchannelList<RoundRobinSubchannelList, RoundRobinSubchannelData>*
subchannel_list,
const grpc_lb_user_data_vtable* user_data_vtable,
const grpc_lb_address& address, grpc_subchannel* subchannel,
const ServerAddress& address, grpc_subchannel* subchannel,
grpc_combiner* combiner)
: SubchannelData(subchannel_list, user_data_vtable, address, subchannel,
combiner),
user_data_vtable_(user_data_vtable),
user_data_(user_data_vtable_ != nullptr
? user_data_vtable_->copy(address.user_data)
: nullptr) {}
void UnrefSubchannelLocked(const char* reason) override {
SubchannelData::UnrefSubchannelLocked(reason);
if (user_data_ != nullptr) {
GPR_ASSERT(user_data_vtable_ != nullptr);
user_data_vtable_->destroy(user_data_);
user_data_ = nullptr;
}
}
void* user_data() const { return user_data_; }
: SubchannelData(subchannel_list, address, subchannel, combiner) {}
grpc_connectivity_state connectivity_state() const {
return last_connectivity_state_;
@ -125,8 +109,6 @@ class RoundRobin : public LoadBalancingPolicy {
void ProcessConnectivityChangeLocked(
grpc_connectivity_state connectivity_state, grpc_error* error) override;
const grpc_lb_user_data_vtable* user_data_vtable_;
void* user_data_ = nullptr;
grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_IDLE;
};
@ -137,7 +119,7 @@ class RoundRobin : public LoadBalancingPolicy {
public:
RoundRobinSubchannelList(
RoundRobin* policy, TraceFlag* tracer,
const grpc_lb_addresses* addresses, grpc_combiner* combiner,
const ServerAddressList& addresses, grpc_combiner* combiner,
grpc_client_channel_factory* client_channel_factory,
const grpc_channel_args& args)
: SubchannelList(policy, tracer, addresses, combiner,
@ -238,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() {
@ -250,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) {
@ -312,7 +292,7 @@ void RoundRobin::CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
pending_picks_ = nullptr;
while (pick != nullptr) {
PickState* next = pick->next;
if ((pick->initial_metadata_flags & initial_metadata_flags_mask) ==
if ((*pick->initial_metadata_flags & initial_metadata_flags_mask) ==
initial_metadata_flags_eq) {
pick->connected_subchannel.reset();
GRPC_CLOSURE_SCHED(pick->on_complete,
@ -354,9 +334,6 @@ bool RoundRobin::DoPickLocked(PickState* pick) {
subchannel_list_->subchannel(next_ready_index);
GPR_ASSERT(sd->connected_subchannel() != nullptr);
pick->connected_subchannel = sd->connected_subchannel()->Ref();
if (pick->user_data != nullptr) {
*pick->user_data = sd->user_data();
}
if (grpc_lb_round_robin_trace.enabled()) {
gpr_log(GPR_INFO,
"[RR %p] Picked target <-- Subchannel %p (connected %p) (sl %p, "
@ -667,9 +644,9 @@ void RoundRobin::NotifyOnStateChangeLocked(grpc_connectivity_state* current,
void RoundRobin::UpdateLocked(const grpc_channel_args& args,
grpc_json* lb_config) {
const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
AutoChildRefsUpdater guard(this);
if (GPR_UNLIKELY(arg == nullptr || arg->type != GRPC_ARG_POINTER)) {
const ServerAddressList* addresses = FindServerAddressListChannelArg(&args);
if (addresses == nullptr) {
gpr_log(GPR_ERROR, "[RR %p] update provided no addresses; ignoring", this);
// If we don't have a current subchannel list, go into TRANSIENT_FAILURE.
// Otherwise, keep using the current subchannel list (ignore this update).
@ -681,11 +658,9 @@ void RoundRobin::UpdateLocked(const grpc_channel_args& args,
}
return;
}
grpc_lb_addresses* addresses =
static_cast<grpc_lb_addresses*>(arg->value.pointer.p);
if (grpc_lb_round_robin_trace.enabled()) {
gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " addresses",
this, addresses->num_addresses);
this, addresses->size());
}
// Replace latest_pending_subchannel_list_.
if (latest_pending_subchannel_list_ != nullptr) {
@ -696,7 +671,7 @@ void RoundRobin::UpdateLocked(const grpc_channel_args& args,
}
}
latest_pending_subchannel_list_ = MakeOrphanable<RoundRobinSubchannelList>(
this, &grpc_lb_round_robin_trace, addresses, combiner(),
this, &grpc_lb_round_robin_trace, *addresses, combiner(),
client_channel_factory(), args);
// If we haven't started picking yet or the new list is empty,
// immediately promote the new list to the current list.
@ -726,7 +701,7 @@ class RoundRobinFactory : public LoadBalancingPolicyFactory {
return OrphanablePtr<LoadBalancingPolicy>(New<RoundRobin>(args));
}
const char* name() const override { return "round_robin"; }
const char* name() const override { return kRoundRobin; }
};
} // namespace

@ -26,6 +26,7 @@
#include <grpc/support/alloc.h>
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/ext/filters/client_channel/subchannel.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/debug/trace.h"
@ -141,8 +142,7 @@ class SubchannelData {
protected:
SubchannelData(
SubchannelList<SubchannelListType, SubchannelDataType>* subchannel_list,
const grpc_lb_user_data_vtable* user_data_vtable,
const grpc_lb_address& address, grpc_subchannel* subchannel,
const ServerAddress& address, grpc_subchannel* subchannel,
grpc_combiner* combiner);
virtual ~SubchannelData();
@ -156,9 +156,8 @@ class SubchannelData {
grpc_connectivity_state connectivity_state,
grpc_error* error) GRPC_ABSTRACT;
// Unrefs the subchannel. May be overridden by subclasses that need
// to perform extra cleanup when unreffing the subchannel.
virtual void UnrefSubchannelLocked(const char* reason);
// Unrefs the subchannel.
void UnrefSubchannelLocked(const char* reason);
private:
// Updates connected_subchannel_ based on pending_connectivity_state_unsafe_.
@ -232,7 +231,7 @@ class SubchannelList : public InternallyRefCounted<SubchannelListType> {
protected:
SubchannelList(LoadBalancingPolicy* policy, TraceFlag* tracer,
const grpc_lb_addresses* addresses, grpc_combiner* combiner,
const ServerAddressList& addresses, grpc_combiner* combiner,
grpc_client_channel_factory* client_channel_factory,
const grpc_channel_args& args);
@ -277,8 +276,7 @@ class SubchannelList : public InternallyRefCounted<SubchannelListType> {
template <typename SubchannelListType, typename SubchannelDataType>
SubchannelData<SubchannelListType, SubchannelDataType>::SubchannelData(
SubchannelList<SubchannelListType, SubchannelDataType>* subchannel_list,
const grpc_lb_user_data_vtable* user_data_vtable,
const grpc_lb_address& address, grpc_subchannel* subchannel,
const ServerAddress& address, grpc_subchannel* subchannel,
grpc_combiner* combiner)
: subchannel_list_(subchannel_list),
subchannel_(subchannel),
@ -488,7 +486,7 @@ void SubchannelData<SubchannelListType, SubchannelDataType>::ShutdownLocked() {
template <typename SubchannelListType, typename SubchannelDataType>
SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
LoadBalancingPolicy* policy, TraceFlag* tracer,
const grpc_lb_addresses* addresses, grpc_combiner* combiner,
const ServerAddressList& addresses, grpc_combiner* combiner,
grpc_client_channel_factory* client_channel_factory,
const grpc_channel_args& args)
: InternallyRefCounted<SubchannelListType>(tracer),
@ -498,9 +496,9 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
if (tracer_->enabled()) {
gpr_log(GPR_INFO,
"[%s %p] Creating subchannel list %p for %" PRIuPTR " subchannels",
tracer_->name(), policy, this, addresses->num_addresses);
tracer_->name(), policy, this, addresses.size());
}
subchannels_.reserve(addresses->num_addresses);
subchannels_.reserve(addresses.size());
// We need to remove the LB addresses in order to be able to compare the
// subchannel keys of subchannels from a different batch of addresses.
// We also remove the inhibit-health-checking arg, since we are
@ -508,28 +506,35 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
inhibit_health_checking_ = grpc_channel_arg_get_bool(
grpc_channel_args_find(&args, GRPC_ARG_INHIBIT_HEALTH_CHECKING), false);
static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS,
GRPC_ARG_LB_ADDRESSES,
GRPC_ARG_SERVER_ADDRESS_LIST,
GRPC_ARG_INHIBIT_HEALTH_CHECKING};
// Create a subchannel for each address.
grpc_subchannel_args sc_args;
for (size_t i = 0; i < addresses->num_addresses; i++) {
// If there were any balancer, we would have chosen grpclb policy instead.
GPR_ASSERT(!addresses->addresses[i].is_balancer);
memset(&sc_args, 0, sizeof(grpc_subchannel_args));
grpc_arg addr_arg =
grpc_create_subchannel_address_arg(&addresses->addresses[i].address);
for (size_t i = 0; i < addresses.size(); i++) {
// If there were any balancer addresses, we would have chosen grpclb
// 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()->get()));
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) {
for (size_t j = 0; j < addresses[i].args()->num_args; ++j) {
args_to_add.emplace_back(addresses[i].args()->args[j]);
}
}
grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
&args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &addr_arg, 1);
gpr_free(addr_arg.value.string);
sc_args.args = new_args;
&args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove),
args_to_add.data(), args_to_add.size());
gpr_free(args_to_add[subchannel_address_arg_index].value.string);
grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel(
client_channel_factory, &sc_args);
client_channel_factory, new_args);
grpc_channel_args_destroy(new_args);
if (subchannel == nullptr) {
// Subchannel could not be created.
if (tracer_->enabled()) {
char* address_uri =
grpc_sockaddr_to_uri(&addresses->addresses[i].address);
char* address_uri = grpc_sockaddr_to_uri(&addresses[i].address());
gpr_log(GPR_INFO,
"[%s %p] could not create subchannel for address uri %s, "
"ignoring",
@ -539,8 +544,7 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
continue;
}
if (tracer_->enabled()) {
char* address_uri =
grpc_sockaddr_to_uri(&addresses->addresses[i].address);
char* address_uri = grpc_sockaddr_to_uri(&addresses[i].address());
gpr_log(GPR_INFO,
"[%s %p] subchannel list %p index %" PRIuPTR
": Created subchannel %p for address uri %s",
@ -548,8 +552,7 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
address_uri);
gpr_free(address_uri);
}
subchannels_.emplace_back(this, addresses->user_data_vtable,
addresses->addresses[i], subchannel, combiner);
subchannels_.emplace_back(this, addresses[i], subchannel, combiner);
}
}

@ -79,7 +79,7 @@
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
#include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
#include "src/core/ext/filters/client_channel/subchannel_index.h"
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
@ -114,9 +114,13 @@ TraceFlag grpc_lb_xds_trace(false, "xds");
namespace {
constexpr char kXds[] = "xds_experimental";
class XdsLb : public LoadBalancingPolicy {
public:
XdsLb(const grpc_lb_addresses* addresses, const Args& args);
explicit XdsLb(const Args& args);
const char* name() const override { return kXds; }
void UpdateLocked(const grpc_channel_args& args,
grpc_json* lb_config) override;
@ -156,9 +160,6 @@ class XdsLb : public LoadBalancingPolicy {
// Our on_complete closure and the original one.
grpc_closure on_complete;
grpc_closure* original_on_complete;
// The LB token associated with the pick. This is set via user_data in
// the pick.
grpc_mdelem lb_token;
// Stats for client-side load reporting.
RefCountedPtr<XdsLbClientStats> client_stats;
// Next pending pick.
@ -256,7 +257,7 @@ class XdsLb : public LoadBalancingPolicy {
grpc_error* error);
// Pending pick methods.
static void PendingPickSetMetadataAndContext(PendingPick* pp);
static void PendingPickCleanup(PendingPick* pp);
PendingPick* PendingPickCreate(PickState* pick);
void AddPendingPick(PendingPick* pp);
static void OnPendingPickComplete(void* arg, grpc_error* error);
@ -319,7 +320,7 @@ class XdsLb : public LoadBalancingPolicy {
// 0 means not using fallback.
int lb_fallback_timeout_ms_ = 0;
// The backend addresses from the resolver.
grpc_lb_addresses* fallback_backend_addresses_ = nullptr;
UniquePtr<ServerAddressList> fallback_backend_addresses_;
// Fallback timer.
bool fallback_timer_callback_pending_ = false;
grpc_timer lb_fallback_timer_;
@ -339,47 +340,15 @@ class XdsLb : public LoadBalancingPolicy {
// serverlist parsing code
//
// vtable for LB tokens in grpc_lb_addresses
void* lb_token_copy(void* token) {
return token == nullptr
? nullptr
: (void*)GRPC_MDELEM_REF(grpc_mdelem{(uintptr_t)token}).payload;
}
void lb_token_destroy(void* token) {
if (token != nullptr) {
GRPC_MDELEM_UNREF(grpc_mdelem{(uintptr_t)token});
}
}
int lb_token_cmp(void* token1, void* token2) {
if (token1 > token2) return 1;
if (token1 < token2) return -1;
return 0;
}
const grpc_lb_user_data_vtable lb_token_vtable = {
lb_token_copy, lb_token_destroy, lb_token_cmp};
// Returns the backend addresses extracted from the given addresses.
grpc_lb_addresses* ExtractBackendAddresses(const grpc_lb_addresses* addresses) {
// First pass: count the number of backend addresses.
size_t num_backends = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (!addresses->addresses[i].is_balancer) {
++num_backends;
UniquePtr<ServerAddressList> ExtractBackendAddresses(
const ServerAddressList& addresses) {
auto backend_addresses = MakeUnique<ServerAddressList>();
for (size_t i = 0; i < addresses.size(); ++i) {
if (!addresses[i].IsBalancer()) {
backend_addresses->emplace_back(addresses[i]);
}
}
// Second pass: actually populate the addresses and (empty) LB tokens.
grpc_lb_addresses* backend_addresses =
grpc_lb_addresses_create(num_backends, &lb_token_vtable);
size_t num_copied = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (addresses->addresses[i].is_balancer) continue;
const grpc_resolved_address* addr = &addresses->addresses[i].address;
grpc_lb_addresses_set_address(backend_addresses, num_copied, &addr->addr,
addr->len, false /* is_balancer */,
nullptr /* balancer_name */,
(void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload);
++num_copied;
}
return backend_addresses;
}
@ -429,56 +398,17 @@ void ParseServer(const xds_grpclb_server* server, grpc_resolved_address* addr) {
}
// Returns addresses extracted from \a serverlist.
grpc_lb_addresses* ProcessServerlist(const xds_grpclb_serverlist* serverlist) {
size_t num_valid = 0;
/* first pass: count how many are valid in order to allocate the necessary
* memory in a single block */
UniquePtr<ServerAddressList> ProcessServerlist(
const xds_grpclb_serverlist* serverlist) {
auto addresses = MakeUnique<ServerAddressList>();
for (size_t i = 0; i < serverlist->num_servers; ++i) {
if (IsServerValid(serverlist->servers[i], i, true)) ++num_valid;
}
grpc_lb_addresses* lb_addresses =
grpc_lb_addresses_create(num_valid, &lb_token_vtable);
/* second pass: actually populate the addresses and LB tokens (aka user data
* to the outside world) to be read by the child policy during its creation.
* Given that the validity tests are very cheap, they are performed again
* instead of marking the valid ones during the first pass, as this would
* incurr in an allocation due to the arbitrary number of server */
size_t addr_idx = 0;
for (size_t sl_idx = 0; sl_idx < serverlist->num_servers; ++sl_idx) {
const xds_grpclb_server* server = serverlist->servers[sl_idx];
if (!IsServerValid(serverlist->servers[sl_idx], sl_idx, false)) continue;
GPR_ASSERT(addr_idx < num_valid);
/* address processing */
const xds_grpclb_server* server = serverlist->servers[i];
if (!IsServerValid(serverlist->servers[i], i, false)) continue;
grpc_resolved_address addr;
ParseServer(server, &addr);
/* lb token processing */
void* user_data;
if (server->has_load_balance_token) {
const size_t lb_token_max_length =
GPR_ARRAY_SIZE(server->load_balance_token);
const size_t lb_token_length =
strnlen(server->load_balance_token, lb_token_max_length);
grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer(
server->load_balance_token, lb_token_length);
user_data =
(void*)grpc_mdelem_from_slices(GRPC_MDSTR_LB_TOKEN, lb_token_mdstr)
.payload;
} else {
char* uri = grpc_sockaddr_to_uri(&addr);
gpr_log(GPR_INFO,
"Missing LB token for backend address '%s'. The empty token will "
"be used instead",
uri);
gpr_free(uri);
user_data = (void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
}
grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
false /* is_balancer */,
nullptr /* balancer_name */, user_data);
++addr_idx;
addresses->emplace_back(addr, nullptr);
}
GPR_ASSERT(addr_idx == num_valid);
return lb_addresses;
return addresses;
}
//
@ -789,8 +719,7 @@ void XdsLb::BalancerCallState::OnBalancerMessageReceivedLocked(
xds_grpclb_destroy_serverlist(xdslb_policy->serverlist_);
} else {
/* or dispose of the fallback */
grpc_lb_addresses_destroy(xdslb_policy->fallback_backend_addresses_);
xdslb_policy->fallback_backend_addresses_ = nullptr;
xdslb_policy->fallback_backend_addresses_.reset();
if (xdslb_policy->fallback_timer_callback_pending_) {
grpc_timer_cancel(&xdslb_policy->lb_fallback_timer_);
}
@ -876,31 +805,15 @@ void XdsLb::BalancerCallState::OnBalancerStatusReceivedLocked(
// helper code for creating balancer channel
//
grpc_lb_addresses* ExtractBalancerAddresses(
const grpc_lb_addresses* addresses) {
size_t num_grpclb_addrs = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
}
// There must be at least one balancer address, or else the
// client_channel would not have chosen this LB policy.
GPR_ASSERT(num_grpclb_addrs > 0);
grpc_lb_addresses* lb_addresses =
grpc_lb_addresses_create(num_grpclb_addrs, nullptr);
size_t lb_addresses_idx = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (!addresses->addresses[i].is_balancer) continue;
if (GPR_UNLIKELY(addresses->addresses[i].user_data != nullptr)) {
gpr_log(GPR_ERROR,
"This LB policy doesn't support user data. It will be ignored");
UniquePtr<ServerAddressList> ExtractBalancerAddresses(
const ServerAddressList& addresses) {
auto balancer_addresses = MakeUnique<ServerAddressList>();
for (size_t i = 0; i < addresses.size(); ++i) {
if (addresses[i].IsBalancer()) {
balancer_addresses->emplace_back(addresses[i]);
}
grpc_lb_addresses_set_address(
lb_addresses, lb_addresses_idx++, addresses->addresses[i].address.addr,
addresses->addresses[i].address.len, false /* is balancer */,
addresses->addresses[i].balancer_name, nullptr /* user data */);
}
GPR_ASSERT(num_grpclb_addrs == lb_addresses_idx);
return lb_addresses;
return balancer_addresses;
}
/* Returns the channel args for the LB channel, used to create a bidirectional
@ -912,10 +825,11 @@ grpc_lb_addresses* ExtractBalancerAddresses(
* above the grpclb policy.
* - \a args: other args inherited from the xds policy. */
grpc_channel_args* BuildBalancerChannelArgs(
const grpc_lb_addresses* addresses,
const ServerAddressList& addresses,
FakeResolverResponseGenerator* response_generator,
const grpc_channel_args* args) {
grpc_lb_addresses* lb_addresses = ExtractBalancerAddresses(addresses);
UniquePtr<ServerAddressList> balancer_addresses =
ExtractBalancerAddresses(addresses);
// Channel args to remove.
static const char* args_to_remove[] = {
// LB policy name, since we want to use the default (pick_first) in
@ -933,7 +847,7 @@ grpc_channel_args* BuildBalancerChannelArgs(
// is_balancer=true. We need the LB channel to return addresses with
// is_balancer=false so that it does not wind up recursively using the
// xds LB policy, as per the special case logic in client_channel.c.
GRPC_ARG_LB_ADDRESSES,
GRPC_ARG_SERVER_ADDRESS_LIST,
// The fake resolver response generator, because we are replacing it
// with the one from the xds policy, used to propagate updates to
// the LB channel.
@ -949,10 +863,10 @@ grpc_channel_args* BuildBalancerChannelArgs(
};
// Channel args to add.
const grpc_arg args_to_add[] = {
// New LB addresses.
// New server address list.
// Note that we pass these in both when creating the LB channel
// and via the fake resolver. The latter is what actually gets used.
grpc_lb_addresses_create_channel_arg(lb_addresses),
CreateServerAddressListChannelArg(balancer_addresses.get()),
// The fake resolver response generator, which we use to inject
// address updates into the LB channel.
grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
@ -970,10 +884,7 @@ grpc_channel_args* BuildBalancerChannelArgs(
args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), args_to_add,
GPR_ARRAY_SIZE(args_to_add));
// Make any necessary modifications for security.
new_args = grpc_lb_policy_xds_modify_lb_channel_args(new_args);
// Clean up.
grpc_lb_addresses_destroy(lb_addresses);
return new_args;
return grpc_lb_policy_xds_modify_lb_channel_args(new_args);
}
//
@ -981,8 +892,7 @@ grpc_channel_args* BuildBalancerChannelArgs(
//
// TODO(vishalpowar): Use lb_config in args to configure LB policy.
XdsLb::XdsLb(const grpc_lb_addresses* addresses,
const LoadBalancingPolicy::Args& args)
XdsLb::XdsLb(const LoadBalancingPolicy::Args& args)
: LoadBalancingPolicy(args),
response_generator_(MakeRefCounted<FakeResolverResponseGenerator>()),
lb_call_backoff_(
@ -994,7 +904,6 @@ XdsLb::XdsLb(const grpc_lb_addresses* addresses,
.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));
@ -1038,10 +947,6 @@ XdsLb::~XdsLb() {
if (serverlist_ != nullptr) {
xds_grpclb_destroy_serverlist(serverlist_);
}
if (fallback_backend_addresses_ != nullptr) {
grpc_lb_addresses_destroy(fallback_backend_addresses_);
}
grpc_subchannel_index_unref();
}
void XdsLb::ShutdownLocked() {
@ -1088,7 +993,6 @@ void XdsLb::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) {
while ((pp = pending_picks_) != nullptr) {
pending_picks_ = pp->next;
pp->pick->on_complete = pp->original_on_complete;
pp->pick->user_data = nullptr;
grpc_error* error = GRPC_ERROR_NONE;
if (new_policy->PickLocked(pp->pick, &error)) {
// Synchronous return; schedule closure.
@ -1150,7 +1054,7 @@ void XdsLb::CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
pending_picks_ = nullptr;
while (pp != nullptr) {
PendingPick* next = pp->next;
if ((pp->pick->initial_metadata_flags & initial_metadata_flags_mask) ==
if ((*pp->pick->initial_metadata_flags & initial_metadata_flags_mask) ==
initial_metadata_flags_eq) {
// Note: pp is deleted in this callback.
GRPC_CLOSURE_SCHED(&pp->on_complete,
@ -1241,21 +1145,16 @@ void XdsLb::NotifyOnStateChangeLocked(grpc_connectivity_state* current,
}
void XdsLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
if (GPR_UNLIKELY(arg == nullptr || arg->type != GRPC_ARG_POINTER)) {
const ServerAddressList* addresses = FindServerAddressListChannelArg(&args);
if (addresses == nullptr) {
// Ignore this update.
gpr_log(GPR_ERROR,
"[xdslb %p] No valid LB addresses channel arg in update, ignoring.",
this);
return;
}
const grpc_lb_addresses* addresses =
static_cast<const grpc_lb_addresses*>(arg->value.pointer.p);
// Update fallback address list.
if (fallback_backend_addresses_ != nullptr) {
grpc_lb_addresses_destroy(fallback_backend_addresses_);
}
fallback_backend_addresses_ = ExtractBackendAddresses(addresses);
fallback_backend_addresses_ = ExtractBackendAddresses(*addresses);
// Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args,
// since we use this to trigger the client_load_reporting filter.
static const char* args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME};
@ -1266,7 +1165,7 @@ void XdsLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
&args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1);
// Construct args for balancer channel.
grpc_channel_args* lb_channel_args =
BuildBalancerChannelArgs(addresses, response_generator_.get(), &args);
BuildBalancerChannelArgs(*addresses, response_generator_.get(), &args);
// Create balancer channel if needed.
if (lb_channel_ == nullptr) {
char* uri_str;
@ -1457,37 +1356,15 @@ void XdsLb::OnBalancerChannelConnectivityChangedLocked(void* arg,
// PendingPick
//
// Adds lb_token of selected subchannel (address) to the call's initial
// metadata.
grpc_error* AddLbTokenToInitialMetadata(
grpc_mdelem lb_token, grpc_linked_mdelem* lb_token_mdelem_storage,
grpc_metadata_batch* initial_metadata) {
GPR_ASSERT(lb_token_mdelem_storage != nullptr);
GPR_ASSERT(!GRPC_MDISNULL(lb_token));
return grpc_metadata_batch_add_tail(initial_metadata, lb_token_mdelem_storage,
lb_token);
}
// Destroy function used when embedding client stats in call context.
void DestroyClientStats(void* arg) {
static_cast<XdsLbClientStats*>(arg)->Unref();
}
void XdsLb::PendingPickSetMetadataAndContext(PendingPick* pp) {
/* if connected_subchannel is nullptr, no pick has been made by the
* child policy (e.g., all addresses failed to connect). There won't be any
* user_data/token available */
void XdsLb::PendingPickCleanup(PendingPick* pp) {
// If connected_subchannel is nullptr, no pick has been made by the
// child policy (e.g., all addresses failed to connect).
if (pp->pick->connected_subchannel != nullptr) {
if (GPR_LIKELY(!GRPC_MDISNULL(pp->lb_token))) {
AddLbTokenToInitialMetadata(GRPC_MDELEM_REF(pp->lb_token),
&pp->pick->lb_token_mdelem_storage,
pp->pick->initial_metadata);
} else {
gpr_log(GPR_ERROR,
"[xdslb %p] No LB token for connected subchannel pick %p",
pp->xdslb_policy, pp->pick);
abort();
}
// Pass on client stats via context. Passes ownership of the reference.
if (pp->client_stats != nullptr) {
pp->pick->subchannel_call_context[GRPC_GRPCLB_CLIENT_STATS].value =
@ -1505,7 +1382,7 @@ void XdsLb::PendingPickSetMetadataAndContext(PendingPick* pp) {
* order to unref the child policy instance upon its invocation */
void XdsLb::OnPendingPickComplete(void* arg, grpc_error* error) {
PendingPick* pp = static_cast<PendingPick*>(arg);
PendingPickSetMetadataAndContext(pp);
PendingPickCleanup(pp);
GRPC_CLOSURE_SCHED(pp->original_on_complete, GRPC_ERROR_REF(error));
Delete(pp);
}
@ -1537,16 +1414,14 @@ void XdsLb::AddPendingPick(PendingPick* pp) {
// completion callback even if the pick is available immediately.
bool XdsLb::PickFromChildPolicyLocked(bool force_async, PendingPick* pp,
grpc_error** error) {
// Set client_stats and user_data.
// Set client_stats.
if (lb_calld_ != nullptr && lb_calld_->client_stats() != nullptr) {
pp->client_stats = lb_calld_->client_stats()->Ref();
}
GPR_ASSERT(pp->pick->user_data == nullptr);
pp->pick->user_data = (void**)&pp->lb_token;
// Pick via the child policy.
bool pick_done = child_policy_->PickLocked(pp->pick, error);
if (pick_done) {
PendingPickSetMetadataAndContext(pp);
PendingPickCleanup(pp);
if (force_async) {
GRPC_CLOSURE_SCHED(pp->original_on_complete, *error);
*error = GRPC_ERROR_NONE;
@ -1608,20 +1483,19 @@ void XdsLb::CreateChildPolicyLocked(const Args& args) {
}
grpc_channel_args* XdsLb::CreateChildPolicyArgsLocked() {
grpc_lb_addresses* addresses;
bool is_backend_from_grpclb_load_balancer = false;
// This should never be invoked if we do not have serverlist_, as fallback
// mode is disabled for xDS plugin.
GPR_ASSERT(serverlist_ != nullptr);
GPR_ASSERT(serverlist_->num_servers > 0);
addresses = ProcessServerlist(serverlist_);
is_backend_from_grpclb_load_balancer = true;
UniquePtr<ServerAddressList> addresses = ProcessServerlist(serverlist_);
GPR_ASSERT(addresses != nullptr);
// Replace the LB addresses in the channel args that we pass down to
is_backend_from_grpclb_load_balancer = true;
// Replace the server address list in the channel args that we pass down to
// the subchannel.
static const char* keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
static const char* keys_to_remove[] = {GRPC_ARG_SERVER_ADDRESS_LIST};
const grpc_arg args_to_add[] = {
grpc_lb_addresses_create_channel_arg(addresses),
CreateServerAddressListChannelArg(addresses.get()),
// A channel arg indicating if the target is a backend inferred from a
// grpclb load balancer.
grpc_channel_arg_integer_create(
@ -1631,7 +1505,6 @@ grpc_channel_args* XdsLb::CreateChildPolicyArgsLocked() {
grpc_channel_args* args = grpc_channel_args_copy_and_add_and_remove(
args_, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add,
GPR_ARRAY_SIZE(args_to_add));
grpc_lb_addresses_destroy(addresses);
return args;
}
@ -1650,6 +1523,7 @@ 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();
lb_policy_args.args = args;
CreateChildPolicyLocked(lb_policy_args);
if (grpc_lb_xds_trace.enabled()) {
@ -1765,22 +1639,21 @@ class XdsFactory : public LoadBalancingPolicyFactory {
OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
const LoadBalancingPolicy::Args& args) const override {
/* Count the number of gRPC-LB addresses. There must be at least one. */
const grpc_arg* arg =
grpc_channel_args_find(args.args, GRPC_ARG_LB_ADDRESSES);
if (arg == nullptr || arg->type != GRPC_ARG_POINTER) {
return nullptr;
}
grpc_lb_addresses* addresses =
static_cast<grpc_lb_addresses*>(arg->value.pointer.p);
size_t num_grpclb_addrs = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
const ServerAddressList* addresses =
FindServerAddressListChannelArg(args.args);
if (addresses == nullptr) return nullptr;
bool found_balancer_address = false;
for (size_t i = 0; i < addresses->size(); ++i) {
if ((*addresses)[i].IsBalancer()) {
found_balancer_address = true;
break;
}
}
if (num_grpclb_addrs == 0) return nullptr;
return OrphanablePtr<LoadBalancingPolicy>(New<XdsLb>(addresses, args));
if (!found_balancer_address) return nullptr;
return OrphanablePtr<LoadBalancingPolicy>(New<XdsLb>(args));
}
const char* name() const override { return "xds_experimental"; }
const char* name() const override { return kXds; }
};
} // namespace

@ -21,7 +21,7 @@
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include <grpc/impl/codegen/grpc_types.h>
/// Makes any necessary modifications to \a args for use in the xds
/// balancer channel.

@ -25,6 +25,7 @@
#include <string.h>
#include "src/core/ext/filters/client_channel/client_channel.h"
#include "src/core/ext/filters/client_channel/server_address.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
@ -41,22 +42,23 @@ int BalancerNameCmp(const grpc_core::UniquePtr<char>& a,
}
RefCountedPtr<TargetAuthorityTable> CreateTargetAuthorityTable(
grpc_lb_addresses* addresses) {
const ServerAddressList& addresses) {
TargetAuthorityTable::Entry* target_authority_entries =
static_cast<TargetAuthorityTable::Entry*>(gpr_zalloc(
sizeof(*target_authority_entries) * addresses->num_addresses));
for (size_t i = 0; i < addresses->num_addresses; ++i) {
static_cast<TargetAuthorityTable::Entry*>(
gpr_zalloc(sizeof(*target_authority_entries) * addresses.size()));
for (size_t i = 0; i < addresses.size(); ++i) {
char* addr_str;
GPR_ASSERT(grpc_sockaddr_to_string(
&addr_str, &addresses->addresses[i].address, true) > 0);
GPR_ASSERT(
grpc_sockaddr_to_string(&addr_str, &addresses[i].address(), true) > 0);
target_authority_entries[i].key = grpc_slice_from_copied_string(addr_str);
target_authority_entries[i].value.reset(
gpr_strdup(addresses->addresses[i].balancer_name));
gpr_free(addr_str);
char* balancer_name = grpc_channel_arg_get_string(grpc_channel_args_find(
addresses[i].args(), GRPC_ARG_ADDRESS_BALANCER_NAME));
target_authority_entries[i].value.reset(gpr_strdup(balancer_name));
}
RefCountedPtr<TargetAuthorityTable> target_authority_table =
TargetAuthorityTable::Create(addresses->num_addresses,
target_authority_entries, BalancerNameCmp);
TargetAuthorityTable::Create(addresses.size(), target_authority_entries,
BalancerNameCmp);
gpr_free(target_authority_entries);
return target_authority_table;
}
@ -71,13 +73,12 @@ grpc_channel_args* grpc_lb_policy_xds_modify_lb_channel_args(
grpc_arg args_to_add[2];
size_t num_args_to_add = 0;
// Add arg for targets info table.
const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_LB_ADDRESSES);
GPR_ASSERT(arg != nullptr);
GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
grpc_lb_addresses* addresses =
static_cast<grpc_lb_addresses*>(arg->value.pointer.p);
grpc_core::ServerAddressList* addresses =
grpc_core::FindServerAddressListChannelArg(args);
GPR_ASSERT(addresses != nullptr);
grpc_core::RefCountedPtr<grpc_core::TargetAuthorityTable>
target_authority_table = grpc_core::CreateTargetAuthorityTable(addresses);
target_authority_table =
grpc_core::CreateTargetAuthorityTable(*addresses);
args_to_add[num_args_to_add++] =
grpc_core::CreateTargetAuthorityTableChannelArg(
target_authority_table.get());
@ -86,22 +87,18 @@ grpc_channel_args* grpc_lb_policy_xds_modify_lb_channel_args(
// bearer token credentials.
grpc_channel_credentials* channel_credentials =
grpc_channel_credentials_find_in_args(args);
grpc_channel_credentials* creds_sans_call_creds = nullptr;
grpc_core::RefCountedPtr<grpc_channel_credentials> creds_sans_call_creds;
if (channel_credentials != nullptr) {
creds_sans_call_creds =
grpc_channel_credentials_duplicate_without_call_credentials(
channel_credentials);
channel_credentials->duplicate_without_call_credentials();
GPR_ASSERT(creds_sans_call_creds != nullptr);
args_to_remove[num_args_to_remove++] = GRPC_ARG_CHANNEL_CREDENTIALS;
args_to_add[num_args_to_add++] =
grpc_channel_credentials_to_arg(creds_sans_call_creds);
grpc_channel_credentials_to_arg(creds_sans_call_creds.get());
}
grpc_channel_args* result = grpc_channel_args_copy_and_add_and_remove(
args, args_to_remove, num_args_to_remove, args_to_add, num_args_to_add);
// Clean up.
grpc_channel_args_destroy(args);
if (creds_sans_call_creds != nullptr) {
grpc_channel_credentials_unref(creds_sans_call_creds);
}
return result;
}

@ -25,7 +25,7 @@
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h"
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#define XDS_SERVICE_NAME_MAX_LENGTH 128

@ -1,163 +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 <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include "src/core/ext/filters/client_channel/parse_address.h"
grpc_lb_addresses* grpc_lb_addresses_create(
size_t num_addresses, const grpc_lb_user_data_vtable* user_data_vtable) {
grpc_lb_addresses* addresses =
static_cast<grpc_lb_addresses*>(gpr_zalloc(sizeof(grpc_lb_addresses)));
addresses->num_addresses = num_addresses;
addresses->user_data_vtable = user_data_vtable;
const size_t addresses_size = sizeof(grpc_lb_address) * num_addresses;
addresses->addresses =
static_cast<grpc_lb_address*>(gpr_zalloc(addresses_size));
return addresses;
}
grpc_lb_addresses* grpc_lb_addresses_copy(const grpc_lb_addresses* addresses) {
grpc_lb_addresses* new_addresses = grpc_lb_addresses_create(
addresses->num_addresses, addresses->user_data_vtable);
memcpy(new_addresses->addresses, addresses->addresses,
sizeof(grpc_lb_address) * addresses->num_addresses);
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (new_addresses->addresses[i].balancer_name != nullptr) {
new_addresses->addresses[i].balancer_name =
gpr_strdup(new_addresses->addresses[i].balancer_name);
}
if (new_addresses->addresses[i].user_data != nullptr) {
new_addresses->addresses[i].user_data = addresses->user_data_vtable->copy(
new_addresses->addresses[i].user_data);
}
}
return new_addresses;
}
void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
const void* address, size_t address_len,
bool is_balancer, const char* balancer_name,
void* user_data) {
GPR_ASSERT(index < addresses->num_addresses);
if (user_data != nullptr) GPR_ASSERT(addresses->user_data_vtable != nullptr);
grpc_lb_address* target = &addresses->addresses[index];
memcpy(target->address.addr, address, address_len);
target->address.len = static_cast<socklen_t>(address_len);
target->is_balancer = is_balancer;
target->balancer_name = gpr_strdup(balancer_name);
target->user_data = user_data;
}
bool grpc_lb_addresses_set_address_from_uri(grpc_lb_addresses* addresses,
size_t index, const grpc_uri* uri,
bool is_balancer,
const char* balancer_name,
void* user_data) {
grpc_resolved_address address;
if (!grpc_parse_uri(uri, &address)) return false;
grpc_lb_addresses_set_address(addresses, index, address.addr, address.len,
is_balancer, balancer_name, user_data);
return true;
}
int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1,
const grpc_lb_addresses* addresses2) {
if (addresses1->num_addresses > addresses2->num_addresses) return 1;
if (addresses1->num_addresses < addresses2->num_addresses) return -1;
if (addresses1->user_data_vtable > addresses2->user_data_vtable) return 1;
if (addresses1->user_data_vtable < addresses2->user_data_vtable) return -1;
for (size_t i = 0; i < addresses1->num_addresses; ++i) {
const grpc_lb_address* target1 = &addresses1->addresses[i];
const grpc_lb_address* target2 = &addresses2->addresses[i];
if (target1->address.len > target2->address.len) return 1;
if (target1->address.len < target2->address.len) return -1;
int retval = memcmp(target1->address.addr, target2->address.addr,
target1->address.len);
if (retval != 0) return retval;
if (target1->is_balancer > target2->is_balancer) return 1;
if (target1->is_balancer < target2->is_balancer) return -1;
const char* balancer_name1 =
target1->balancer_name != nullptr ? target1->balancer_name : "";
const char* balancer_name2 =
target2->balancer_name != nullptr ? target2->balancer_name : "";
retval = strcmp(balancer_name1, balancer_name2);
if (retval != 0) return retval;
if (addresses1->user_data_vtable != nullptr) {
retval = addresses1->user_data_vtable->cmp(target1->user_data,
target2->user_data);
if (retval != 0) return retval;
}
}
return 0;
}
void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses) {
for (size_t i = 0; i < addresses->num_addresses; ++i) {
gpr_free(addresses->addresses[i].balancer_name);
if (addresses->addresses[i].user_data != nullptr) {
addresses->user_data_vtable->destroy(addresses->addresses[i].user_data);
}
}
gpr_free(addresses->addresses);
gpr_free(addresses);
}
static void* lb_addresses_copy(void* addresses) {
return grpc_lb_addresses_copy(static_cast<grpc_lb_addresses*>(addresses));
}
static void lb_addresses_destroy(void* addresses) {
grpc_lb_addresses_destroy(static_cast<grpc_lb_addresses*>(addresses));
}
static int lb_addresses_cmp(void* addresses1, void* addresses2) {
return grpc_lb_addresses_cmp(static_cast<grpc_lb_addresses*>(addresses1),
static_cast<grpc_lb_addresses*>(addresses2));
}
static const grpc_arg_pointer_vtable lb_addresses_arg_vtable = {
lb_addresses_copy, lb_addresses_destroy, lb_addresses_cmp};
grpc_arg grpc_lb_addresses_create_channel_arg(
const grpc_lb_addresses* addresses) {
return grpc_channel_arg_pointer_create(
(char*)GRPC_ARG_LB_ADDRESSES, (void*)addresses, &lb_addresses_arg_vtable);
}
grpc_lb_addresses* grpc_lb_addresses_find_channel_arg(
const grpc_channel_args* channel_args) {
const grpc_arg* lb_addresses_arg =
grpc_channel_args_find(channel_args, GRPC_ARG_LB_ADDRESSES);
if (lb_addresses_arg == nullptr || lb_addresses_arg->type != GRPC_ARG_POINTER)
return nullptr;
return static_cast<grpc_lb_addresses*>(lb_addresses_arg->value.pointer.p);
}
bool grpc_lb_addresses_contains_balancer_address(
const grpc_lb_addresses& addresses) {
for (size_t i = 0; i < addresses.num_addresses; ++i) {
if (addresses.addresses[i].is_balancer) return true;
}
return false;
}

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

Loading…
Cancel
Save