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

pull/15771/head
ncteisen 7 years ago
commit 8db7788d46
  1. 8
      .gitmodules
  2. 75
      BUILD
  3. 110
      BUILDING.md
  4. 298
      CMakeLists.txt
  5. 63
      CONCEPTS.md
  6. 31
      CONTRIBUTING.md
  7. 384
      Makefile
  8. 120
      README.md
  9. 131
      build.yaml
  10. 12
      config.m4
  11. 13
      config.w32
  12. 2
      doc/command_line_tool.md
  13. 2
      examples/cpp/README.md
  14. 4
      examples/cpp/cpptutorial.md
  15. 4
      examples/cpp/helloworld/README.md
  16. 6
      examples/cpp/route_guide/README.md
  17. 19
      gRPC-C++.podspec
  18. 17
      gRPC-Core.podspec
  19. 2
      grpc.def
  20. 10
      grpc.gemspec
  21. 52
      grpc.gyp
  22. 8
      include/grpc/grpc.h
  23. 4
      include/grpc/impl/codegen/grpc_types.h
  24. 4
      include/grpcpp/impl/codegen/call.h
  25. 10
      package.xml
  26. 2
      src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
  27. 4
      src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
  28. 19
      src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c
  29. 54
      src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h
  30. 19
      src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c
  31. 54
      src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h
  32. 21
      src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
  33. 98
      src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
  34. 10
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc
  35. 11
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
  36. 5
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
  37. 43
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
  38. 4
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
  39. 108
      src/core/ext/filters/load_reporting/registered_opencensus_objects.h
  40. 430
      src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
  41. 99
      src/core/ext/filters/load_reporting/server_load_reporting_filter.h
  42. 71
      src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
  43. 61
      src/core/ext/filters/load_reporting/server_load_reporting_plugin.h
  44. 37
      src/core/ext/transport/chttp2/transport/writing.cc
  45. 49
      src/core/lib/channel/channel_trace.cc
  46. 30
      src/core/lib/channel/channel_trace.h
  47. 188
      src/core/lib/channel/channelz.cc
  48. 85
      src/core/lib/channel/channelz.h
  49. 2
      src/core/lib/gprpp/thd_posix.cc
  50. 97
      src/core/lib/iomgr/ev_epollex_linux.cc
  51. 11
      src/core/lib/iomgr/exec_ctx.h
  52. 2
      src/core/lib/iomgr/executor.cc
  53. 2
      src/core/lib/iomgr/iomgr.cc
  54. 5
      src/core/lib/iomgr/iomgr.h
  55. 9
      src/core/lib/iomgr/socket_utils.h
  56. 4
      src/core/lib/iomgr/socket_utils_common_posix.cc
  57. 4
      src/core/lib/iomgr/socket_utils_uv.cc
  58. 4
      src/core/lib/iomgr/socket_utils_windows.cc
  59. 3
      src/core/lib/iomgr/timer_manager.cc
  60. 8
      src/core/lib/security/context/security_context.cc
  61. 5
      src/core/lib/security/context/security_context.h
  62. 2
      src/core/lib/security/transport/server_auth_filter.cc
  63. 31
      src/core/lib/surface/call.cc
  64. 2
      src/core/lib/surface/call.h
  65. 33
      src/core/lib/surface/channel.cc
  66. 4
      src/core/lib/surface/channel.h
  67. 4
      src/core/plugin_registry/grpc_cronet_plugin_registry.cc
  68. 4
      src/core/plugin_registry/grpc_plugin_registry.cc
  69. 4
      src/core/plugin_registry/grpc_unsecure_plugin_registry.cc
  70. 1
      src/core/tsi/alts/handshaker/altscontext.pb.c
  71. 1
      src/core/tsi/alts/handshaker/altscontext.pb.h
  72. 1
      src/core/tsi/alts/handshaker/handshaker.pb.c
  73. 1
      src/core/tsi/alts/handshaker/handshaker.pb.h
  74. 1
      src/core/tsi/alts/handshaker/transport_security_common.pb.c
  75. 64
      src/cpp/README.md
  76. 12
      src/cpp/common/channel_filter.h
  77. 71
      src/cpp/server/load_reporter/constants.h
  78. 36
      src/cpp/server/load_reporter/get_cpu_stats.h
  79. 45
      src/cpp/server/load_reporter/get_cpu_stats_linux.cc
  80. 45
      src/cpp/server/load_reporter/get_cpu_stats_macos.cc
  81. 40
      src/cpp/server/load_reporter/get_cpu_stats_unsupported.cc
  82. 55
      src/cpp/server/load_reporter/get_cpu_stats_windows.cc
  83. 65
      src/cpp/server/load_reporter/load_data_store.cc
  84. 34
      src/cpp/server/load_reporter/load_data_store.h
  85. 498
      src/cpp/server/load_reporter/load_reporter.cc
  86. 225
      src/cpp/server/load_reporter/load_reporter.h
  87. 4
      src/csharp/README.md
  88. 15
      src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
  89. 15
      src/objective-c/GRPCClient/GRPCCall+ChannelArg.m
  90. 5
      src/objective-c/GRPCClient/private/GRPCHost.h
  91. 15
      src/objective-c/GRPCClient/private/GRPCHost.m
  92. 92
      src/objective-c/NetworkTransitionBehavior.md
  93. 32
      src/objective-c/README-CFSTREAM.md
  94. 43
      src/objective-c/tests/GRPCClientTests.m
  95. 76
      src/php/lib/Grpc/BaseStub.php
  96. 14
      src/php/lib/Grpc/Interceptor.php
  97. 20
      src/php/tests/unit_tests/InterceptorTest.php
  98. 143
      src/proto/grpc/channelz/channelz.proto
  99. 19
      src/proto/grpc/lb/v1/BUILD
  100. 61
      src/proto/grpc/lb/v1/load_balancer.proto
  101. Some files were not shown because too many files have changed in this diff Show More

8
.gitmodules vendored

@ -34,3 +34,11 @@
[submodule "third_party/abseil-cpp"]
path = third_party/abseil-cpp
url = https://github.com/abseil/abseil-cpp
[submodule "third_party/libcxxabi"]
path = third_party/libcxxabi
url = https://github.com/llvm-mirror/libcxxabi.git
branch = release_60
[submodule "third_party/libcxx"]
path = third_party/libcxx
url = https://github.com/llvm-mirror/libcxx.git
branch = release_60

75
BUILD

@ -29,8 +29,8 @@ package(
load(
"//bazel:grpc_build_system.bzl",
"grpc_cc_library",
"grpc_proto_plugin",
"grpc_generate_one_off_targets",
"grpc_proto_plugin",
)
config_setting(
@ -676,6 +676,7 @@ grpc_cc_library(
"src/core/lib/channel/channel_stack.cc",
"src/core/lib/channel/channel_stack_builder.cc",
"src/core/lib/channel/channel_trace.cc",
"src/core/lib/channel/channelz.cc",
"src/core/lib/channel/channelz_registry.cc",
"src/core/lib/channel/connected_channel.cc",
"src/core/lib/channel/handshaker.cc",
@ -823,6 +824,7 @@ grpc_cc_library(
"src/core/lib/channel/channel_stack.h",
"src/core/lib/channel/channel_stack_builder.h",
"src/core/lib/channel/channel_trace.h",
"src/core/lib/channel/channelz.h",
"src/core/lib/channel/channelz_registry.h",
"src/core/lib/channel/connected_channel.h",
"src/core/lib/channel/context.h",
@ -986,7 +988,6 @@ grpc_cc_library(
"grpc_client_authority_filter",
"grpc_lb_policy_pick_first",
"grpc_lb_policy_round_robin",
"grpc_server_load_reporting",
"grpc_max_age_filter",
"grpc_message_size_filter",
"grpc_resolver_dns_ares",
@ -1197,6 +1198,8 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc",
"src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc",
"src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",
"src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c",
"src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c",
],
hdrs = [
"src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h",
@ -1205,6 +1208,8 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h",
"src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h",
"src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h",
"src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h",
"src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h",
],
external_deps = [
"nanopb",
@ -1226,6 +1231,8 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc",
"src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc",
"src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c",
"src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c",
"src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c",
],
hdrs = [
"src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h",
@ -1234,6 +1241,8 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h",
"src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h",
"src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h",
"src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h",
"src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h",
],
external_deps = [
"nanopb",
@ -1286,18 +1295,22 @@ grpc_cc_library(
)
grpc_cc_library(
name = "grpc_server_load_reporting",
name = "lb_server_load_reporting_filter",
srcs = [
"src/core/ext/filters/load_reporting/server_load_reporting_filter.cc",
"src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc",
],
hdrs = [
"src/core/ext/filters/load_reporting/registered_opencensus_objects.h",
"src/core/ext/filters/load_reporting/server_load_reporting_filter.h",
"src/core/ext/filters/load_reporting/server_load_reporting_plugin.h",
"src/cpp/server/load_reporter/constants.h",
],
external_deps = [
"opencensus-stats",
],
language = "c++",
deps = [
"grpc_base",
"grpc++_base",
"grpc_secure",
],
)
@ -1307,6 +1320,7 @@ grpc_cc_library(
"src/cpp/server/load_reporter/load_data_store.cc",
],
hdrs = [
"src/cpp/server/load_reporter/constants.h",
"src/cpp/server/load_reporter/load_data_store.h",
],
language = "c++",
@ -1315,6 +1329,43 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "lb_get_cpu_stats",
srcs = [
"src/cpp/server/load_reporter/get_cpu_stats_linux.cc",
"src/cpp/server/load_reporter/get_cpu_stats_macos.cc",
"src/cpp/server/load_reporter/get_cpu_stats_unsupported.cc",
"src/cpp/server/load_reporter/get_cpu_stats_windows.cc",
],
hdrs = [
"src/cpp/server/load_reporter/get_cpu_stats.h",
],
language = "c++",
deps = [
"grpc++",
],
)
grpc_cc_library(
name = "lb_load_reporter",
srcs = [
"src/cpp/server/load_reporter/load_reporter.cc",
],
hdrs = [
"src/cpp/server/load_reporter/constants.h",
"src/cpp/server/load_reporter/load_reporter.h",
],
external_deps = [
"opencensus-stats",
],
language = "c++",
deps = [
"lb_get_cpu_stats",
"lb_load_data_store",
"//src/proto/grpc/lb/v1:load_reporter_proto",
],
)
grpc_cc_library(
name = "grpc_resolver_dns_native",
srcs = [
@ -1738,11 +1789,11 @@ grpc_cc_library(
"src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h",
"src/core/tsi/alts/handshaker/transport_security_common_api.h",
],
public_hdrs = GRPC_SECURE_PUBLIC_HDRS,
external_deps = [
"nanopb",
],
language = "c++",
public_hdrs = GRPC_SECURE_PUBLIC_HDRS,
deps = [
"alts_proto",
"gpr",
@ -1992,33 +2043,33 @@ grpc_cc_library(
grpc_cc_library(
name = "grpc_opencensus_plugin",
srcs = [
"src/cpp/ext/filters/census/client_filter.cc",
"src/cpp/ext/filters/census/server_filter.cc",
"src/cpp/ext/filters/census/channel_filter.cc",
"src/cpp/ext/filters/census/client_filter.cc",
"src/cpp/ext/filters/census/context.cc",
"src/cpp/ext/filters/census/grpc_context.cc",
"src/cpp/ext/filters/census/grpc_plugin.cc",
"src/cpp/ext/filters/census/measures.cc",
"src/cpp/ext/filters/census/rpc_encoding.cc",
"src/cpp/ext/filters/census/server_filter.cc",
"src/cpp/ext/filters/census/views.cc",
],
hdrs = [
"include/grpcpp/opencensus.h",
"src/cpp/ext/filters/census/client_filter.h",
"src/cpp/ext/filters/census/server_filter.h",
"src/cpp/ext/filters/census/channel_filter.h",
"src/cpp/ext/filters/census/client_filter.h",
"src/cpp/ext/filters/census/context.h",
"src/cpp/ext/filters/census/grpc_plugin.h",
"src/cpp/ext/filters/census/measures.h",
"src/cpp/ext/filters/census/rpc_encoding.h",
"src/cpp/ext/filters/census/server_filter.h",
],
language = "c++",
external_deps = [
"absl-base",
"absl-time",
"opencensus-trace",
"opencensus-stats",
],
language = "c++",
deps = [
":census",
":grpc++",

@ -1,18 +1,5 @@
# If you are in a hurry
For language-specific installation instructions for gRPC runtime, please
refer to these documents
* [C++](examples/cpp): Currently to install gRPC for C++, you need to build from source as described below.
* [C#](src/csharp): NuGet package `Grpc`
* [Go](https://github.com/grpc/grpc-go): `go get google.golang.org/grpc`
* [Java](https://github.com/grpc/grpc-java)
* [Node](src/node): `npm install grpc`
* [Objective-C](src/objective-c)
* [PHP](src/php): `pecl install grpc`
* [Python](src/python/grpcio): `pip install grpcio`
* [Ruby](src/ruby): `gem install grpc`
gRPC C++ - Building from source
===========================
# Pre-requisites
@ -28,7 +15,7 @@ If you plan to build from source and run tests, install the following as well:
$ [sudo] apt-get install clang libc++-dev
```
## macOS
## MacOS
On a Mac, you will first need to
install Xcode or
@ -60,6 +47,17 @@ installed by `brew` is being used:
$ LIBTOOL=glibtool LIBTOOLIZE=glibtoolize make
```
## Windows
To prepare for cmake + Microsoft Visual C++ compiler build
- Install Visual Studio 2015 or 2017 (Visual C++ compiler will be used).
- Install [Git](https://git-scm.com/).
- Install [CMake](https://cmake.org/download/).
- Install [Active State Perl](https://www.activestate.com/activeperl/) (`choco install activeperl`) - *required by boringssl*
- Install [Go](https://golang.org/dl/) (`choco install golang`) - *required by boringssl*
- Install [yasm](http://yasm.tortall.net/) and add it to `PATH` (`choco install yasm`) - *required by boringssl*
- (Optional) Install [Ninja](https://ninja-build.org/) (`choco install ninja`)
## Protoc
By default gRPC uses [protocol buffers](https://github.com/google/protobuf),
@ -77,48 +75,49 @@ $ cd grpc/third_party/protobuf
$ sudo make install # 'make' should have been run by core grpc
```
# Build from Source
# Clone the repository (including submodules)
For developers who are interested to contribute, the following commands show how to compile the
gRPC C Core library.
Before building, you need to clone the gRPC github repository and download submodules containing source code
for gRPC's dependencies (that's done by the `submodule` command or `--recursive` flag). The following commands will clone the gRPC
repository at the latest stable version.
## Unix
```sh
$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
$ cd grpc
$ git submodule update --init
$ make
$ [sudo] make install
```
```
## Windows
There are several ways to build under Windows, of varying complexity depending
on experience with the tools involved.
```
> @rem You can also do just "git clone --recursive -b THE_BRANCH_YOU_WANT https://github.com/grpc/grpc"
> powershell git clone --recursive -b ((New-Object System.Net.WebClient).DownloadString(\"https://grpc.io/release\").Trim()) https://github.com/grpc/grpc
> cd grpc
> @rem To update submodules at later time, run "git submodule update --init"
```
# Build from source
In the C++ world, there's no "standard" build system that would work for in all supported use cases and on all supported platforms.
Therefore, gRPC supports several major build systems, which should satisfy most users.
### Building using CMake (RECOMMENDED)
## make (on UNIX systems)
Builds gRPC C and C++ with boringssl.
- Install Visual Studio 2015 or 2017 (Visual C++ compiler will be used).
- Install [Git](https://git-scm.com/).
- Install [CMake](https://cmake.org/download/).
- Install [Active State Perl](https://www.activestate.com/activeperl/) (`choco install activeperl`) - *required by boringssl*
- Install [Go](https://golang.org/dl/) (`choco install golang`) - *required by boringssl*
- Install [yasm](http://yasm.tortall.net/) and add it to `PATH` (`choco install yasm`) - *required by boringssl*
- (Optional) Install [Ninja](https://ninja-build.org/) (`choco install ninja`)
From the grpc repository root
```sh
$ make
```
#### Clone grpc sources including submodules
Before building, you need to clone the gRPC github repository and download submodules containing source code
for gRPC's dependencies (that's done by the `submodule` command).
## bazel
From the grpc repository root
```
> @rem You can also do just "git clone --recursive -b THE_BRANCH_YOU_WANT https://github.com/grpc/grpc"
> powershell git clone --recursive -b ((New-Object System.Net.WebClient).DownloadString(\"https://grpc.io/release\").Trim()) https://github.com/grpc/grpc
> cd grpc
> @rem To update submodules at later time, run "git submodule update --init"
bazel build :all
```
#### cmake: Using Visual Studio 2015 or 2017 (can only build with OPENSSL_NO_ASM).
## cmake: Windows, Using Visual Studio 2015 or 2017 (can only build with OPENSSL_NO_ASM).
When using the "Visual Studio" generator,
cmake will generate a solution (`grpc.sln`) that contains a VS project for
every target defined in `CMakeLists.txt` (+ few extra convenience projects
@ -132,7 +131,7 @@ you will be able to browse and build the code.
> cmake --build .
```
#### cmake: Using Ninja (faster build, supports boringssl's assembly optimizations).
## cmake: Windows, Using Ninja (faster build, supports boringssl's assembly optimizations).
Please note that when using Ninja, you will still need Visual C++ (part of Visual Studio)
installed to be able to compile the C/C++ sources.
```
@ -143,30 +142,3 @@ installed to be able to compile the C/C++ sources.
> cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release
> cmake --build .
```
### msys2 (with mingw)
The Makefile (and source code) should support msys2's mingw32 and mingw64
compilers. Building with msys2's native compiler is possible, but
difficult.
This approach requires having [msys2](https://msys2.github.io/) installed.
```
# Install prerequisites
MSYS2$ pacman -S autoconf automake gcc libtool mingw-w64-x86_64-toolchain perl pkg-config zlib
MSYS2$ pacman -S mingw-w64-x86_64-gflags
```
```
# From mingw shell
MINGW64$ export CPPFLAGS="-D_WIN32_WINNT=0x0600"
MINGW64$ make
```
NOTE: Though most of the make targets are buildable under Mingw, some haven't been ported to Windows yet
and may fail to build (mostly trying to include POSIX headers not available on Mingw).
### Pre-generated Visual Studio solution (DELETED)
*WARNING: This used to be the recommended way to build on Windows, but because of significant limitations (hard to build dependencies including boringssl, .proto codegen is hard to support, ..) we are no longer providing them. Use cmake to build on Windows instead.*

@ -246,6 +246,9 @@ endif()
add_dependencies(buildtests_c endpoint_pair_test)
add_dependencies(buildtests_c error_test)
if(_gRPC_PLATFORM_LINUX)
add_dependencies(buildtests_c ev_epollex_linux_test)
endif()
if(_gRPC_PLATFORM_LINUX)
add_dependencies(buildtests_c ev_epollsig_linux_test)
endif()
add_dependencies(buildtests_c fake_resolver_test)
@ -430,7 +433,6 @@ endif()
add_dependencies(buildtests_c h2_full+trace_test)
add_dependencies(buildtests_c h2_full+workarounds_test)
add_dependencies(buildtests_c h2_http_proxy_test)
add_dependencies(buildtests_c h2_load_reporting_test)
add_dependencies(buildtests_c h2_oauth2_test)
add_dependencies(buildtests_c h2_proxy_test)
add_dependencies(buildtests_c h2_sockpair_test)
@ -454,7 +456,6 @@ endif()
add_dependencies(buildtests_c h2_full+trace_nosec_test)
add_dependencies(buildtests_c h2_full+workarounds_nosec_test)
add_dependencies(buildtests_c h2_http_proxy_nosec_test)
add_dependencies(buildtests_c h2_load_reporting_nosec_test)
add_dependencies(buildtests_c h2_proxy_nosec_test)
add_dependencies(buildtests_c h2_sockpair_nosec_test)
add_dependencies(buildtests_c h2_sockpair+trace_nosec_test)
@ -504,6 +505,9 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_call_create)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_channel)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_chttp2_hpack)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@ -544,6 +548,7 @@ add_dependencies(buildtests_cxx channel_arguments_test)
add_dependencies(buildtests_cxx channel_filter_test)
add_dependencies(buildtests_cxx channel_trace_test)
add_dependencies(buildtests_cxx channelz_registry_test)
add_dependencies(buildtests_cxx channelz_test)
add_dependencies(buildtests_cxx check_gcp_environment_linux_test)
add_dependencies(buildtests_cxx check_gcp_environment_windows_test)
add_dependencies(buildtests_cxx chttp2_settings_timeout_test)
@ -596,7 +601,6 @@ endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx json_run_localhost)
endif()
add_dependencies(buildtests_cxx lb_load_data_store_test)
add_dependencies(buildtests_cxx memory_test)
add_dependencies(buildtests_cxx metrics_client)
add_dependencies(buildtests_cxx mock_test)
@ -938,6 +942,7 @@ add_library(grpc
src/core/lib/channel/channel_stack.cc
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_trace.cc
src/core/lib/channel/channelz.cc
src/core/lib/channel/channelz_registry.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
@ -1214,6 +1219,8 @@ add_library(grpc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
@ -1225,8 +1232,6 @@ add_library(grpc
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc
src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
src/cpp/ext/filters/census/grpc_context.cc
src/core/ext/filters/max_age/max_age_filter.cc
src/core/ext/filters/message_size/message_size_filter.cc
@ -1334,6 +1339,7 @@ add_library(grpc_cronet
src/core/lib/channel/channel_stack.cc
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_trace.cc
src/core/lib/channel/channelz.cc
src/core/lib/channel/channelz_registry.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
@ -1602,8 +1608,6 @@ add_library(grpc_cronet
src/core/tsi/ssl/session_cache/ssl_session_openssl.cc
src/core/tsi/ssl_transport_security.cc
src/core/tsi/transport_security_grpc.cc
src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
src/core/plugin_registry/grpc_cronet_plugin_registry.cc
)
@ -1721,6 +1725,7 @@ add_library(grpc_test_util
src/core/lib/channel/channel_stack.cc
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_trace.cc
src/core/lib/channel/channelz.cc
src/core/lib/channel/channelz_registry.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
@ -2027,6 +2032,7 @@ add_library(grpc_test_util_unsecure
src/core/lib/channel/channel_stack.cc
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_trace.cc
src/core/lib/channel/channelz.cc
src/core/lib/channel/channelz_registry.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
@ -2312,6 +2318,7 @@ add_library(grpc_unsecure
src/core/lib/channel/channel_stack.cc
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_trace.cc
src/core/lib/channel/channelz.cc
src/core/lib/channel/channelz_registry.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
@ -2521,13 +2528,13 @@ add_library(grpc_unsecure
src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
third_party/nanopb/pb_common.c
third_party/nanopb/pb_decode.c
@ -3147,6 +3154,7 @@ add_library(grpc++_cronet
src/core/lib/channel/channel_stack.cc
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_trace.cc
src/core/lib/channel/channelz.cc
src/core/lib/channel/channelz_registry.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
@ -5035,50 +5043,6 @@ target_link_libraries(interop_server_main
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_library(lb_load_data_store
src/cpp/server/load_reporter/load_data_store.cc
)
if(WIN32 AND MSVC)
set_target_properties(lb_load_data_store PROPERTIES COMPILE_PDB_NAME "lb_load_data_store"
COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
)
if (gRPC_INSTALL)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lb_load_data_store.pdb
DESTINATION ${gRPC_INSTALL_LIBDIR} OPTIONAL
)
endif()
endif()
target_include_directories(lb_load_data_store
PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(lb_load_data_store
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc++
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
@ -5336,6 +5300,7 @@ add_library(end2end_tests
test/core/end2end/tests/cancel_before_invoke.cc
test/core/end2end/tests/cancel_in_a_vacuum.cc
test/core/end2end/tests/cancel_with_status.cc
test/core/end2end/tests/channelz.cc
test/core/end2end/tests/compressed_payload.cc
test/core/end2end/tests/connectivity.cc
test/core/end2end/tests/default_host.cc
@ -5352,7 +5317,6 @@ add_library(end2end_tests
test/core/end2end/tests/invoke_large_request.cc
test/core/end2end/tests/keepalive_timeout.cc
test/core/end2end/tests/large_metadata.cc
test/core/end2end/tests/load_reporting_hook.cc
test/core/end2end/tests/max_concurrent_streams.cc
test/core/end2end/tests/max_connection_age.cc
test/core/end2end/tests/max_connection_idle.cc
@ -5456,6 +5420,7 @@ add_library(end2end_nosec_tests
test/core/end2end/tests/cancel_before_invoke.cc
test/core/end2end/tests/cancel_in_a_vacuum.cc
test/core/end2end/tests/cancel_with_status.cc
test/core/end2end/tests/channelz.cc
test/core/end2end/tests/compressed_payload.cc
test/core/end2end/tests/connectivity.cc
test/core/end2end/tests/default_host.cc
@ -5472,7 +5437,6 @@ add_library(end2end_nosec_tests
test/core/end2end/tests/invoke_large_request.cc
test/core/end2end/tests/keepalive_timeout.cc
test/core/end2end/tests/large_metadata.cc
test/core/end2end/tests/load_reporting_hook.cc
test/core/end2end/tests/max_concurrent_streams.cc
test/core/end2end/tests/max_connection_age.cc
test/core/end2end/tests/max_connection_idle.cc
@ -6247,6 +6211,37 @@ endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX)
add_executable(ev_epollex_linux_test
test/core/iomgr/ev_epollex_linux_test.cc
)
target_include_directories(ev_epollex_linux_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
)
target_link_libraries(ev_epollex_linux_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX)
add_executable(ev_epollsig_linux_test
test/core/iomgr/ev_epollsig_linux_test.cc
)
@ -10080,6 +10075,51 @@ endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(bm_channel
test/cpp/microbenchmarks/bm_channel.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(bm_channel
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(bm_channel
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_benchmark
${_gRPC_BENCHMARK_LIBRARIES}
grpc++_test_util_unsecure
grpc_test_util_unsecure
grpc++_unsecure
grpc_unsecure
gpr_test_util
gpr
grpc++_test_config
${_gRPC_GFLAGS_LIBRARIES}
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(bm_chttp2_hpack
test/cpp/microbenchmarks/bm_chttp2_hpack.cc
third_party/googletest/googletest/src/gtest-all.cc
@ -10818,6 +10858,53 @@ target_link_libraries(channelz_registry_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(channelz_test
test/core/channel/channelz_test.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/channelz/channelz.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/channelz/channelz.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/channelz/channelz.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/channelz/channelz.grpc.pb.h
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
protobuf_generate_grpc_cpp(
src/proto/grpc/channelz/channelz.proto
)
target_include_directories(channelz_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(channelz_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc++_test_util
grpc++
grpc
gpr_test_util
gpr
${_gRPC_GFLAGS_LIBRARIES}
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(check_gcp_environment_linux_test
test/core/security/check_gcp_environment_linux_test.cc
third_party/googletest/googletest/src/gtest-all.cc
@ -12736,47 +12823,6 @@ endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(lb_load_data_store_test
test/cpp/server/load_reporter/load_data_store_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(lb_load_data_store_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(lb_load_data_store_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
lb_load_data_store
grpc++_test_util
grpc_test_util
grpc++
grpc
gpr_test_util
gpr
${_gRPC_GFLAGS_LIBRARIES}
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(memory_test
test/core/gprpp/memory_test.cc
third_party/googletest/googletest/src/gtest-all.cc
@ -15272,36 +15318,6 @@ target_link_libraries(h2_http_proxy_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(h2_load_reporting_test
test/core/end2end/fixtures/h2_load_reporting.cc
)
target_include_directories(h2_load_reporting_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
)
target_link_libraries(h2_load_reporting_test
${_gRPC_ALLTARGETS_LIBRARIES}
end2end_tests
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(h2_oauth2_test
test/core/end2end/fixtures/h2_oauth2.cc
)
@ -15818,36 +15834,6 @@ target_link_libraries(h2_http_proxy_nosec_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(h2_load_reporting_nosec_test
test/core/end2end/fixtures/h2_load_reporting.cc
)
target_include_directories(h2_load_reporting_nosec_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR}
)
target_link_libraries(h2_load_reporting_nosec_test
${_gRPC_ALLTARGETS_LIBRARIES}
end2end_nosec_tests
grpc_test_util_unsecure
grpc_unsecure
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(h2_proxy_nosec_test
test/core/end2end/fixtures/h2_proxy.cc
)

@ -0,0 +1,63 @@
# gRPC Concepts Overview
Remote Procedure Calls (RPCs) provide a useful abstraction for building
distributed applications and services. The libraries in this repository
provide a concrete implementation of the gRPC protocol, layered over HTTP/2.
These libraries enable communication between clients and servers using any
combination of the supported languages.
## Interface
Developers using gRPC start with a language agnostic description of an RPC service (a collection
of methods). From this description, gRPC will generate client and server side interfaces
in any of the supported languages. The server implements
the service interface, which can be remotely invoked by the client interface.
By default, gRPC uses [Protocol Buffers](https://github.com/google/protobuf) as the
Interface Definition Language (IDL) for describing both the service interface
and the structure of the payload messages. It is possible to use other
alternatives if desired.
### Invoking & handling remote calls
Starting from an interface definition in a .proto file, gRPC provides
Protocol Compiler plugins that generate Client- and Server-side APIs.
gRPC users call into these APIs on the Client side and implement
the corresponding API on the server side.
#### Synchronous vs. asynchronous
Synchronous RPC calls, that block until a response arrives from the server, are
the closest approximation to the abstraction of a procedure call that RPC
aspires to.
On the other hand, networks are inherently asynchronous and in many scenarios,
it is desirable to have the ability to start RPCs without blocking the current
thread.
The gRPC programming surface in most languages comes in both synchronous and
asynchronous flavors.
## Streaming
gRPC supports streaming semantics, where either the client or the server (or both)
send a stream of messages on a single RPC call. The most general case is
Bidirectional Streaming where a single gRPC call establishes a stream in which both
the client and the server can send a stream of messages to each other. The streamed
messages are delivered in the order they were sent.
# Protocol
The [gRPC protocol](doc/PROTOCOL-HTTP2.md) specifies the abstract requirements for communication between
clients and servers. A concrete embedding over HTTP/2 completes the picture by
fleshing out the details of each of the required operations.
## Abstract gRPC protocol
A gRPC call comprises of a bidirectional stream of messages, initiated by the client. In the client-to-server direction, this stream begins with a mandatory `Call Header`, followed by optional `Initial-Metadata`, followed by zero or more `Payload Messages`. The server-to-client direction contains an optional `Initial-Metadata`, followed by zero or more `Payload Messages` terminated with a mandatory `Status` and optional `Status-Metadata` (a.k.a.,`Trailing-Metadata`).
## Implementation over HTTP/2
The abstract protocol defined above is implemented over [HTTP/2](https://http2.github.io/). gRPC bidirectional streams are mapped to HTTP/2 streams. The contents of `Call Header` and `Initial Metadata` are sent as HTTP/2 headers and subject to HPACK compression. `Payload Messages` are serialized into a byte stream of length prefixed gRPC frames which are then fragmented into HTTP/2 frames at the sender and reassembled at the receiver. `Status` and `Trailing-Metadata` are sent as HTTP/2 trailing headers (a.k.a., trailers).
## Flow Control
gRPC uses the flow control mechanism in HTTP/2. This enables fine-grained control of memory used for buffering in-flight messages.

@ -11,13 +11,34 @@ In order to protect both you and ourselves, you will need to sign the
[Contributor License
Agreement](https://identity.linuxfoundation.org/projects/cncf).
## Running tests
## Cloning the repository
Use `tools/run_tests/run_tests.py` script to run the unit tests. See
[tools/run_tests](tools/run_tests) for how to run tests for a given language.
Before starting any development work you will need a local copy of the gRPC repository.
Please follow the instructions in [Building gRPC C++: Clone the repository](BUILDING.md#clone-the-repository-including-submodules).
Prerequisites for building and running tests are listed in
[INSTALL.md](INSTALL.md) and in `src/YOUR-LANGUAGE` (e.g. `src/csharp`)
## Building & Running tests
Different languages use different build systems. To hide the complexity
of needing to build with many different build systems, a portable python
script that unifies the experience of building and testing gRPC in different
languages and on different platforms is provided.
To build gRPC in the language of choice (e.g. `c++`, `csharp`, `php`, `python`, `ruby`, ...)
- Prepare you development environment based on language-specific instructions in `src/YOUR-LANGUAGE` directory.
- The language-specific instructions might involve installing C/C++ prerequisites listed in
[Building gRPC C++: Prerequisites](BUILDING.md#pre-requisites) as gRPC implementations
in this repository are using the native gRPC "core" library internally.
- Run
```
python tools/run_tests/run_tests.py -l YOUR_LANGUAGE --build_only
```
- To also run all the unit tests after building
```
python tools/run_tests/run_tests.py -l YOUR_LANGUAGE
```
You can also run `python tools/run_tests/run_tests.py --help` to discover useful command line flags supported. For more details,
see [tools/run_tests](tools/run_tests) where you will also find guidance on how to run various other test suites (e.g. interop tests, benchmarks)
## Generated project files

@ -300,6 +300,12 @@ else
TMPOUT = `mktemp /tmp/test-out-XXXXXX`
endif
CHECK_NO_CXX14_COMPAT_WORKS_CMD = $(CC) -std=c++11 -Werror -Wno-c++14-compat -o $(TMPOUT) -c test/build/no-c++14-compat.cc
HAS_WORKING_NO_CXX14_COMPAT = $(shell $(CHECK_NO_CXX14_COMPAT_WORKS_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_WORKING_NO_CXX14_COMPAT),true)
W_NO_CXX14_COMPAT=-Wno-c++14-compat
endif
CHECK_SHADOW_WORKS_CMD = $(CC) -std=c99 -Werror -Wshadow -o $(TMPOUT) -c test/build/shadow.c
HAS_WORKING_SHADOW = $(shell $(CHECK_SHADOW_WORKS_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_WORKING_SHADOW),true)
@ -318,6 +324,18 @@ ifeq ($(HAS_WORKING_NO_SHIFT_NEGATIVE_VALUE),true)
W_NO_SHIFT_NEGATIVE_VALUE=-Wno-shift-negative-value
NO_W_NO_SHIFT_NEGATIVE_VALUE=-Wshift-negative-value
endif
CHECK_NO_UNUSED_BUT_SET_VARIABLE_WORKS_CMD = $(CC) -std=c99 -Werror -Wno-unused-but-set-variable -o $(TMPOUT) -c test/build/no-unused-but-set-variable.c
HAS_WORKING_NO_UNUSED_BUT_SET_VARIABLE = $(shell $(CHECK_NO_UNUSED_BUT_SET_VARIABLE_WORKS_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_WORKING_NO_UNUSED_BUT_SET_VARIABLE),true)
W_NO_UNUSED_BUT_SET_VARIABLE=-Wno-unused-but-set-variable
NO_W_NO_UNUSED_BUT_SET_VARIABLE=-Wunused-but-set-variable
endif
CHECK_NO_MAYBE_UNINITIALIZED_WORKS_CMD = $(CC) -std=c99 -Werror -Wno-maybe-uninitialized -o $(TMPOUT) -c test/build/no-maybe-uninitialized.c
HAS_WORKING_NO_MAYBE_UNINITIALIZED = $(shell $(CHECK_NO_MAYBE_UNINITIALIZED_WORKS_CMD) 2> /dev/null && echo true || echo false)
ifeq ($(HAS_WORKING_NO_MAYBE_UNINITIALIZED),true)
W_NO_MAYBE_UNINITIALIZED=-Wno-maybe-uninitialized
NO_W_NO_MAYBE_UNINITIALIZED=-Wmaybe-uninitialized
endif
# The HOST compiler settings are used to compile the protoc plugins.
# In most cases, you won't have to change anything, but if you are
@ -968,6 +986,7 @@ dns_resolver_test: $(BINDIR)/$(CONFIG)/dns_resolver_test
dualstack_socket_test: $(BINDIR)/$(CONFIG)/dualstack_socket_test
endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test
error_test: $(BINDIR)/$(CONFIG)/error_test
ev_epollex_linux_test: $(BINDIR)/$(CONFIG)/ev_epollex_linux_test
ev_epollsig_linux_test: $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test
fake_resolver_test: $(BINDIR)/$(CONFIG)/fake_resolver_test
fake_transport_security_test: $(BINDIR)/$(CONFIG)/fake_transport_security_test
@ -1105,6 +1124,7 @@ backoff_test: $(BINDIR)/$(CONFIG)/backoff_test
bdp_estimator_test: $(BINDIR)/$(CONFIG)/bdp_estimator_test
bm_arena: $(BINDIR)/$(CONFIG)/bm_arena
bm_call_create: $(BINDIR)/$(CONFIG)/bm_call_create
bm_channel: $(BINDIR)/$(CONFIG)/bm_channel
bm_chttp2_hpack: $(BINDIR)/$(CONFIG)/bm_chttp2_hpack
bm_chttp2_transport: $(BINDIR)/$(CONFIG)/bm_chttp2_transport
bm_closure: $(BINDIR)/$(CONFIG)/bm_closure
@ -1122,6 +1142,7 @@ channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test
channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test
channel_trace_test: $(BINDIR)/$(CONFIG)/channel_trace_test
channelz_registry_test: $(BINDIR)/$(CONFIG)/channelz_registry_test
channelz_test: $(BINDIR)/$(CONFIG)/channelz_test
check_gcp_environment_linux_test: $(BINDIR)/$(CONFIG)/check_gcp_environment_linux_test
check_gcp_environment_windows_test: $(BINDIR)/$(CONFIG)/check_gcp_environment_windows_test
chttp2_settings_timeout_test: $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test
@ -1167,7 +1188,6 @@ interop_client: $(BINDIR)/$(CONFIG)/interop_client
interop_server: $(BINDIR)/$(CONFIG)/interop_server
interop_test: $(BINDIR)/$(CONFIG)/interop_test
json_run_localhost: $(BINDIR)/$(CONFIG)/json_run_localhost
lb_load_data_store_test: $(BINDIR)/$(CONFIG)/lb_load_data_store_test
memory_test: $(BINDIR)/$(CONFIG)/memory_test
metrics_client: $(BINDIR)/$(CONFIG)/metrics_client
mock_test: $(BINDIR)/$(CONFIG)/mock_test
@ -1285,7 +1305,6 @@ h2_full+pipe_test: $(BINDIR)/$(CONFIG)/h2_full+pipe_test
h2_full+trace_test: $(BINDIR)/$(CONFIG)/h2_full+trace_test
h2_full+workarounds_test: $(BINDIR)/$(CONFIG)/h2_full+workarounds_test
h2_http_proxy_test: $(BINDIR)/$(CONFIG)/h2_http_proxy_test
h2_load_reporting_test: $(BINDIR)/$(CONFIG)/h2_load_reporting_test
h2_oauth2_test: $(BINDIR)/$(CONFIG)/h2_oauth2_test
h2_proxy_test: $(BINDIR)/$(CONFIG)/h2_proxy_test
h2_sockpair_test: $(BINDIR)/$(CONFIG)/h2_sockpair_test
@ -1303,7 +1322,6 @@ h2_full+pipe_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+pipe_nosec_test
h2_full+trace_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+trace_nosec_test
h2_full+workarounds_nosec_test: $(BINDIR)/$(CONFIG)/h2_full+workarounds_nosec_test
h2_http_proxy_nosec_test: $(BINDIR)/$(CONFIG)/h2_http_proxy_nosec_test
h2_load_reporting_nosec_test: $(BINDIR)/$(CONFIG)/h2_load_reporting_nosec_test
h2_proxy_nosec_test: $(BINDIR)/$(CONFIG)/h2_proxy_nosec_test
h2_sockpair_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_nosec_test
h2_sockpair+trace_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test
@ -1373,7 +1391,7 @@ plugins: $(PROTOC_PLUGINS)
privatelibs: privatelibs_c privatelibs_cxx
privatelibs_c: $(LIBDIR)/$(CONFIG)/libalts_test_util.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libz.a $(LIBDIR)/$(CONFIG)/libares.a $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a
privatelibs_c: $(LIBDIR)/$(CONFIG)/libalts_test_util.a $(LIBDIR)/$(CONFIG)/libcxxabi.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libreconnect_server.a $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libz.a $(LIBDIR)/$(CONFIG)/libares.a $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libbad_ssl_test_server.a $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a
pc_c: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc.pc
pc_c_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc_unsecure.pc
@ -1383,9 +1401,9 @@ pc_cxx: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc
pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc
ifeq ($(EMBED_OPENSSL),true)
privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_crypto_test_data_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_buf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_compiler_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_constant_time_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_scrypt_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_p256-x86_64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ctrdrbg_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_lhash_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs7_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pool_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_refcount_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_self_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_file_test_gtest_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gtest_main_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_thread_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_tab_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_v3name_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_span_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_crypto_test_data_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_buf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_compiler_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_constant_time_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_scrypt_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_p256-x86_64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ctrdrbg_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_lhash_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs7_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pool_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_refcount_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_self_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_file_test_gtest_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gtest_main_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_thread_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_tab_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_v3name_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_span_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
else
privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
endif
@ -1415,6 +1433,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/dualstack_socket_test \
$(BINDIR)/$(CONFIG)/endpoint_pair_test \
$(BINDIR)/$(CONFIG)/error_test \
$(BINDIR)/$(CONFIG)/ev_epollex_linux_test \
$(BINDIR)/$(CONFIG)/ev_epollsig_linux_test \
$(BINDIR)/$(CONFIG)/fake_resolver_test \
$(BINDIR)/$(CONFIG)/fake_transport_security_test \
@ -1540,7 +1559,6 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/h2_full+trace_test \
$(BINDIR)/$(CONFIG)/h2_full+workarounds_test \
$(BINDIR)/$(CONFIG)/h2_http_proxy_test \
$(BINDIR)/$(CONFIG)/h2_load_reporting_test \
$(BINDIR)/$(CONFIG)/h2_oauth2_test \
$(BINDIR)/$(CONFIG)/h2_proxy_test \
$(BINDIR)/$(CONFIG)/h2_sockpair_test \
@ -1558,7 +1576,6 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/h2_full+trace_nosec_test \
$(BINDIR)/$(CONFIG)/h2_full+workarounds_nosec_test \
$(BINDIR)/$(CONFIG)/h2_http_proxy_nosec_test \
$(BINDIR)/$(CONFIG)/h2_load_reporting_nosec_test \
$(BINDIR)/$(CONFIG)/h2_proxy_nosec_test \
$(BINDIR)/$(CONFIG)/h2_sockpair_nosec_test \
$(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test \
@ -1603,6 +1620,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/bdp_estimator_test \
$(BINDIR)/$(CONFIG)/bm_arena \
$(BINDIR)/$(CONFIG)/bm_call_create \
$(BINDIR)/$(CONFIG)/bm_channel \
$(BINDIR)/$(CONFIG)/bm_chttp2_hpack \
$(BINDIR)/$(CONFIG)/bm_chttp2_transport \
$(BINDIR)/$(CONFIG)/bm_closure \
@ -1620,6 +1638,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/channel_filter_test \
$(BINDIR)/$(CONFIG)/channel_trace_test \
$(BINDIR)/$(CONFIG)/channelz_registry_test \
$(BINDIR)/$(CONFIG)/channelz_test \
$(BINDIR)/$(CONFIG)/check_gcp_environment_linux_test \
$(BINDIR)/$(CONFIG)/check_gcp_environment_windows_test \
$(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test \
@ -1658,7 +1677,6 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/interop_server \
$(BINDIR)/$(CONFIG)/interop_test \
$(BINDIR)/$(CONFIG)/json_run_localhost \
$(BINDIR)/$(CONFIG)/lb_load_data_store_test \
$(BINDIR)/$(CONFIG)/memory_test \
$(BINDIR)/$(CONFIG)/metrics_client \
$(BINDIR)/$(CONFIG)/mock_test \
@ -1780,6 +1798,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/bdp_estimator_test \
$(BINDIR)/$(CONFIG)/bm_arena \
$(BINDIR)/$(CONFIG)/bm_call_create \
$(BINDIR)/$(CONFIG)/bm_channel \
$(BINDIR)/$(CONFIG)/bm_chttp2_hpack \
$(BINDIR)/$(CONFIG)/bm_chttp2_transport \
$(BINDIR)/$(CONFIG)/bm_closure \
@ -1797,6 +1816,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/channel_filter_test \
$(BINDIR)/$(CONFIG)/channel_trace_test \
$(BINDIR)/$(CONFIG)/channelz_registry_test \
$(BINDIR)/$(CONFIG)/channelz_test \
$(BINDIR)/$(CONFIG)/check_gcp_environment_linux_test \
$(BINDIR)/$(CONFIG)/check_gcp_environment_windows_test \
$(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test \
@ -1835,7 +1855,6 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/interop_server \
$(BINDIR)/$(CONFIG)/interop_test \
$(BINDIR)/$(CONFIG)/json_run_localhost \
$(BINDIR)/$(CONFIG)/lb_load_data_store_test \
$(BINDIR)/$(CONFIG)/memory_test \
$(BINDIR)/$(CONFIG)/metrics_client \
$(BINDIR)/$(CONFIG)/mock_test \
@ -1938,6 +1957,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/endpoint_pair_test || ( echo test endpoint_pair_test failed ; exit 1 )
$(E) "[RUN] Testing error_test"
$(Q) $(BINDIR)/$(CONFIG)/error_test || ( echo test error_test failed ; exit 1 )
$(E) "[RUN] Testing ev_epollex_linux_test"
$(Q) $(BINDIR)/$(CONFIG)/ev_epollex_linux_test || ( echo test ev_epollex_linux_test failed ; exit 1 )
$(E) "[RUN] Testing ev_epollsig_linux_test"
$(Q) $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test || ( echo test ev_epollsig_linux_test failed ; exit 1 )
$(E) "[RUN] Testing fake_resolver_test"
@ -2202,6 +2223,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/bm_arena || ( echo test bm_arena failed ; exit 1 )
$(E) "[RUN] Testing bm_call_create"
$(Q) $(BINDIR)/$(CONFIG)/bm_call_create || ( echo test bm_call_create failed ; exit 1 )
$(E) "[RUN] Testing bm_channel"
$(Q) $(BINDIR)/$(CONFIG)/bm_channel || ( echo test bm_channel failed ; exit 1 )
$(E) "[RUN] Testing bm_chttp2_hpack"
$(Q) $(BINDIR)/$(CONFIG)/bm_chttp2_hpack || ( echo test bm_chttp2_hpack failed ; exit 1 )
$(E) "[RUN] Testing bm_chttp2_transport"
@ -2236,6 +2259,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/channel_trace_test || ( echo test channel_trace_test failed ; exit 1 )
$(E) "[RUN] Testing channelz_registry_test"
$(Q) $(BINDIR)/$(CONFIG)/channelz_registry_test || ( echo test channelz_registry_test failed ; exit 1 )
$(E) "[RUN] Testing channelz_test"
$(Q) $(BINDIR)/$(CONFIG)/channelz_test || ( echo test channelz_test failed ; exit 1 )
$(E) "[RUN] Testing check_gcp_environment_linux_test"
$(Q) $(BINDIR)/$(CONFIG)/check_gcp_environment_linux_test || ( echo test check_gcp_environment_linux_test failed ; exit 1 )
$(E) "[RUN] Testing check_gcp_environment_windows_test"
@ -2298,8 +2323,6 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/inproc_sync_unary_ping_pong_test || ( echo test inproc_sync_unary_ping_pong_test failed ; exit 1 )
$(E) "[RUN] Testing interop_test"
$(Q) $(BINDIR)/$(CONFIG)/interop_test || ( echo test interop_test failed ; exit 1 )
$(E) "[RUN] Testing lb_load_data_store_test"
$(Q) $(BINDIR)/$(CONFIG)/lb_load_data_store_test || ( echo test lb_load_data_store_test failed ; exit 1 )
$(E) "[RUN] Testing memory_test"
$(Q) $(BINDIR)/$(CONFIG)/memory_test || ( echo test memory_test failed ; exit 1 )
$(E) "[RUN] Testing mock_test"
@ -2859,6 +2882,11 @@ $(OBJDIR)/$(CONFIG)/%.o : %.cc
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
$(OBJDIR)/$(CONFIG)/%.o : %.cpp
$(E) "[CXX] Compiling $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
install: install_c install_cxx install-plugins install-certs
install_c: install-headers_c install-static_c install-shared_c
@ -3173,6 +3201,50 @@ endif
endif
LIBCXXABI_SRC = \
third_party/libcxxabi/src/abort_message.cpp \
third_party/libcxxabi/src/cxa_aux_runtime.cpp \
third_party/libcxxabi/src/cxa_default_handlers.cpp \
third_party/libcxxabi/src/cxa_demangle.cpp \
third_party/libcxxabi/src/cxa_exception_storage.cpp \
third_party/libcxxabi/src/cxa_guard.cpp \
third_party/libcxxabi/src/cxa_handlers.cpp \
third_party/libcxxabi/src/cxa_noexception.cpp \
third_party/libcxxabi/src/cxa_thread_atexit.cpp \
third_party/libcxxabi/src/cxa_unexpected.cpp \
third_party/libcxxabi/src/cxa_vector.cpp \
third_party/libcxxabi/src/cxa_virtual.cpp \
third_party/libcxxabi/src/fallback_malloc.cpp \
third_party/libcxxabi/src/private_typeinfo.cpp \
third_party/libcxxabi/src/stdlib_exception.cpp \
third_party/libcxxabi/src/stdlib_new_delete.cpp \
third_party/libcxxabi/src/stdlib_stdexcept.cpp \
third_party/libcxxabi/src/stdlib_typeinfo.cpp \
PUBLIC_HEADERS_C += \
LIBCXXABI_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBCXXABI_SRC))))
$(LIBCXXABI_OBJS): CPPFLAGS += -D_LIBCPP_DISABLE_EXTERN_TEMPLATE -D_LIBCXXABI_BUILDING_LIBRARY -D_LIBCXXABI_NO_EXCEPTIONS -Ithird_party/libcxxabi/include -nostdinc++ -Ithird_party/libcxx/include $(W_NO_UNUSED_BUT_SET_VARIABLE) $(W_NO_MAYBE_UNINITIALIZED) -fvisibility=hidden
$(LIBCXXABI_OBJS): CXXFLAGS += $(W_NO_CXX14_COMPAT)
$(LIBDIR)/$(CONFIG)/libcxxabi.a: $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(LIBCXXABI_OBJS)
$(E) "[AR] Creating $@"
$(Q) mkdir -p `dirname $@`
$(Q) rm -f $(LIBDIR)/$(CONFIG)/libcxxabi.a
$(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libcxxabi.a $(LIBCXXABI_OBJS)
ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libcxxabi.a
endif
ifneq ($(NO_DEPS),true)
-include $(LIBCXXABI_OBJS:.o=.dep)
endif
LIBGPR_SRC = \
src/core/lib/gpr/alloc.cc \
src/core/lib/gpr/arena.cc \
@ -3317,6 +3389,7 @@ LIBGRPC_SRC = \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_trace.cc \
src/core/lib/channel/channelz.cc \
src/core/lib/channel/channelz_registry.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
@ -3593,6 +3666,8 @@ LIBGRPC_SRC = \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c \
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c \
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
@ -3604,8 +3679,6 @@ LIBGRPC_SRC = \
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \
src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \
src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \
src/core/ext/filters/load_reporting/server_load_reporting_filter.cc \
src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc \
src/cpp/ext/filters/census/grpc_context.cc \
src/core/ext/filters/max_age/max_age_filter.cc \
src/core/ext/filters/message_size/message_size_filter.cc \
@ -3712,6 +3785,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_trace.cc \
src/core/lib/channel/channelz.cc \
src/core/lib/channel/channelz_registry.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
@ -3980,8 +4054,6 @@ LIBGRPC_CRONET_SRC = \
src/core/tsi/ssl/session_cache/ssl_session_openssl.cc \
src/core/tsi/ssl_transport_security.cc \
src/core/tsi/transport_security_grpc.cc \
src/core/ext/filters/load_reporting/server_load_reporting_filter.cc \
src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc \
src/core/plugin_registry/grpc_cronet_plugin_registry.cc \
PUBLIC_HEADERS_C += \
@ -4097,6 +4169,7 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_trace.cc \
src/core/lib/channel/channelz.cc \
src/core/lib/channel/channelz_registry.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
@ -4394,6 +4467,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_trace.cc \
src/core/lib/channel/channelz.cc \
src/core/lib/channel/channelz_registry.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
@ -4657,6 +4731,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_trace.cc \
src/core/lib/channel/channelz.cc \
src/core/lib/channel/channelz_registry.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
@ -4866,13 +4941,13 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \
src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \
src/core/ext/filters/load_reporting/server_load_reporting_filter.cc \
src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c \
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c \
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
third_party/nanopb/pb_common.c \
third_party/nanopb/pb_decode.c \
@ -5480,6 +5555,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_trace.cc \
src/core/lib/channel/channelz.cc \
src/core/lib/channel/channelz_registry.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
@ -7241,55 +7317,6 @@ endif
endif
LIBLB_LOAD_DATA_STORE_SRC = \
src/cpp/server/load_reporter/load_data_store.cc \
PUBLIC_HEADERS_CXX += \
LIBLB_LOAD_DATA_STORE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBLB_LOAD_DATA_STORE_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure libraries if you don't have OpenSSL.
$(LIBDIR)/$(CONFIG)/liblb_load_data_store.a: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay.
$(LIBDIR)/$(CONFIG)/liblb_load_data_store.a: protobuf_dep_error
else
$(LIBDIR)/$(CONFIG)/liblb_load_data_store.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(PROTOBUF_DEP) $(LIBLB_LOAD_DATA_STORE_OBJS)
$(E) "[AR] Creating $@"
$(Q) mkdir -p `dirname $@`
$(Q) rm -f $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a
$(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a $(LIBLB_LOAD_DATA_STORE_OBJS)
ifeq ($(SYSTEM),Darwin)
$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a
endif
endif
endif
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(LIBLB_LOAD_DATA_STORE_OBJS:.o=.dep)
endif
endif
LIBQPS_SRC = \
$(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \
$(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc \
@ -9995,6 +10022,7 @@ LIBEND2END_TESTS_SRC = \
test/core/end2end/tests/cancel_before_invoke.cc \
test/core/end2end/tests/cancel_in_a_vacuum.cc \
test/core/end2end/tests/cancel_with_status.cc \
test/core/end2end/tests/channelz.cc \
test/core/end2end/tests/compressed_payload.cc \
test/core/end2end/tests/connectivity.cc \
test/core/end2end/tests/default_host.cc \
@ -10011,7 +10039,6 @@ LIBEND2END_TESTS_SRC = \
test/core/end2end/tests/invoke_large_request.cc \
test/core/end2end/tests/keepalive_timeout.cc \
test/core/end2end/tests/large_metadata.cc \
test/core/end2end/tests/load_reporting_hook.cc \
test/core/end2end/tests/max_concurrent_streams.cc \
test/core/end2end/tests/max_connection_age.cc \
test/core/end2end/tests/max_connection_idle.cc \
@ -10112,6 +10139,7 @@ LIBEND2END_NOSEC_TESTS_SRC = \
test/core/end2end/tests/cancel_before_invoke.cc \
test/core/end2end/tests/cancel_in_a_vacuum.cc \
test/core/end2end/tests/cancel_with_status.cc \
test/core/end2end/tests/channelz.cc \
test/core/end2end/tests/compressed_payload.cc \
test/core/end2end/tests/connectivity.cc \
test/core/end2end/tests/default_host.cc \
@ -10128,7 +10156,6 @@ LIBEND2END_NOSEC_TESTS_SRC = \
test/core/end2end/tests/invoke_large_request.cc \
test/core/end2end/tests/keepalive_timeout.cc \
test/core/end2end/tests/large_metadata.cc \
test/core/end2end/tests/load_reporting_hook.cc \
test/core/end2end/tests/max_concurrent_streams.cc \
test/core/end2end/tests/max_connection_age.cc \
test/core/end2end/tests/max_connection_idle.cc \
@ -11068,6 +11095,38 @@ endif
endif
EV_EPOLLEX_LINUX_TEST_SRC = \
test/core/iomgr/ev_epollex_linux_test.cc \
EV_EPOLLEX_LINUX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(EV_EPOLLEX_LINUX_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/ev_epollex_linux_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/ev_epollex_linux_test: $(EV_EPOLLEX_LINUX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(EV_EPOLLEX_LINUX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/ev_epollex_linux_test
endif
$(OBJDIR)/$(CONFIG)/test/core/iomgr/ev_epollex_linux_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_ev_epollex_linux_test: $(EV_EPOLLEX_LINUX_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(EV_EPOLLEX_LINUX_TEST_OBJS:.o=.dep)
endif
endif
EV_EPOLLSIG_LINUX_TEST_SRC = \
test/core/iomgr/ev_epollsig_linux_test.cc \
@ -15698,6 +15757,50 @@ endif
endif
BM_CHANNEL_SRC = \
test/cpp/microbenchmarks/bm_channel.cc \
BM_CHANNEL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CHANNEL_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/bm_channel: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
$(BINDIR)/$(CONFIG)/bm_channel: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/bm_channel: $(PROTOBUF_DEP) $(BM_CHANNEL_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(BM_CHANNEL_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_channel
endif
endif
$(BM_CHANNEL_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_channel.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
deps_bm_channel: $(BM_CHANNEL_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(BM_CHANNEL_OBJS:.o=.dep)
endif
endif
BM_CHTTP2_HPACK_SRC = \
test/cpp/microbenchmarks/bm_chttp2_hpack.cc \
@ -16445,6 +16548,53 @@ endif
endif
CHANNELZ_TEST_SRC = \
test/core/channel/channelz_test.cc \
$(GENDIR)/src/proto/grpc/channelz/channelz.pb.cc $(GENDIR)/src/proto/grpc/channelz/channelz.grpc.pb.cc \
CHANNELZ_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHANNELZ_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/channelz_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
$(BINDIR)/$(CONFIG)/channelz_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/channelz_test: $(PROTOBUF_DEP) $(CHANNELZ_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(CHANNELZ_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/channelz_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/core/channel/channelz_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(OBJDIR)/$(CONFIG)/src/proto/grpc/channelz/channelz.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_channelz_test: $(CHANNELZ_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(CHANNELZ_TEST_OBJS:.o=.dep)
endif
endif
$(OBJDIR)/$(CONFIG)/test/core/channel/channelz_test.o: $(GENDIR)/src/proto/grpc/channelz/channelz.pb.cc $(GENDIR)/src/proto/grpc/channelz/channelz.grpc.pb.cc
CHECK_GCP_ENVIRONMENT_LINUX_TEST_SRC = \
test/core/security/check_gcp_environment_linux_test.cc \
@ -18335,49 +18485,6 @@ endif
endif
LB_LOAD_DATA_STORE_TEST_SRC = \
test/cpp/server/load_reporter/load_data_store_test.cc \
LB_LOAD_DATA_STORE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LB_LOAD_DATA_STORE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/lb_load_data_store_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
$(BINDIR)/$(CONFIG)/lb_load_data_store_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/lb_load_data_store_test: $(PROTOBUF_DEP) $(LB_LOAD_DATA_STORE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(LB_LOAD_DATA_STORE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/lb_load_data_store_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/server/load_reporter/load_data_store_test.o: $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_lb_load_data_store_test: $(LB_LOAD_DATA_STORE_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(LB_LOAD_DATA_STORE_TEST_OBJS:.o=.dep)
endif
endif
MEMORY_TEST_SRC = \
test/core/gprpp/memory_test.cc \
@ -22913,38 +23020,6 @@ endif
endif
H2_LOAD_REPORTING_TEST_SRC = \
test/core/end2end/fixtures/h2_load_reporting.cc \
H2_LOAD_REPORTING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_LOAD_REPORTING_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/h2_load_reporting_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/h2_load_reporting_test: $(H2_LOAD_REPORTING_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_LOAD_REPORTING_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/h2_load_reporting_test
endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_load_reporting.o: $(LIBDIR)/$(CONFIG)/libend2end_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_load_reporting_test: $(H2_LOAD_REPORTING_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(H2_LOAD_REPORTING_TEST_OBJS:.o=.dep)
endif
endif
H2_OAUTH2_TEST_SRC = \
test/core/end2end/fixtures/h2_oauth2.cc \
@ -23393,26 +23468,6 @@ ifneq ($(NO_DEPS),true)
endif
H2_LOAD_REPORTING_NOSEC_TEST_SRC = \
test/core/end2end/fixtures/h2_load_reporting.cc \
H2_LOAD_REPORTING_NOSEC_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(H2_LOAD_REPORTING_NOSEC_TEST_SRC))))
$(BINDIR)/$(CONFIG)/h2_load_reporting_nosec_test: $(H2_LOAD_REPORTING_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(H2_LOAD_REPORTING_NOSEC_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/h2_load_reporting_nosec_test
$(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/h2_load_reporting.o: $(LIBDIR)/$(CONFIG)/libend2end_nosec_tests.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_h2_load_reporting_nosec_test: $(H2_LOAD_REPORTING_NOSEC_TEST_OBJS:.o=.dep)
ifneq ($(NO_DEPS),true)
-include $(H2_LOAD_REPORTING_NOSEC_TEST_OBJS:.o=.dep)
endif
H2_PROXY_NOSEC_TEST_SRC = \
test/core/end2end/fixtures/h2_proxy.cc \
@ -24413,7 +24468,6 @@ src/cpp/common/secure_channel_arguments.cc: $(OPENSSL_DEP)
src/cpp/common/secure_create_auth_context.cc: $(OPENSSL_DEP)
src/cpp/ext/proto_server_reflection.cc: $(OPENSSL_DEP)
src/cpp/ext/proto_server_reflection_plugin.cc: $(OPENSSL_DEP)
src/cpp/server/load_reporter/load_data_store.cc: $(OPENSSL_DEP)
src/cpp/server/secure_server_credentials.cc: $(OPENSSL_DEP)
src/cpp/util/core_stats.cc: $(OPENSSL_DEP)
src/cpp/util/error_details.cc: $(OPENSSL_DEP)

@ -1,24 +1,59 @@
[gRPC - An RPC library and framework](http://github.com/grpc/grpc)
gRPC - An RPC library and framework
===================================
gRPC is a modern, open source, high-performance remote procedure call (RPC) framework that can run anywhere. It enables client and server applications to communicate transparently, and makes it easier to build connected systems.
<table>
<tr>
<td><b>Homepage:</b></td>
<td><a href="https://grpc.io/">grpc.io</a></td>
</tr>
<tr>
<td><b>Mailing List:</b></td>
<td><a href="https://groups.google.com/forum/#!forum/grpc-io">grpc-io@googlegroups.com</a></td>
</tr>
</table>
[![Join the chat at https://gitter.im/grpc/grpc](https://badges.gitter.im/grpc/grpc.svg)](https://gitter.im/grpc/grpc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Copyright 2015
[The gRPC Authors](https://github.com/grpc/grpc/blob/master/AUTHORS)
# To start using gRPC
To maximize usability, gRPC supports the standard way of adding dependencies in your language of choice (if there is one).
In most languages, the gRPC runtime comes in form of a package available in your language's package manager.
For instructions on how to use the language-specific gRPC runtime in your project, please refer to these documents
# Documentation
* [C++](src/cpp): follow the instructions under the `src/cpp` directory
* [C#](src/csharp): NuGet package `Grpc`
* [Dart](https://github.com/grpc/grpc-dart): pub package `grpc`
* [Go](https://github.com/grpc/grpc-go): `go get google.golang.org/grpc`
* [Java](https://github.com/grpc/grpc-java): Use JARs from Maven Central Repository
* [Node](https://github.com/grpc/grpc-node): `npm install grpc`
* [Objective-C](src/objective-c): Add `gRPC-ProtoRPC` dependency to podspec
* [PHP](src/php): `pecl install grpc`
* [Python](src/python/grpcio): `pip install grpcio`
* [Ruby](src/ruby): `gem install grpc`
* [WebJS](https://github.com/grpc/grpc-web): follow the grpc-web instructions
You can find more detailed documentation and examples in the [doc](doc) and [examples](examples) directories respectively.
You can find per-language quickstart guides and tutorials in [Documentation section on grpc.io website](https://grpc.io/docs/). The code examples are available in the [examples](examples) directory.
# Installation & Testing
# To start developing gRPC
See [INSTALL](INSTALL.md) for installation instructions for various platforms.
Contributions are welcome!
See [tools/run_tests](tools/run_tests) for more guidance on how to run various test suites (e.g. unit tests, interop tests, benchmarks)
Please read [How to contribute](CONTRIBUTING.md) which will guide you through the entire workflow of how to build the source code, how to run the tests and how to contribute your changes to
the gRPC codebase.
The document also contains info on how the contributing process works and contains best practices for creating contributions.
# Performance
See [Performance dashboard](http://performance-dot-grpc-testing.appspot.com/explore?dashboard=5636470266134528) for the performance numbers for the latest released version.
# Repository Structure & Status
# Concepts
See [gRPC Concepts](CONCEPTS.md)
# About This Repository
This repository contains source code for gRPC libraries for multiple languages written on top of shared C core library [src/core](src/core).
@ -42,70 +77,3 @@ Libraries in different languages may be in different states of development. We a
| WebJS | [grpc-web](https://github.com/grpc/grpc-web) |
| Dart | [grpc-dart](https://github.com/grpc/grpc-dart) |
See [MANIFEST.md](MANIFEST.md) for a listing of top-level items in the
repository.
# Overview
Remote Procedure Calls (RPCs) provide a useful abstraction for building
distributed applications and services. The libraries in this repository
provide a concrete implementation of the gRPC protocol, layered over HTTP/2.
These libraries enable communication between clients and servers using any
combination of the supported languages.
## Interface
Developers using gRPC typically start with the description of an RPC service
(a collection of methods), and generate client and server side interfaces
which they use on the client-side and implement on the server side.
By default, gRPC uses [Protocol Buffers](https://github.com/google/protobuf) as the
Interface Definition Language (IDL) for describing both the service interface
and the structure of the payload messages. It is possible to use other
alternatives if desired.
### Surface API
Starting from an interface definition in a .proto file, gRPC provides
Protocol Compiler plugins that generate Client- and Server-side APIs.
gRPC users typically call into these APIs on the Client side and implement
the corresponding API on the server side.
#### Synchronous vs. asynchronous
Synchronous RPC calls, that block until a response arrives from the server, are
the closest approximation to the abstraction of a procedure call that RPC
aspires to.
On the other hand, networks are inherently asynchronous and in many scenarios,
it is desirable to have the ability to start RPCs without blocking the current
thread.
The gRPC programming surface in most languages comes in both synchronous and
asynchronous flavors.
## Streaming
gRPC supports streaming semantics, where either the client or the server (or both)
send a stream of messages on a single RPC call. The most general case is
Bidirectional Streaming where a single gRPC call establishes a stream where both
the client and the server can send a stream of messages to each other. The streamed
messages are delivered in the order they were sent.
# Protocol
The [gRPC protocol](doc/PROTOCOL-HTTP2.md) specifies the abstract requirements for communication between
clients and servers. A concrete embedding over HTTP/2 completes the picture by
fleshing out the details of each of the required operations.
## Abstract gRPC protocol
A gRPC RPC comprises of a bidirectional stream of messages, initiated by the client. In the client-to-server direction, this stream begins with a mandatory `Call Header`, followed by optional `Initial-Metadata`, followed by zero or more `Payload Messages`. The server-to-client direction contains an optional `Initial-Metadata`, followed by zero or more `Payload Messages` terminated with a mandatory `Status` and optional `Status-Metadata` (a.k.a.,`Trailing-Metadata`).
## Implementation over HTTP/2
The abstract protocol defined above is implemented over [HTTP/2](https://http2.github.io/). gRPC bidirectional streams are mapped to HTTP/2 streams. The contents of `Call Header` and `Initial Metadata` are sent as HTTP/2 headers and subject to HPACK compression. `Payload Messages` are serialized into a byte stream of length prefixed gRPC frames which are then fragmented into HTTP/2 frames at the sender and reassembled at the receiver. `Status` and `Trailing-Metadata` are sent as HTTP/2 trailing headers (a.k.a., trailers).
## Flow Control
gRPC inherits the flow control mechanisms in HTTP/2 and uses them to enable fine-grained control of the amount of memory used for buffering in-flight messages.

@ -235,6 +235,7 @@ filegroups:
- src/core/lib/channel/channel_stack.cc
- src/core/lib/channel/channel_stack_builder.cc
- src/core/lib/channel/channel_trace.cc
- src/core/lib/channel/channelz.cc
- src/core/lib/channel/channelz_registry.cc
- src/core/lib/channel/connected_channel.cc
- src/core/lib/channel/handshaker.cc
@ -405,6 +406,7 @@ filegroups:
- src/core/lib/channel/channel_stack.h
- src/core/lib/channel/channel_stack_builder.h
- src/core/lib/channel/channel_trace.h
- src/core/lib/channel/channelz.h
- src/core/lib/channel/channelz_registry.h
- src/core/lib/channel/connected_channel.h
- src/core/lib/channel/context.h
@ -645,6 +647,8 @@ filegroups:
- src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h
- src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
- src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
- src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h
- src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h
- src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
src:
- src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
@ -652,6 +656,8 @@ filegroups:
- src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc
- src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc
- src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
- src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c
- src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c
- src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
plugin: grpc_lb_policy_grpclb
uses:
@ -666,6 +672,8 @@ filegroups:
- src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h
- src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
- src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
- src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h
- src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h
- src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h
src:
- src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc
@ -673,6 +681,8 @@ filegroups:
- src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc
- src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc
- src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc
- src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c
- src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c
- src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
plugin: grpc_lb_policy_grpclb
uses:
@ -822,16 +832,6 @@ filegroups:
- src/core/ext/filters/workarounds/workaround_utils.cc
uses:
- grpc_base
- name: grpc_server_load_reporting
headers:
- src/core/ext/filters/load_reporting/server_load_reporting_filter.h
- src/core/ext/filters/load_reporting/server_load_reporting_plugin.h
src:
- src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
- src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
plugin: grpc_server_load_reporting_plugin
uses:
- grpc_base
- name: grpc_test_util_base
build: test
headers:
@ -1374,6 +1374,32 @@ libs:
deps:
- grpc
secure: true
- name: cxxabi
build: private
language: c
src:
- third_party/libcxxabi/src/abort_message.cpp
- third_party/libcxxabi/src/cxa_aux_runtime.cpp
- third_party/libcxxabi/src/cxa_default_handlers.cpp
- third_party/libcxxabi/src/cxa_demangle.cpp
- third_party/libcxxabi/src/cxa_exception_storage.cpp
- third_party/libcxxabi/src/cxa_guard.cpp
- third_party/libcxxabi/src/cxa_handlers.cpp
- third_party/libcxxabi/src/cxa_noexception.cpp
- third_party/libcxxabi/src/cxa_thread_atexit.cpp
- third_party/libcxxabi/src/cxa_unexpected.cpp
- third_party/libcxxabi/src/cxa_vector.cpp
- third_party/libcxxabi/src/cxa_virtual.cpp
- third_party/libcxxabi/src/fallback_malloc.cpp
- third_party/libcxxabi/src/private_typeinfo.cpp
- third_party/libcxxabi/src/stdlib_exception.cpp
- third_party/libcxxabi/src/stdlib_new_delete.cpp
- third_party/libcxxabi/src/stdlib_stdexcept.cpp
- third_party/libcxxabi/src/stdlib_typeinfo.cpp
build_system:
- Makefile
defaults: cxxabi
secure: false
- name: gpr
build: all
language: c
@ -1414,7 +1440,6 @@ libs:
- grpc_resolver_dns_native
- grpc_resolver_sockaddr
- grpc_resolver_fake
- grpc_server_load_reporting
- grpc_secure
- census
- grpc_max_age_filter
@ -1441,7 +1466,6 @@ libs:
- grpc_base
- grpc_transport_cronet_client_secure
- grpc_transport_chttp2_client_secure
- grpc_server_load_reporting
generate_plugin_registry: true
platforms:
- linux
@ -1515,7 +1539,6 @@ libs:
- grpc_resolver_dns_native
- grpc_resolver_sockaddr
- grpc_resolver_fake
- grpc_server_load_reporting
- grpc_lb_policy_grpclb
- grpc_lb_policy_pick_first
- grpc_lb_policy_round_robin
@ -1906,15 +1929,6 @@ libs:
- test/cpp/interop/interop_server_bootstrap.cc
deps:
- interop_server_lib
- name: lb_load_data_store
build: private
language: c++
headers:
- src/cpp/server/load_reporter/load_data_store.h
src:
- src/cpp/server/load_reporter/load_data_store.cc
deps:
- grpc++
- name: qps
build: private
language: c++
@ -2279,6 +2293,21 @@ targets:
- gpr_test_util
- gpr
uses_polling: false
- name: ev_epollex_linux_test
cpu_cost: 3
build: test
language: c
src:
- test/core/iomgr/ev_epollex_linux_test.cc
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
exclude_iomgrs:
- uv
platforms:
- linux
- name: ev_epollsig_linux_test
cpu_cost: 3
build: test
@ -3908,6 +3937,28 @@ targets:
- linux
- posix
uses_polling: false
- name: bm_channel
build: test
language: c++
src:
- test/cpp/microbenchmarks/bm_channel.cc
deps:
- grpc_benchmark
- benchmark
- grpc++_test_util_unsecure
- grpc_test_util_unsecure
- grpc++_unsecure
- grpc_unsecure
- gpr_test_util
- gpr
- grpc++_test_config
benchmark: true
defaults: benchmark
platforms:
- mac
- linux
- posix
uses_polling: false
- name: bm_chttp2_hpack
build: test
language: c++
@ -4254,6 +4305,23 @@ targets:
uses:
- grpc++_test
uses_polling: false
- name: channelz_test
gtest: true
build: test
language: c++
src:
- test/core/channel/channelz_test.cc
deps:
- grpc_test_util
- grpc++_test_util
- grpc++
- grpc
- gpr_test_util
- gpr
filegroups:
- grpc++_channelz_proto
uses:
- grpc++_test
- name: check_gcp_environment_linux_test
build: test
language: c++
@ -4860,20 +4928,6 @@ targets:
- mac
- linux
- posix
- name: lb_load_data_store_test
gtest: true
build: test
language: c++
src:
- test/cpp/server/load_reporter/load_data_store_test.cc
deps:
- lb_load_data_store
- grpc++_test_util
- grpc_test_util
- grpc++
- grpc
- gpr_test_util
- gpr
- name: memory_test
gtest: true
build: test
@ -5652,6 +5706,11 @@ defaults:
CPPFLAGS: -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM
-D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX
CXXFLAGS: -fno-rtti -fno-exceptions
cxxabi:
CPPFLAGS: -D_LIBCPP_DISABLE_EXTERN_TEMPLATE -D_LIBCXXABI_BUILDING_LIBRARY -D_LIBCXXABI_NO_EXCEPTIONS
-Ithird_party/libcxxabi/include -nostdinc++ -Ithird_party/libcxx/include $(W_NO_UNUSED_BUT_SET_VARIABLE)
$(W_NO_MAYBE_UNINITIALIZED) -fvisibility=hidden
CXXFLAGS: $(W_NO_CXX14_COMPAT)
global:
COREFLAGS: -fno-rtti -fno-exceptions
CPPFLAGS: -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1

@ -9,11 +9,12 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/address_sorting/include)
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/nanopb)
LIBS="-lpthread $LIBS"
CFLAGS="-Wall -Werror -Wno-parentheses-equality -Wno-unused-value -std=c11 -g -O2 -D PB_FIELD_16BIT=1"
CXXFLAGS="-std=c++11 -fno-exceptions -fno-rtti -g -O2 -D PB_FIELD_16BIT=1"
CFLAGS="-Wall -Werror -Wno-parentheses-equality -Wno-unused-value -std=c11 -g -O2 -D PB_FIELD_32BIT=1"
CXXFLAGS="-std=c++11 -fno-exceptions -fno-rtti -g -O2 -D PB_FIELD_32BIT=1"
GRPC_SHARED_LIBADD="-lpthread $GRPC_SHARED_LIBADD"
PHP_REQUIRE_CXX()
PHP_ADD_LIBRARY(pthread)
@ -89,6 +90,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_trace.cc \
src/core/lib/channel/channelz.cc \
src/core/lib/channel/channelz_registry.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
@ -365,6 +367,8 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c \
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c \
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
@ -376,8 +380,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc \
src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \
src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \
src/core/ext/filters/load_reporting/server_load_reporting_filter.cc \
src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc \
src/cpp/ext/filters/census/grpc_context.cc \
src/core/ext/filters/max_age/max_age_filter.cc \
src/core/ext/filters/message_size/message_size_filter.cc \
@ -652,6 +654,7 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/grpclb)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/pick_first)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/round_robin)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns/c_ares)
@ -663,7 +666,6 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/http/client)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/http/message_compress)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/http/server)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/load_reporting)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/max_age)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/message_size)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/workarounds)

@ -65,6 +65,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\channel\\channel_stack.cc " +
"src\\core\\lib\\channel\\channel_stack_builder.cc " +
"src\\core\\lib\\channel\\channel_trace.cc " +
"src\\core\\lib\\channel\\channelz.cc " +
"src\\core\\lib\\channel\\channelz_registry.cc " +
"src\\core\\lib\\channel\\connected_channel.cc " +
"src\\core\\lib\\channel\\handshaker.cc " +
@ -341,6 +342,8 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\grpclb_channel_secure.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\grpclb_client_stats.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\load_balancer_api.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc\\lb\\v1\\google\\protobuf\\duration.pb.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc\\lb\\v1\\google\\protobuf\\timestamp.pb.c " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc\\lb\\v1\\load_balancer.pb.c " +
"src\\core\\ext\\filters\\client_channel\\resolver\\fake\\fake_resolver.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\pick_first\\pick_first.cc " +
@ -352,8 +355,6 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_wrapper_fallback.cc " +
"src\\core\\ext\\filters\\client_channel\\resolver\\dns\\native\\dns_resolver.cc " +
"src\\core\\ext\\filters\\client_channel\\resolver\\sockaddr\\sockaddr_resolver.cc " +
"src\\core\\ext\\filters\\load_reporting\\server_load_reporting_filter.cc " +
"src\\core\\ext\\filters\\load_reporting\\server_load_reporting_plugin.cc " +
"src\\cpp\\ext\\filters\\census\\grpc_context.cc " +
"src\\core\\ext\\filters\\max_age\\max_age_filter.cc " +
"src\\core\\ext\\filters\\message_size\\message_size_filter.cc " +
@ -638,13 +639,14 @@ if (PHP_GRPC != "no") {
EXTENSION("grpc", grpc_source, null,
"/DOPENSSL_NO_ASM /D_GNU_SOURCE /DWIN32_LEAN_AND_MEAN "+
"/D_HAS_EXCEPTIONS=0 /DNOMINMAX /DGRPC_ARES=0 /D_WIN32_WINNT=0x600 "+
"/DPB_FIELD_16BIT "+
"/DPB_FIELD_32BIT "+
"/I"+configure_module_dirname+" "+
"/I"+configure_module_dirname+"\\include "+
"/I"+configure_module_dirname+"\\src\\php\\ext\\grpc "+
"/I"+configure_module_dirname+"\\third_party\\boringssl\\include "+
"/I"+configure_module_dirname+"\\third_party\\zlib "+
"/I"+configure_module_dirname+"\\third_party\\address_sorting\\include");
"/I"+configure_module_dirname+"\\third_party\\address_sorting\\include "+
"/I"+configure_module_dirname+"\\third_party\\nanopb");
base_dir = get_define('BUILD_DIR');
FSO.CreateFolder(base_dir+"\\ext");
@ -661,6 +663,8 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc\\lb");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc\\lb\\v1");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc\\lb\\v1\\google");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc\\lb\\v1\\google\\protobuf");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\pick_first");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\round_robin");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver");
@ -674,7 +678,6 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\http\\client");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\http\\message_compress");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\http\\server");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\load_reporting");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\max_age");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\message_size");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\workarounds");

@ -32,7 +32,7 @@ The command line tool should support the following things:
To use the tool, you need to get the grpc repository and make sure your system
has the prerequisites for building grpc from source, given in the [installation
instructions](https://github.com/grpc/grpc/blob/master/INSTALL.md).
instructions](../BUILDING.md).
In order to build the grpc command line tool from a fresh clone of the grpc
repository, you need to run the following command to update submodules:

@ -3,7 +3,7 @@
## Installation
To install gRPC on your system, follow the instructions to build from source
[here](../../INSTALL.md). This also installs the protocol buffer compiler
[here](../../BUILDING.md). This also installs the protocol buffer compiler
`protoc` (if you don't have it already), and the C++ gRPC plugin for `protoc`.
## Hello C++ gRPC!

@ -35,7 +35,7 @@ updating.
The example code for our tutorial is in [examples/cpp/route_guide](route_guide).
You also should have the relevant tools installed to generate the server and
client interface code - if you don't already, follow the setup instructions in
[INSTALL.md](../../INSTALL.md).
[BUILDING.md](../../BUILDING.md).
## Defining the service
@ -130,7 +130,7 @@ a special gRPC C++ plugin.
For simplicity, we've provided a [Makefile](route_guide/Makefile) that runs
`protoc` for you with the appropriate plugin, input, and output (if you want to
run this yourself, make sure you've installed protoc and followed the gRPC code
[installation instructions](../../INSTALL.md) first):
[installation instructions](../../BUILDING.md) first):
```shell
$ make route_guide.grpc.pb.cc route_guide.pb.cc

@ -1,8 +1,8 @@
# gRPC C++ Hello World Tutorial
### Install gRPC
Make sure you have installed gRPC on your system. Follow the instructions here:
[https://github.com/grpc/grpc/blob/master/INSTALL](../../../INSTALL.md).
Make sure you have installed gRPC on your system. Follow the
[BUILDING.md](../../../BUILDING.md) instructions.
### Get the tutorial source code

@ -0,0 +1,6 @@
# gRPC Basics: C++ sample code
The files in this folder are the samples used in [gRPC Basics: C++][],
a detailed tutorial for using gRPC in C++.
[gRPC Basics: C++]:https://grpc.io/docs/tutorials/basic/c.html

@ -24,7 +24,7 @@ Pod::Spec.new do |s|
s.name = 'gRPC-C++'
# TODO (mxyan): use version that match gRPC version when pod is stabilized
# version = '1.14.0-dev'
version = '0.0.2'
version = '0.0.3'
s.version = version
s.summary = 'gRPC C++ library'
s.homepage = 'https://grpc.io'
@ -348,6 +348,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/channel_stack.h',
'src/core/lib/channel/channel_stack_builder.h',
'src/core/lib/channel/channel_trace.h',
'src/core/lib/channel/channelz.h',
'src/core/lib/channel/channelz_registry.h',
'src/core/lib/channel/connected_channel.h',
'src/core/lib/channel/context.h',
@ -479,13 +480,13 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h',
'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h',
'src/core/ext/filters/load_reporting/server_load_reporting_filter.h',
'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
'src/core/ext/filters/max_age/max_age_filter.h',
'src/core/ext/filters/message_size/message_size_filter.h',
'src/core/ext/filters/http/client_authority_filter.h',
@ -533,6 +534,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/channel_stack.h',
'src/core/lib/channel/channel_stack_builder.h',
'src/core/lib/channel/channel_trace.h',
'src/core/lib/channel/channelz.h',
'src/core/lib/channel/channelz_registry.h',
'src/core/lib/channel/connected_channel.h',
'src/core/lib/channel/context.h',
@ -663,6 +665,17 @@ Pod::Spec.new do |s|
'src/core/ext/transport/inproc/inproc_transport.h'
end
s.subspec 'Protobuf' do |ss|
ss.header_mappings_dir = 'include/grpcpp'
ss.dependency "#{s.name}/Interface", version
ss.source_files = 'include/grpcpp/impl/codegen/proto_buffer_reader.h',
'include/grpcpp/impl/codegen/proto_buffer_writer.h',
'include/grpcpp/impl/codegen/proto_utils.h',
'include/grpcpp/impl/codegen/config_protobuf.h',
'include/grpcpp/impl/codegen/config_protobuf.h'
end
s.prepare_command = <<-END_OF_COMMAND
find src/cpp/ -type f ! -path '*.grpc_back' -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "(pb(_.*)?\\.h)";#include <nanopb/\\1>;g'
find src/cpp/ -type f -path '*.grpc_back' -print0 | xargs -0 rm

@ -359,6 +359,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/channel_stack.h',
'src/core/lib/channel/channel_stack_builder.h',
'src/core/lib/channel/channel_trace.h',
'src/core/lib/channel/channelz.h',
'src/core/lib/channel/channelz_registry.h',
'src/core/lib/channel/connected_channel.h',
'src/core/lib/channel/context.h',
@ -490,13 +491,13 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h',
'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h',
'src/core/ext/filters/load_reporting/server_load_reporting_filter.h',
'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
'src/core/ext/filters/max_age/max_age_filter.h',
'src/core/ext/filters/message_size/message_size_filter.h',
'src/core/ext/filters/http/client_authority_filter.h',
@ -509,6 +510,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/channel_stack.cc',
'src/core/lib/channel/channel_stack_builder.cc',
'src/core/lib/channel/channel_trace.cc',
'src/core/lib/channel/channelz.cc',
'src/core/lib/channel/channelz_registry.cc',
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
@ -782,6 +784,8 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
@ -793,8 +797,6 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc',
'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc',
'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc',
'src/core/ext/filters/load_reporting/server_load_reporting_filter.cc',
'src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc',
'src/cpp/ext/filters/census/grpc_context.cc',
'src/core/ext/filters/max_age/max_age_filter.cc',
'src/core/ext/filters/message_size/message_size_filter.cc',
@ -938,6 +940,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/channel_stack.h',
'src/core/lib/channel/channel_stack_builder.h',
'src/core/lib/channel/channel_trace.h',
'src/core/lib/channel/channelz.h',
'src/core/lib/channel/channelz_registry.h',
'src/core/lib/channel/connected_channel.h',
'src/core/lib/channel/context.h',
@ -1069,13 +1072,13 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h',
'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h',
'src/core/ext/filters/load_reporting/server_load_reporting_filter.h',
'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
'src/core/ext/filters/max_age/max_age_filter.h',
'src/core/ext/filters/message_size/message_size_filter.h',
'src/core/ext/filters/http/client_authority_filter.h',
@ -1196,6 +1199,7 @@ Pod::Spec.new do |s|
'test/core/end2end/tests/cancel_before_invoke.cc',
'test/core/end2end/tests/cancel_in_a_vacuum.cc',
'test/core/end2end/tests/cancel_with_status.cc',
'test/core/end2end/tests/channelz.cc',
'test/core/end2end/tests/compressed_payload.cc',
'test/core/end2end/tests/connectivity.cc',
'test/core/end2end/tests/default_host.cc',
@ -1212,7 +1216,6 @@ Pod::Spec.new do |s|
'test/core/end2end/tests/invoke_large_request.cc',
'test/core/end2end/tests/keepalive_timeout.cc',
'test/core/end2end/tests/large_metadata.cc',
'test/core/end2end/tests/load_reporting_hook.cc',
'test/core/end2end/tests/max_concurrent_streams.cc',
'test/core/end2end/tests/max_connection_age.cc',
'test/core/end2end/tests/max_connection_idle.cc',

@ -45,8 +45,6 @@ EXPORTS
grpc_insecure_channel_create
grpc_lame_client_channel_create
grpc_channel_destroy
grpc_channel_get_trace
grpc_channel_get_uuid
grpc_call_cancel
grpc_call_cancel_with_status
grpc_call_ref

@ -296,6 +296,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/channel_stack.h )
s.files += %w( src/core/lib/channel/channel_stack_builder.h )
s.files += %w( src/core/lib/channel/channel_trace.h )
s.files += %w( src/core/lib/channel/channelz.h )
s.files += %w( src/core/lib/channel/channelz_registry.h )
s.files += %w( src/core/lib/channel/connected_channel.h )
s.files += %w( src/core/lib/channel/context.h )
@ -427,13 +428,13 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h )
s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/subchannel_list.h )
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h )
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h )
s.files += %w( src/core/ext/filters/load_reporting/server_load_reporting_filter.h )
s.files += %w( src/core/ext/filters/load_reporting/server_load_reporting_plugin.h )
s.files += %w( src/core/ext/filters/max_age/max_age_filter.h )
s.files += %w( src/core/ext/filters/message_size/message_size_filter.h )
s.files += %w( src/core/ext/filters/http/client_authority_filter.h )
@ -446,6 +447,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/channel_stack.cc )
s.files += %w( src/core/lib/channel/channel_stack_builder.cc )
s.files += %w( src/core/lib/channel/channel_trace.cc )
s.files += %w( src/core/lib/channel/channelz.cc )
s.files += %w( src/core/lib/channel/channelz_registry.cc )
s.files += %w( src/core/lib/channel/connected_channel.cc )
s.files += %w( src/core/lib/channel/handshaker.cc )
@ -722,6 +724,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c )
s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc )
@ -733,8 +737,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc )
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc )
s.files += %w( src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc )
s.files += %w( src/core/ext/filters/load_reporting/server_load_reporting_filter.cc )
s.files += %w( src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc )
s.files += %w( src/cpp/ext/filters/census/grpc_context.cc )
s.files += %w( src/core/ext/filters/max_age/max_age_filter.cc )
s.files += %w( src/core/ext/filters/message_size/message_size_filter.cc )

@ -185,6 +185,32 @@
'test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.cc',
],
},
{
'target_name': 'cxxabi',
'type': 'static_library',
'dependencies': [
],
'sources': [
'third_party/libcxxabi/src/abort_message.cpp',
'third_party/libcxxabi/src/cxa_aux_runtime.cpp',
'third_party/libcxxabi/src/cxa_default_handlers.cpp',
'third_party/libcxxabi/src/cxa_demangle.cpp',
'third_party/libcxxabi/src/cxa_exception_storage.cpp',
'third_party/libcxxabi/src/cxa_guard.cpp',
'third_party/libcxxabi/src/cxa_handlers.cpp',
'third_party/libcxxabi/src/cxa_noexception.cpp',
'third_party/libcxxabi/src/cxa_thread_atexit.cpp',
'third_party/libcxxabi/src/cxa_unexpected.cpp',
'third_party/libcxxabi/src/cxa_vector.cpp',
'third_party/libcxxabi/src/cxa_virtual.cpp',
'third_party/libcxxabi/src/fallback_malloc.cpp',
'third_party/libcxxabi/src/private_typeinfo.cpp',
'third_party/libcxxabi/src/stdlib_exception.cpp',
'third_party/libcxxabi/src/stdlib_new_delete.cpp',
'third_party/libcxxabi/src/stdlib_stdexcept.cpp',
'third_party/libcxxabi/src/stdlib_typeinfo.cpp',
],
},
{
'target_name': 'gpr',
'type': 'static_library',
@ -256,6 +282,7 @@
'src/core/lib/channel/channel_stack.cc',
'src/core/lib/channel/channel_stack_builder.cc',
'src/core/lib/channel/channel_trace.cc',
'src/core/lib/channel/channelz.cc',
'src/core/lib/channel/channelz_registry.cc',
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
@ -532,6 +559,8 @@
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
@ -543,8 +572,6 @@
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc',
'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc',
'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc',
'src/core/ext/filters/load_reporting/server_load_reporting_filter.cc',
'src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc',
'src/cpp/ext/filters/census/grpc_context.cc',
'src/core/ext/filters/max_age/max_age_filter.cc',
'src/core/ext/filters/message_size/message_size_filter.cc',
@ -606,6 +633,7 @@
'src/core/lib/channel/channel_stack.cc',
'src/core/lib/channel/channel_stack_builder.cc',
'src/core/lib/channel/channel_trace.cc',
'src/core/lib/channel/channelz.cc',
'src/core/lib/channel/channelz_registry.cc',
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
@ -837,6 +865,7 @@
'src/core/lib/channel/channel_stack.cc',
'src/core/lib/channel/channel_stack_builder.cc',
'src/core/lib/channel/channel_trace.cc',
'src/core/lib/channel/channelz.cc',
'src/core/lib/channel/channelz_registry.cc',
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
@ -1046,6 +1075,7 @@
'src/core/lib/channel/channel_stack.cc',
'src/core/lib/channel/channel_stack_builder.cc',
'src/core/lib/channel/channel_trace.cc',
'src/core/lib/channel/channelz.cc',
'src/core/lib/channel/channelz_registry.cc',
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
@ -1255,13 +1285,13 @@
'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc',
'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'src/core/ext/filters/load_reporting/server_load_reporting_filter.cc',
'src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'third_party/nanopb/pb_common.c',
'third_party/nanopb/pb_decode.c',
@ -1645,16 +1675,6 @@
'test/cpp/interop/interop_server_bootstrap.cc',
],
},
{
'target_name': 'lb_load_data_store',
'type': 'static_library',
'dependencies': [
'grpc++',
],
'sources': [
'src/cpp/server/load_reporter/load_data_store.cc',
],
},
{
'target_name': 'qps',
'type': 'static_library',
@ -2616,6 +2636,7 @@
'test/core/end2end/tests/cancel_before_invoke.cc',
'test/core/end2end/tests/cancel_in_a_vacuum.cc',
'test/core/end2end/tests/cancel_with_status.cc',
'test/core/end2end/tests/channelz.cc',
'test/core/end2end/tests/compressed_payload.cc',
'test/core/end2end/tests/connectivity.cc',
'test/core/end2end/tests/default_host.cc',
@ -2632,7 +2653,6 @@
'test/core/end2end/tests/invoke_large_request.cc',
'test/core/end2end/tests/keepalive_timeout.cc',
'test/core/end2end/tests/large_metadata.cc',
'test/core/end2end/tests/load_reporting_hook.cc',
'test/core/end2end/tests/max_concurrent_streams.cc',
'test/core/end2end/tests/max_connection_age.cc',
'test/core/end2end/tests/max_connection_idle.cc',
@ -2707,6 +2727,7 @@
'test/core/end2end/tests/cancel_before_invoke.cc',
'test/core/end2end/tests/cancel_in_a_vacuum.cc',
'test/core/end2end/tests/cancel_with_status.cc',
'test/core/end2end/tests/channelz.cc',
'test/core/end2end/tests/compressed_payload.cc',
'test/core/end2end/tests/connectivity.cc',
'test/core/end2end/tests/default_host.cc',
@ -2723,7 +2744,6 @@
'test/core/end2end/tests/invoke_large_request.cc',
'test/core/end2end/tests/keepalive_timeout.cc',
'test/core/end2end/tests/large_metadata.cc',
'test/core/end2end/tests/load_reporting_hook.cc',
'test/core/end2end/tests/max_concurrent_streams.cc',
'test/core/end2end/tests/max_connection_age.cc',
'test/core/end2end/tests/max_connection_idle.cc',

@ -286,14 +286,6 @@ GRPCAPI grpc_channel* grpc_lame_client_channel_create(
/** Close and destroy a grpc channel */
GRPCAPI void grpc_channel_destroy(grpc_channel* channel);
/** Returns the JSON formatted channel trace for this channel. The caller
owns the returned string and is responsible for freeing it. */
GRPCAPI char* grpc_channel_get_trace(grpc_channel* channel);
/** Returns the channel uuid, which can be used to look up its trace at a
later time. */
GRPCAPI intptr_t grpc_channel_get_uuid(grpc_channel* channel);
/** Error handling for grpc_call
Most grpc_call functions return a grpc_error. If the error is not GRPC_OK
then the operation failed due to some unsatisfied precondition.

@ -289,6 +289,10 @@ typedef struct {
* subchannel. The default is 10. If set to 0, channel tracing is disabled. */
#define GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE \
"grpc.max_channel_trace_events_per_node"
/** If non-zero, gRPC library will track stats and information at at per channel
* level. Disabling channelz naturally disables channel tracing. The default
* is for channelz to be disabled. */
#define GRPC_ARG_ENABLE_CHANNELZ "grpc.enable_channelz"
/** If non-zero, Cronet transport will coalesce packets to fewer frames
* when possible. */
#define GRPC_ARG_USE_CRONET_PACKET_COALESCING \

@ -171,8 +171,8 @@ class WriteOptions {
return *this;
}
/// Guarantee that all bytes have been written to the wire before completing
/// this write (usually writes are completed when they pass flow control)
/// Guarantee that all bytes have been written to the socket before completing
/// this write (usually writes are completed when they pass flow control).
inline WriteOptions& set_write_through() {
SetBit(GRPC_WRITE_THROUGH);
return *this;

@ -301,6 +301,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/channel_stack.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_stack_builder.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_trace.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channelz.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channelz_registry.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/connected_channel.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/context.h" role="src" />
@ -432,13 +433,13 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/subchannel_list.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/load_reporting/server_load_reporting_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/load_reporting/server_load_reporting_plugin.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/max_age/max_age_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/message_size/message_size_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/client_authority_filter.h" role="src" />
@ -451,6 +452,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/channel_stack.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_stack_builder.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_trace.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channelz.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channelz_registry.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/connected_channel.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/handshaker.cc" role="src" />
@ -727,6 +729,8 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc" role="src" />
@ -738,8 +742,6 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/load_reporting/server_load_reporting_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc" role="src" />
<file baseinstalldir="/" name="src/cpp/ext/filters/census/grpc_context.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/max_age/max_age_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/message_size/message_size_filter.cc" role="src" />

@ -73,7 +73,7 @@ grpc_grpclb_request* grpc_grpclb_request_create(const char* lb_service_name) {
}
static void populate_timestamp(gpr_timespec timestamp,
struct _grpc_lb_v1_Timestamp* timestamp_pb) {
grpc_grpclb_timestamp* timestamp_pb) {
timestamp_pb->has_seconds = true;
timestamp_pb->seconds = timestamp.tv_sec;
timestamp_pb->has_nanos = true;

@ -33,7 +33,9 @@ typedef grpc_lb_v1_Server_ip_address_t grpc_grpclb_ip_address;
typedef grpc_lb_v1_LoadBalanceRequest grpc_grpclb_request;
typedef grpc_lb_v1_InitialLoadBalanceResponse grpc_grpclb_initial_response;
typedef grpc_lb_v1_Server grpc_grpclb_server;
typedef grpc_lb_v1_Duration grpc_grpclb_duration;
typedef google_protobuf_Duration grpc_grpclb_duration;
typedef google_protobuf_Timestamp grpc_grpclb_timestamp;
typedef struct {
grpc_grpclb_server** servers;
size_t num_servers;

@ -0,0 +1,19 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.3.7-dev */
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
const pb_field_t google_protobuf_Duration_fields[3] = {
PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, google_protobuf_Duration, seconds, seconds, 0),
PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, google_protobuf_Duration, nanos, seconds, 0),
PB_LAST_FIELD
};
/* @@protoc_insertion_point(eof) */

@ -0,0 +1,54 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.3.7-dev */
#ifndef PB_GOOGLE_PROTOBUF_DURATION_PB_H_INCLUDED
#define PB_GOOGLE_PROTOBUF_DURATION_PB_H_INCLUDED
#include "pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Struct definitions */
typedef struct _google_protobuf_Duration {
bool has_seconds;
int64_t seconds;
bool has_nanos;
int32_t nanos;
/* @@protoc_insertion_point(struct:google_protobuf_Duration) */
} google_protobuf_Duration;
/* Default values for struct fields */
/* Initializer values for message structs */
#define google_protobuf_Duration_init_default {false, 0, false, 0}
#define google_protobuf_Duration_init_zero {false, 0, false, 0}
/* Field tags (for use in manual encoding/decoding) */
#define google_protobuf_Duration_seconds_tag 1
#define google_protobuf_Duration_nanos_tag 2
/* Struct field encoding specification for nanopb */
extern const pb_field_t google_protobuf_Duration_fields[3];
/* Maximum encoded size of messages (where known) */
#define google_protobuf_Duration_size 22
/* Message IDs (where set with "msgid" option) */
#ifdef PB_MSGID
#define DURATION_MESSAGES \
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
/* @@protoc_insertion_point(eof) */
#endif

@ -0,0 +1,19 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.3.7-dev */
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
const pb_field_t google_protobuf_Timestamp_fields[3] = {
PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, google_protobuf_Timestamp, seconds, seconds, 0),
PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, google_protobuf_Timestamp, nanos, seconds, 0),
PB_LAST_FIELD
};
/* @@protoc_insertion_point(eof) */

@ -0,0 +1,54 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.3.7-dev */
#ifndef PB_GOOGLE_PROTOBUF_TIMESTAMP_PB_H_INCLUDED
#define PB_GOOGLE_PROTOBUF_TIMESTAMP_PB_H_INCLUDED
#include "pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Struct definitions */
typedef struct _google_protobuf_Timestamp {
bool has_seconds;
int64_t seconds;
bool has_nanos;
int32_t nanos;
/* @@protoc_insertion_point(struct:google_protobuf_Timestamp) */
} google_protobuf_Timestamp;
/* Default values for struct fields */
/* Initializer values for message structs */
#define google_protobuf_Timestamp_init_default {false, 0, false, 0}
#define google_protobuf_Timestamp_init_zero {false, 0, false, 0}
/* Field tags (for use in manual encoding/decoding) */
#define google_protobuf_Timestamp_seconds_tag 1
#define google_protobuf_Timestamp_nanos_tag 2
/* Struct field encoding specification for nanopb */
extern const pb_field_t google_protobuf_Timestamp_fields[3];
/* Maximum encoded size of messages (where known) */
#define google_protobuf_Timestamp_size 22
/* Message IDs (where set with "msgid" option) */
#ifdef PB_MSGID
#define TIMESTAMP_MESSAGES \
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
/* @@protoc_insertion_point(eof) */
#endif

@ -2,7 +2,6 @@
/* Generated by nanopb-0.3.7-dev */
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
@ -10,18 +9,6 @@
const pb_field_t grpc_lb_v1_Duration_fields[3] = {
PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v1_Duration, seconds, seconds, 0),
PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Duration, nanos, seconds, 0),
PB_LAST_FIELD
};
const pb_field_t grpc_lb_v1_Timestamp_fields[3] = {
PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, grpc_lb_v1_Timestamp, seconds, seconds, 0),
PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_Timestamp, nanos, seconds, 0),
PB_LAST_FIELD
};
const pb_field_t grpc_lb_v1_LoadBalanceRequest_fields[3] = {
PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v1_LoadBalanceRequest, initial_request, initial_request, &grpc_lb_v1_InitialLoadBalanceRequest_fields),
PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_LoadBalanceRequest, client_stats, initial_request, &grpc_lb_v1_ClientStats_fields),
@ -40,7 +27,7 @@ const pb_field_t grpc_lb_v1_ClientStatsPerToken_fields[3] = {
};
const pb_field_t grpc_lb_v1_ClientStats_fields[7] = {
PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v1_ClientStats, timestamp, timestamp, &grpc_lb_v1_Timestamp_fields),
PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_lb_v1_ClientStats, timestamp, timestamp, &google_protobuf_Timestamp_fields),
PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ClientStats, num_calls_started, timestamp, 0),
PB_FIELD( 3, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ClientStats, num_calls_finished, num_calls_started, 0),
PB_FIELD( 6, INT64 , OPTIONAL, STATIC , OTHER, grpc_lb_v1_ClientStats, num_calls_finished_with_client_failed_to_send, num_calls_finished, 0),
@ -57,7 +44,7 @@ const pb_field_t grpc_lb_v1_LoadBalanceResponse_fields[3] = {
const pb_field_t grpc_lb_v1_InitialLoadBalanceResponse_fields[3] = {
PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_lb_v1_InitialLoadBalanceResponse, load_balancer_delegate, load_balancer_delegate, 0),
PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval, load_balancer_delegate, &grpc_lb_v1_Duration_fields),
PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval, load_balancer_delegate, &google_protobuf_Duration_fields),
PB_LAST_FIELD
};
@ -84,7 +71,7 @@ const pb_field_t grpc_lb_v1_Server_fields[5] = {
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
* field descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 65536 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v1_ServerList, servers) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_Timestamp_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server)
PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 65536 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v1_ServerList, servers) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server)
#endif
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
@ -95,7 +82,7 @@ PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request)
* numbers or field sizes that are larger than what can fit in the default
* 8 bit descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 256 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v1_Duration_grpc_lb_v1_Timestamp_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server)
PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 256 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server)
#endif

@ -4,6 +4,8 @@
#ifndef PB_GRPC_LB_V1_LOAD_BALANCER_PB_H_INCLUDED
#define PB_GRPC_LB_V1_LOAD_BALANCER_PB_H_INCLUDED
#include "pb.h"
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h"
#include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
@ -19,6 +21,21 @@ typedef struct _grpc_lb_v1_ServerList {
/* @@protoc_insertion_point(struct:grpc_lb_v1_ServerList) */
} grpc_lb_v1_ServerList;
typedef struct _grpc_lb_v1_ClientStats {
bool has_timestamp;
google_protobuf_Timestamp timestamp;
bool has_num_calls_started;
int64_t num_calls_started;
bool has_num_calls_finished;
int64_t num_calls_finished;
bool has_num_calls_finished_with_client_failed_to_send;
int64_t num_calls_finished_with_client_failed_to_send;
bool has_num_calls_finished_known_received;
int64_t num_calls_finished_known_received;
pb_callback_t calls_finished_with_drop;
/* @@protoc_insertion_point(struct:grpc_lb_v1_ClientStats) */
} grpc_lb_v1_ClientStats;
typedef struct _grpc_lb_v1_ClientStatsPerToken {
pb_callback_t load_balance_token;
bool has_num_calls;
@ -26,20 +43,20 @@ typedef struct _grpc_lb_v1_ClientStatsPerToken {
/* @@protoc_insertion_point(struct:grpc_lb_v1_ClientStatsPerToken) */
} grpc_lb_v1_ClientStatsPerToken;
typedef struct _grpc_lb_v1_Duration {
bool has_seconds;
int64_t seconds;
bool has_nanos;
int32_t nanos;
/* @@protoc_insertion_point(struct:grpc_lb_v1_Duration) */
} grpc_lb_v1_Duration;
typedef struct _grpc_lb_v1_InitialLoadBalanceRequest {
bool has_name;
char name[128];
/* @@protoc_insertion_point(struct:grpc_lb_v1_InitialLoadBalanceRequest) */
} grpc_lb_v1_InitialLoadBalanceRequest;
typedef struct _grpc_lb_v1_InitialLoadBalanceResponse {
bool has_load_balancer_delegate;
char load_balancer_delegate[64];
bool has_client_stats_report_interval;
google_protobuf_Duration client_stats_report_interval;
/* @@protoc_insertion_point(struct:grpc_lb_v1_InitialLoadBalanceResponse) */
} grpc_lb_v1_InitialLoadBalanceResponse;
typedef PB_BYTES_ARRAY_T(16) grpc_lb_v1_Server_ip_address_t;
typedef struct _grpc_lb_v1_Server {
bool has_ip_address;
@ -53,37 +70,6 @@ typedef struct _grpc_lb_v1_Server {
/* @@protoc_insertion_point(struct:grpc_lb_v1_Server) */
} grpc_lb_v1_Server;
typedef struct _grpc_lb_v1_Timestamp {
bool has_seconds;
int64_t seconds;
bool has_nanos;
int32_t nanos;
/* @@protoc_insertion_point(struct:grpc_lb_v1_Timestamp) */
} grpc_lb_v1_Timestamp;
typedef struct _grpc_lb_v1_ClientStats {
bool has_timestamp;
grpc_lb_v1_Timestamp timestamp;
bool has_num_calls_started;
int64_t num_calls_started;
bool has_num_calls_finished;
int64_t num_calls_finished;
bool has_num_calls_finished_with_client_failed_to_send;
int64_t num_calls_finished_with_client_failed_to_send;
bool has_num_calls_finished_known_received;
int64_t num_calls_finished_known_received;
pb_callback_t calls_finished_with_drop;
/* @@protoc_insertion_point(struct:grpc_lb_v1_ClientStats) */
} grpc_lb_v1_ClientStats;
typedef struct _grpc_lb_v1_InitialLoadBalanceResponse {
bool has_load_balancer_delegate;
char load_balancer_delegate[64];
bool has_client_stats_report_interval;
grpc_lb_v1_Duration client_stats_report_interval;
/* @@protoc_insertion_point(struct:grpc_lb_v1_InitialLoadBalanceResponse) */
} grpc_lb_v1_InitialLoadBalanceResponse;
typedef struct _grpc_lb_v1_LoadBalanceRequest {
bool has_initial_request;
grpc_lb_v1_InitialLoadBalanceRequest initial_request;
@ -103,56 +89,46 @@ typedef struct _grpc_lb_v1_LoadBalanceResponse {
/* Default values for struct fields */
/* Initializer values for message structs */
#define grpc_lb_v1_Duration_init_default {false, 0, false, 0}
#define grpc_lb_v1_Timestamp_init_default {false, 0, false, 0}
#define grpc_lb_v1_LoadBalanceRequest_init_default {false, grpc_lb_v1_InitialLoadBalanceRequest_init_default, false, grpc_lb_v1_ClientStats_init_default}
#define grpc_lb_v1_InitialLoadBalanceRequest_init_default {false, ""}
#define grpc_lb_v1_ClientStatsPerToken_init_default {{{NULL}, NULL}, false, 0}
#define grpc_lb_v1_ClientStats_init_default {false, grpc_lb_v1_Timestamp_init_default, false, 0, false, 0, false, 0, false, 0, {{NULL}, NULL}}
#define grpc_lb_v1_ClientStats_init_default {false, google_protobuf_Timestamp_init_default, false, 0, false, 0, false, 0, false, 0, {{NULL}, NULL}}
#define grpc_lb_v1_LoadBalanceResponse_init_default {false, grpc_lb_v1_InitialLoadBalanceResponse_init_default, false, grpc_lb_v1_ServerList_init_default}
#define grpc_lb_v1_InitialLoadBalanceResponse_init_default {false, "", false, grpc_lb_v1_Duration_init_default}
#define grpc_lb_v1_InitialLoadBalanceResponse_init_default {false, "", false, google_protobuf_Duration_init_default}
#define grpc_lb_v1_ServerList_init_default {{{NULL}, NULL}}
#define grpc_lb_v1_Server_init_default {false, {0, {0}}, false, 0, false, "", false, 0}
#define grpc_lb_v1_Duration_init_zero {false, 0, false, 0}
#define grpc_lb_v1_Timestamp_init_zero {false, 0, false, 0}
#define grpc_lb_v1_LoadBalanceRequest_init_zero {false, grpc_lb_v1_InitialLoadBalanceRequest_init_zero, false, grpc_lb_v1_ClientStats_init_zero}
#define grpc_lb_v1_InitialLoadBalanceRequest_init_zero {false, ""}
#define grpc_lb_v1_ClientStatsPerToken_init_zero {{{NULL}, NULL}, false, 0}
#define grpc_lb_v1_ClientStats_init_zero {false, grpc_lb_v1_Timestamp_init_zero, false, 0, false, 0, false, 0, false, 0, {{NULL}, NULL}}
#define grpc_lb_v1_ClientStats_init_zero {false, google_protobuf_Timestamp_init_zero, false, 0, false, 0, false, 0, false, 0, {{NULL}, NULL}}
#define grpc_lb_v1_LoadBalanceResponse_init_zero {false, grpc_lb_v1_InitialLoadBalanceResponse_init_zero, false, grpc_lb_v1_ServerList_init_zero}
#define grpc_lb_v1_InitialLoadBalanceResponse_init_zero {false, "", false, grpc_lb_v1_Duration_init_zero}
#define grpc_lb_v1_InitialLoadBalanceResponse_init_zero {false, "", false, google_protobuf_Duration_init_zero}
#define grpc_lb_v1_ServerList_init_zero {{{NULL}, NULL}}
#define grpc_lb_v1_Server_init_zero {false, {0, {0}}, false, 0, false, "", false, 0}
/* Field tags (for use in manual encoding/decoding) */
#define grpc_lb_v1_ServerList_servers_tag 1
#define grpc_lb_v1_ClientStatsPerToken_load_balance_token_tag 1
#define grpc_lb_v1_ClientStatsPerToken_num_calls_tag 2
#define grpc_lb_v1_Duration_seconds_tag 1
#define grpc_lb_v1_Duration_nanos_tag 2
#define grpc_lb_v1_InitialLoadBalanceRequest_name_tag 1
#define grpc_lb_v1_Server_ip_address_tag 1
#define grpc_lb_v1_Server_port_tag 2
#define grpc_lb_v1_Server_load_balance_token_tag 3
#define grpc_lb_v1_Server_drop_tag 4
#define grpc_lb_v1_Timestamp_seconds_tag 1
#define grpc_lb_v1_Timestamp_nanos_tag 2
#define grpc_lb_v1_ClientStats_timestamp_tag 1
#define grpc_lb_v1_ClientStats_num_calls_started_tag 2
#define grpc_lb_v1_ClientStats_num_calls_finished_tag 3
#define grpc_lb_v1_ClientStats_num_calls_finished_with_client_failed_to_send_tag 6
#define grpc_lb_v1_ClientStats_num_calls_finished_known_received_tag 7
#define grpc_lb_v1_ClientStats_calls_finished_with_drop_tag 8
#define grpc_lb_v1_ClientStatsPerToken_load_balance_token_tag 1
#define grpc_lb_v1_ClientStatsPerToken_num_calls_tag 2
#define grpc_lb_v1_InitialLoadBalanceRequest_name_tag 1
#define grpc_lb_v1_InitialLoadBalanceResponse_load_balancer_delegate_tag 1
#define grpc_lb_v1_InitialLoadBalanceResponse_client_stats_report_interval_tag 2
#define grpc_lb_v1_Server_ip_address_tag 1
#define grpc_lb_v1_Server_port_tag 2
#define grpc_lb_v1_Server_load_balance_token_tag 3
#define grpc_lb_v1_Server_drop_tag 4
#define grpc_lb_v1_LoadBalanceRequest_initial_request_tag 1
#define grpc_lb_v1_LoadBalanceRequest_client_stats_tag 2
#define grpc_lb_v1_LoadBalanceResponse_initial_response_tag 1
#define grpc_lb_v1_LoadBalanceResponse_server_list_tag 2
/* Struct field encoding specification for nanopb */
extern const pb_field_t grpc_lb_v1_Duration_fields[3];
extern const pb_field_t grpc_lb_v1_Timestamp_fields[3];
extern const pb_field_t grpc_lb_v1_LoadBalanceRequest_fields[3];
extern const pb_field_t grpc_lb_v1_InitialLoadBalanceRequest_fields[2];
extern const pb_field_t grpc_lb_v1_ClientStatsPerToken_fields[3];
@ -163,8 +139,6 @@ extern const pb_field_t grpc_lb_v1_ServerList_fields[2];
extern const pb_field_t grpc_lb_v1_Server_fields[5];
/* Maximum encoded size of messages (where known) */
#define grpc_lb_v1_Duration_size 22
#define grpc_lb_v1_Timestamp_size 22
#define grpc_lb_v1_LoadBalanceRequest_size (140 + grpc_lb_v1_ClientStats_size)
#define grpc_lb_v1_InitialLoadBalanceRequest_size 131
/* grpc_lb_v1_ClientStatsPerToken_size depends on runtime parameters */

@ -74,6 +74,8 @@ struct grpc_ares_ev_driver {
bool working;
/** is this event driver being shut down */
bool shutting_down;
/** request object that's using this ev driver */
grpc_ares_request* request;
};
static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver);
@ -92,6 +94,7 @@ static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) {
GPR_ASSERT(ev_driver->fds == nullptr);
GRPC_COMBINER_UNREF(ev_driver->combiner, "free ares event driver");
ares_destroy(ev_driver->channel);
grpc_ares_complete_request_locked(ev_driver->request);
gpr_free(ev_driver);
}
}
@ -115,7 +118,8 @@ static void fd_node_shutdown_locked(fd_node* fdn, const char* reason) {
grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
grpc_pollset_set* pollset_set,
grpc_combiner* combiner) {
grpc_combiner* combiner,
grpc_ares_request* request) {
*ev_driver = static_cast<grpc_ares_ev_driver*>(
gpr_malloc(sizeof(grpc_ares_ev_driver)));
ares_options opts;
@ -139,10 +143,12 @@ grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
(*ev_driver)->fds = nullptr;
(*ev_driver)->working = false;
(*ev_driver)->shutting_down = false;
(*ev_driver)->request = request;
return GRPC_ERROR_NONE;
}
void grpc_ares_ev_driver_destroy_locked(grpc_ares_ev_driver* ev_driver) {
void grpc_ares_ev_driver_on_queries_complete_locked(
grpc_ares_ev_driver* ev_driver) {
// We mark the event driver as being shut down. If the event driver
// is working, grpc_ares_notify_on_event_locked will shut down the
// fds; if it's not working, there are no fds to shut down.

@ -22,6 +22,7 @@
#include <grpc/support/port_platform.h>
#include <ares.h>
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
#include "src/core/lib/gprpp/abstract.h"
#include "src/core/lib/iomgr/pollset_set.h"
@ -42,12 +43,12 @@ ares_channel* grpc_ares_ev_driver_get_channel_locked(
created successfully. */
grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver,
grpc_pollset_set* pollset_set,
grpc_combiner* combiner);
grpc_combiner* combiner,
grpc_ares_request* request);
/* Destroys \a ev_driver asynchronously. Pending lookups made on \a ev_driver
will be cancelled and their on_done callbacks will be invoked with a status
of ARES_ECANCELLED. */
void grpc_ares_ev_driver_destroy_locked(grpc_ares_ev_driver* ev_driver);
/* Called back when all DNS lookups have completed. */
void grpc_ares_ev_driver_on_queries_complete_locked(
grpc_ares_ev_driver* ev_driver);
/* Shutdown all the grpc_fds used by \a ev_driver */
void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver);

@ -44,11 +44,13 @@ class GrpcPolledFdPosix : public GrpcPolledFd {
: as_(as) {
gpr_asprintf(&name_, "c-ares fd: %d", (int)as);
fd_ = grpc_fd_create((int)as, name_, false);
grpc_pollset_set_add_fd(driver_pollset_set, fd_);
driver_pollset_set_ = driver_pollset_set;
grpc_pollset_set_add_fd(driver_pollset_set_, fd_);
}
~GrpcPolledFdPosix() {
gpr_free(name_);
grpc_pollset_set_del_fd(driver_pollset_set_, fd_);
/* c-ares library will close the fd inside grpc_fd. This fd may be picked up
immediately by another thread, and should not be closed by the following
grpc_fd_orphan. */
@ -81,6 +83,7 @@ class GrpcPolledFdPosix : public GrpcPolledFd {
char* name_;
ares_socket_t as_;
grpc_fd* fd_;
grpc_pollset_set* driver_pollset_set_;
};
GrpcPolledFd* NewGrpcPolledFdLocked(ares_socket_t as,

@ -63,7 +63,7 @@ struct grpc_ares_request {
/** the evernt driver used by this request */
grpc_ares_ev_driver* ev_driver;
/** number of ongoing queries */
gpr_refcount pending_queries;
size_t pending_queries;
/** is there at least one successful query, set in on_done_cb */
bool success;
@ -145,21 +145,25 @@ void grpc_cares_wrapper_test_only_address_sorting_sort(
}
static void grpc_ares_request_ref_locked(grpc_ares_request* r) {
gpr_ref(&r->pending_queries);
r->pending_queries++;
}
static void grpc_ares_request_unref_locked(grpc_ares_request* r) {
/* If there are no pending queries, invoke on_done callback and destroy the
r->pending_queries--;
if (r->pending_queries == 0u) {
grpc_ares_ev_driver_on_queries_complete_locked(r->ev_driver);
}
}
void grpc_ares_complete_request_locked(grpc_ares_request* r) {
/* Invoke on_done callback and destroy the
request */
if (gpr_unref(&r->pending_queries)) {
grpc_lb_addresses* lb_addrs = *(r->lb_addrs_out);
if (lb_addrs != nullptr) {
grpc_cares_wrapper_address_sorting_sort(lb_addrs);
}
GRPC_CLOSURE_SCHED(r->on_done, r->error);
grpc_ares_ev_driver_destroy_locked(r->ev_driver);
gpr_free(r);
grpc_lb_addresses* lb_addrs = *(r->lb_addrs_out);
if (lb_addrs != nullptr) {
grpc_cares_wrapper_address_sorting_sort(lb_addrs);
}
GRPC_CLOSURE_SCHED(r->on_done, r->error);
gpr_free(r);
}
static grpc_ares_hostbyname_request* create_hostbyname_request_locked(
@ -399,20 +403,18 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
}
port = gpr_strdup(default_port);
}
grpc_ares_ev_driver* ev_driver;
error = grpc_ares_ev_driver_create_locked(&ev_driver, interested_parties,
combiner);
if (error != GRPC_ERROR_NONE) goto error_cleanup;
r = static_cast<grpc_ares_request*>(gpr_zalloc(sizeof(grpc_ares_request)));
r->ev_driver = ev_driver;
r->ev_driver = nullptr;
r->on_done = on_done;
r->lb_addrs_out = addrs;
r->service_config_json_out = service_config_json;
r->success = false;
r->error = GRPC_ERROR_NONE;
r->pending_queries = 0;
error = grpc_ares_ev_driver_create_locked(&r->ev_driver, interested_parties,
combiner, r);
if (error != GRPC_ERROR_NONE) goto error_cleanup;
channel = grpc_ares_ev_driver_get_channel_locked(r->ev_driver);
// If dns_server is specified, use it.
if (dns_server != nullptr) {
gpr_log(GPR_INFO, "Using DNS server %s", dns_server);
@ -437,7 +439,6 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
error = grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("cannot parse authority"),
GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
gpr_free(r);
goto error_cleanup;
}
int status = ares_set_servers_ports(*channel, &r->dns_server_addr);
@ -447,11 +448,10 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
ares_strerror(status));
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
gpr_free(error_msg);
gpr_free(r);
goto error_cleanup;
}
}
gpr_ref_init(&r->pending_queries, 1);
r->pending_queries = 1;
if (grpc_ipv6_loopback_available()) {
hr = create_hostbyname_request_locked(r, host, strhtons(port),
false /* is_balancer */);
@ -487,6 +487,7 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
error_cleanup:
GRPC_CLOSURE_SCHED(on_done, error);
gpr_free(r);
gpr_free(host);
gpr_free(port);
return nullptr;

@ -66,6 +66,10 @@ grpc_error* grpc_ares_init(void);
it has been called the same number of times as grpc_ares_init(). */
void grpc_ares_cleanup(void);
/** Schedules the desired callback for request completion
* and destroys the grpc_ares_request */
void grpc_ares_complete_request_locked(grpc_ares_request* request);
/* Exposed only for testing */
void grpc_cares_wrapper_test_only_address_sorting_sort(
grpc_lb_addresses* lb_addrs);

@ -0,0 +1,108 @@
/*
*
* 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_LOAD_REPORTING_REGISTERED_OPENCENSUS_OBJECTS_H
#define GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_REGISTERED_OPENCENSUS_OBJECTS_H
#include <grpc/support/port_platform.h>
#include "opencensus/stats/stats.h"
#include "src/cpp/server/load_reporter/constants.h"
namespace grpc {
namespace load_reporter {
// Measures.
::opencensus::stats::MeasureInt64 MeasureStartCount() {
static const ::opencensus::stats::MeasureInt64 start_count =
::opencensus::stats::MeasureInt64::Register(
kMeasureStartCount, kMeasureStartCount, kMeasureStartCount);
return start_count;
}
::opencensus::stats::MeasureInt64 MeasureEndCount() {
static const ::opencensus::stats::MeasureInt64 end_count =
::opencensus::stats::MeasureInt64::Register(
kMeasureEndCount, kMeasureEndCount, kMeasureEndCount);
return end_count;
}
::opencensus::stats::MeasureInt64 MeasureEndBytesSent() {
static const ::opencensus::stats::MeasureInt64 end_bytes_sent =
::opencensus::stats::MeasureInt64::Register(
kMeasureEndBytesSent, kMeasureEndBytesSent, kMeasureEndBytesSent);
return end_bytes_sent;
}
::opencensus::stats::MeasureInt64 MeasureEndBytesReceived() {
static const ::opencensus::stats::MeasureInt64 end_bytes_received =
::opencensus::stats::MeasureInt64::Register(kMeasureEndBytesReceived,
kMeasureEndBytesReceived,
kMeasureEndBytesReceived);
return end_bytes_received;
}
::opencensus::stats::MeasureInt64 MeasureEndLatencyMs() {
static const ::opencensus::stats::MeasureInt64 end_latency_ms =
::opencensus::stats::MeasureInt64::Register(
kMeasureEndLatencyMs, kMeasureEndLatencyMs, kMeasureEndLatencyMs);
return end_latency_ms;
}
::opencensus::stats::MeasureDouble MeasureOtherCallMetric() {
static const ::opencensus::stats::MeasureDouble other_call_metric =
::opencensus::stats::MeasureDouble::Register(kMeasureOtherCallMetric,
kMeasureOtherCallMetric,
kMeasureOtherCallMetric);
return other_call_metric;
}
// Tags.
opencensus::stats::TagKey TagKeyToken() {
static const auto token = opencensus::stats::TagKey::Register(kTagKeyToken);
return token;
}
opencensus::stats::TagKey TagKeyHost() {
static const auto token = opencensus::stats::TagKey::Register(kTagKeyHost);
return token;
}
opencensus::stats::TagKey TagKeyUserId() {
static const auto token = opencensus::stats::TagKey::Register(kTagKeyUserId);
return token;
}
opencensus::stats::TagKey TagKeyStatus() {
static const auto token = opencensus::stats::TagKey::Register(kTagKeyStatus);
return token;
}
opencensus::stats::TagKey TagKeyMetricName() {
static const auto token =
opencensus::stats::TagKey::Register(kTagKeyMetricName);
return token;
}
} // namespace load_reporter
} // namespace grpc
#endif /* GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_REGISTERED_OPENCENSUS_OBJECTS_H \
*/

@ -18,203 +18,311 @@
#include <grpc/support/port_platform.h>
#include <string.h>
#include <grpc/grpc_security.h>
#include <grpc/load_reporting.h>
#include <grpc/slice.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/uri_parser.h"
#include "src/core/ext/filters/load_reporting/registered_opencensus_objects.h"
#include "src/core/ext/filters/load_reporting/server_load_reporting_filter.h"
#include "src/core/ext/filters/load_reporting/server_load_reporting_plugin.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/sockaddr_posix.h"
#include "src/core/lib/iomgr/socket_utils.h"
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/call.h"
#include "src/core/lib/transport/static_metadata.h"
namespace {
struct call_data {
intptr_t id; /**< an id unique to the call */
bool have_trailing_md_string;
grpc_slice trailing_md_string;
bool have_initial_md_string;
grpc_slice initial_md_string;
bool have_service_method;
grpc_slice service_method;
/* stores the recv_initial_metadata op's ready closure, which we wrap with our
* own (on_initial_md_ready) in order to capture the incoming initial metadata
* */
grpc_closure* ops_recv_initial_metadata_ready;
/* to get notified of the availability of the incoming initial metadata. */
grpc_closure on_initial_md_ready;
grpc_metadata_batch* recv_initial_metadata;
};
namespace grpc {
struct channel_data {
intptr_t id; /**< an id unique to the channel */
};
} // namespace
static void on_initial_md_ready(void* user_data, grpc_error* err) {
grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (err == GRPC_ERROR_NONE) {
if (calld->recv_initial_metadata->idx.named.path != nullptr) {
calld->service_method = grpc_slice_ref_internal(
GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.path->md));
calld->have_service_method = true;
} else {
err = grpc_error_add_child(
err, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing :path header"));
}
if (calld->recv_initial_metadata->idx.named.lb_token != nullptr) {
calld->initial_md_string = grpc_slice_ref_internal(
GRPC_MDVALUE(calld->recv_initial_metadata->idx.named.lb_token->md));
calld->have_initial_md_string = true;
grpc_metadata_batch_remove(
calld->recv_initial_metadata,
calld->recv_initial_metadata->idx.named.lb_token);
grpc_error* ServerLoadReportingChannelData::Init(
grpc_channel_element* /* elem */, grpc_channel_element_args* args) {
GPR_ASSERT(!args->is_last);
// Find and record the peer_identity.
const grpc_auth_context* auth_context =
grpc_find_auth_context_in_args(args->channel_args);
if (auth_context != nullptr &&
grpc_auth_context_peer_is_authenticated(auth_context)) {
grpc_auth_property_iterator auth_it =
grpc_auth_context_peer_identity(auth_context);
const grpc_auth_property* auth_property =
grpc_auth_property_iterator_next(&auth_it);
if (auth_property != nullptr) {
peer_identity_ = auth_property->value;
peer_identity_len_ = auth_property->value_length;
}
} else {
GRPC_ERROR_REF(err);
}
GRPC_CLOSURE_RUN(calld->ops_recv_initial_metadata_ready, err);
}
/* Constructor for call_data */
static grpc_error* init_call_elem(grpc_call_element* elem,
const grpc_call_element_args* args) {
call_data* calld = static_cast<call_data*>(elem->call_data);
calld->id = (intptr_t)args->call_stack;
GRPC_CLOSURE_INIT(&calld->on_initial_md_ready, on_initial_md_ready, elem,
grpc_schedule_on_exec_ctx);
/* TODO(dgq): do something with the data
channel_data *chand = elem->channel_data;
grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_CREATION,
(intptr_t)chand->id,
(intptr_t)calld->id,
NULL,
NULL,
NULL,
NULL};
*/
return GRPC_ERROR_NONE;
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_call_element* elem,
const grpc_call_final_info* final_info,
grpc_closure* ignored) {
call_data* calld = static_cast<call_data*>(elem->call_data);
void ServerLoadReportingCallData::Destroy(
grpc_call_element* elem, const grpc_call_final_info* final_info,
grpc_closure* then_call_closure) {
ServerLoadReportingChannelData* chand =
reinterpret_cast<ServerLoadReportingChannelData*>(elem->channel_data);
// Only record an end if we've recorded its corresponding start, which is
// indicated by a non-null client_ip_and_lr_token_. Note that it's possible
// that we attempt to record the call end before we have recorded the call
// start, because the data needed for recording the start comes from the
// initial metadata, which may not be ready before the call finishes.
if (client_ip_and_lr_token_ != nullptr) {
opencensus::stats::Record(
{{::grpc::load_reporter::MeasureEndCount(), 1},
{::grpc::load_reporter::MeasureEndBytesSent(),
final_info->stats.transport_stream_stats.outgoing.data_bytes},
{::grpc::load_reporter::MeasureEndBytesReceived(),
final_info->stats.transport_stream_stats.incoming.data_bytes},
{::grpc::load_reporter::MeasureEndLatencyMs(),
gpr_time_to_millis(final_info->stats.latency)}},
{{::grpc::load_reporter::TagKeyToken(),
{client_ip_and_lr_token_, client_ip_and_lr_token_len_}},
{::grpc::load_reporter::TagKeyHost(),
{target_host_, target_host_len_}},
{::grpc::load_reporter::TagKeyUserId(),
{chand->peer_identity(), chand->peer_identity_len()}},
{::grpc::load_reporter::TagKeyStatus(),
GetStatusTagForStatus(final_info->final_status)}});
}
grpc_slice_unref_internal(service_method_);
}
/* TODO(dgq): do something with the data
channel_data *chand = elem->channel_data;
grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CALL_DESTRUCTION,
(intptr_t)chand->id,
(intptr_t)calld->id,
final_info,
calld->initial_md_string,
calld->trailing_md_string,
calld->service_method};
*/
void ServerLoadReportingCallData::StartTransportStreamOpBatch(
grpc_call_element* elem, TransportStreamOpBatch* op) {
GPR_TIMER_SCOPE("lr_start_transport_stream_op", 0);
if (op->recv_initial_metadata() != nullptr) {
// Save some fields to use when initial metadata is ready.
peer_string_ = op->get_peer_string();
recv_initial_metadata_ = op->recv_initial_metadata();
original_recv_initial_metadata_ready_ = op->recv_initial_metadata_ready();
// Substitute the original closure for the wrapper closure.
op->set_recv_initial_metadata_ready(&recv_initial_metadata_ready_);
} else if (op->send_trailing_metadata() != nullptr) {
GRPC_LOG_IF_ERROR(
"server_load_reporting_filter",
grpc_metadata_batch_filter(op->send_trailing_metadata()->batch(),
SendTrailingMetadataFilter, elem,
"send_trailing_metadata filtering error"));
}
grpc_call_next_op(elem, op->op());
}
if (calld->have_initial_md_string) {
grpc_slice_unref_internal(calld->initial_md_string);
void ServerLoadReportingCallData::GetCensusSafeClientIpString(
char** client_ip_string, size_t* size) {
// Find the client URI string.
const char* client_uri_str =
reinterpret_cast<const char*>(gpr_atm_acq_load(peer_string_));
if (client_uri_str == nullptr) {
gpr_log(GPR_ERROR,
"Unable to extract client URI string (peer string) from gRPC "
"metadata.");
*client_ip_string = nullptr;
*size = 0;
return;
}
if (calld->have_trailing_md_string) {
grpc_slice_unref_internal(calld->trailing_md_string);
// Parse the client URI string into grpc_uri.
grpc_uri* client_uri = grpc_uri_parse(client_uri_str, true);
if (client_uri == nullptr) {
gpr_log(GPR_ERROR,
"Unable to parse the client URI string (peer string) to a client "
"URI.");
*client_ip_string = nullptr;
*size = 0;
return;
}
if (calld->have_service_method) {
grpc_slice_unref_internal(calld->service_method);
// Parse the client URI into grpc_resolved_address.
grpc_resolved_address resolved_address;
bool success = grpc_parse_uri(client_uri, &resolved_address);
grpc_uri_destroy(client_uri);
if (!success) {
gpr_log(GPR_ERROR,
"Unable to parse client URI into a grpc_resolved_address.");
*client_ip_string = nullptr;
*size = 0;
return;
}
// Convert the socket address in the grpc_resolved_address into a hex string
// according to the address family.
grpc_sockaddr* addr = reinterpret_cast<grpc_sockaddr*>(resolved_address.addr);
if (addr->sa_family == GRPC_AF_INET) {
grpc_sockaddr_in* addr4 = reinterpret_cast<grpc_sockaddr_in*>(addr);
gpr_asprintf(client_ip_string, "%08x", grpc_ntohl(addr4->sin_addr.s_addr));
*size = 8;
} else if (addr->sa_family == GRPC_AF_INET6) {
grpc_sockaddr_in6* addr6 = reinterpret_cast<grpc_sockaddr_in6*>(addr);
*client_ip_string = static_cast<char*>(gpr_malloc(32));
for (size_t i = 0; i < 16; ++i) {
sprintf(*client_ip_string + i, "%02x",
addr6->sin6_addr.__in6_u.__u6_addr8[i]);
}
*size = 32;
} else {
GPR_UNREACHABLE_CODE();
}
}
/* Constructor for channel_data */
static grpc_error* init_channel_elem(grpc_channel_element* elem,
grpc_channel_element_args* args) {
GPR_ASSERT(!args->is_last);
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
chand->id = (intptr_t)args->channel_stack;
void ServerLoadReportingCallData::StoreClientIpAndLrToken(const char* lr_token,
size_t lr_token_len) {
char* client_ip;
size_t client_ip_len;
GetCensusSafeClientIpString(&client_ip, &client_ip_len);
client_ip_and_lr_token_len_ =
kLengthPrefixSize + client_ip_len + lr_token_len;
client_ip_and_lr_token_ = static_cast<char*>(
gpr_zalloc(client_ip_and_lr_token_len_ * sizeof(char)));
char* cur_pos = client_ip_and_lr_token_;
// Store the IP length prefix.
if (client_ip_len == 0) {
strncpy(cur_pos, kEmptyAddressLengthString, kLengthPrefixSize);
} else if (client_ip_len == 8) {
strncpy(cur_pos, kEncodedIpv4AddressLengthString, kLengthPrefixSize);
} else if (client_ip_len == 32) {
strncpy(cur_pos, kEncodedIpv6AddressLengthString, kLengthPrefixSize);
} else {
GPR_UNREACHABLE_CODE();
}
cur_pos += kLengthPrefixSize;
// Store the IP.
if (client_ip_len != 0) {
strncpy(cur_pos, client_ip, client_ip_len);
}
gpr_free(client_ip);
cur_pos += client_ip_len;
// Store the LR token.
if (lr_token_len != 0) {
strncpy(cur_pos, lr_token, lr_token_len);
}
GPR_ASSERT(cur_pos + lr_token_len - client_ip_and_lr_token_ ==
client_ip_and_lr_token_len_);
}
/* TODO(dgq): do something with the data
grpc_load_reporting_call_data lr_call_data = {GRPC_LR_POINT_CHANNEL_CREATION,
(intptr_t)chand,
0,
NULL,
NULL,
NULL,
NULL};
*/
grpc_filtered_mdelem ServerLoadReportingCallData::RecvInitialMetadataFilter(
void* user_data, grpc_mdelem md) {
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
ServerLoadReportingCallData* calld =
reinterpret_cast<ServerLoadReportingCallData*>(elem->call_data);
if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_PATH)) {
calld->service_method_ = grpc_slice_ref_internal(GRPC_MDVALUE(md));
} else if (calld->target_host_ == nullptr &&
grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_AUTHORITY)) {
grpc_slice target_host_slice = GRPC_MDVALUE(md);
calld->target_host_len_ = GRPC_SLICE_LENGTH(target_host_slice);
calld->target_host_ =
reinterpret_cast<char*>(gpr_zalloc(calld->target_host_len_));
for (size_t i = 0; i < calld->target_host_len_; ++i) {
calld->target_host_[i] = static_cast<char>(
tolower(GRPC_SLICE_START_PTR(target_host_slice)[i]));
}
} else if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_LB_TOKEN)) {
if (calld->client_ip_and_lr_token_ == nullptr) {
calld->StoreClientIpAndLrToken(
reinterpret_cast<const char*> GRPC_SLICE_START_PTR(GRPC_MDVALUE(md)),
GRPC_SLICE_LENGTH(GRPC_MDVALUE(md)));
}
return GRPC_FILTERED_REMOVE();
}
return GRPC_FILTERED_MDELEM(md);
}
return GRPC_ERROR_NONE;
void ServerLoadReportingCallData::RecvInitialMetadataReady(void* arg,
grpc_error* err) {
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(arg);
ServerLoadReportingCallData* calld =
reinterpret_cast<ServerLoadReportingCallData*>(elem->call_data);
ServerLoadReportingChannelData* chand =
reinterpret_cast<ServerLoadReportingChannelData*>(elem->channel_data);
if (err == GRPC_ERROR_NONE) {
GRPC_LOG_IF_ERROR(
"server_load_reporting_filter",
grpc_metadata_batch_filter(calld->recv_initial_metadata_->batch(),
RecvInitialMetadataFilter, elem,
"recv_initial_metadata filtering error"));
// If the LB token was not found in the recv_initial_metadata, only the
// client IP part will be recorded (with an empty LB token).
if (calld->client_ip_and_lr_token_ == nullptr) {
calld->StoreClientIpAndLrToken(nullptr, 0);
}
opencensus::stats::Record(
{{::grpc::load_reporter::MeasureStartCount(), 1}},
{{::grpc::load_reporter::TagKeyToken(),
{calld->client_ip_and_lr_token_, calld->client_ip_and_lr_token_len_}},
{::grpc::load_reporter::TagKeyHost(),
{calld->target_host_, calld->target_host_len_}},
{::grpc::load_reporter::TagKeyUserId(),
{chand->peer_identity(), chand->peer_identity_len()}}});
}
GRPC_CLOSURE_RUN(calld->original_recv_initial_metadata_ready_,
GRPC_ERROR_REF(err));
}
/* Destructor for channel data */
static void destroy_channel_elem(grpc_channel_element* elem) {
/* TODO(dgq): do something with the data
channel_data *chand = elem->channel_data;
grpc_load_reporting_call_data lr_call_data = {
GRPC_LR_POINT_CHANNEL_DESTRUCTION,
(intptr_t)chand->id,
0,
NULL,
NULL,
NULL,
NULL};
*/
grpc_error* ServerLoadReportingCallData::Init(
grpc_call_element* elem, const grpc_call_element_args* args) {
service_method_ = grpc_empty_slice();
GRPC_CLOSURE_INIT(&recv_initial_metadata_ready_, RecvInitialMetadataReady,
elem, grpc_schedule_on_exec_ctx);
return GRPC_ERROR_NONE;
}
static grpc_filtered_mdelem lr_trailing_md_filter(void* user_data,
grpc_mdelem md) {
grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
grpc_filtered_mdelem ServerLoadReportingCallData::SendTrailingMetadataFilter(
void* user_data, grpc_mdelem md) {
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
ServerLoadReportingCallData* calld =
reinterpret_cast<ServerLoadReportingCallData*>(elem->call_data);
ServerLoadReportingChannelData* chand =
reinterpret_cast<ServerLoadReportingChannelData*>(elem->channel_data);
// TODO(juanlishen): GRPC_MDSTR_LB_COST_BIN meaning?
if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_LB_COST_BIN)) {
calld->trailing_md_string = GRPC_MDVALUE(md);
const grpc_slice value = GRPC_MDVALUE(md);
const size_t cost_entry_size = GRPC_SLICE_LENGTH(value);
if (cost_entry_size < sizeof(double)) {
gpr_log(GPR_ERROR,
"Cost metadata value too small (%zu bytes) to hold valid data. "
"Ignoring.",
cost_entry_size);
return GRPC_FILTERED_REMOVE();
}
const double* cost_entry_ptr =
reinterpret_cast<const double*>(GRPC_SLICE_START_PTR(value));
double cost_value = *cost_entry_ptr++;
const char* cost_name = reinterpret_cast<const char*>(cost_entry_ptr);
const size_t cost_name_len = cost_entry_size - sizeof(double);
opencensus::stats::Record(
{{::grpc::load_reporter::MeasureOtherCallMetric(), cost_value}},
{{::grpc::load_reporter::TagKeyToken(),
{calld->client_ip_and_lr_token_, calld->client_ip_and_lr_token_len_}},
{::grpc::load_reporter::TagKeyHost(),
{calld->target_host_, calld->target_host_len_}},
{::grpc::load_reporter::TagKeyUserId(),
{chand->peer_identity(), chand->peer_identity_len()}},
{::grpc::load_reporter::TagKeyMetricName(),
{cost_name, cost_name_len}}});
return GRPC_FILTERED_REMOVE();
}
return GRPC_FILTERED_MDELEM(md);
}
static void lr_start_transport_stream_op_batch(
grpc_call_element* elem, grpc_transport_stream_op_batch* op) {
GPR_TIMER_SCOPE("lr_start_transport_stream_op_batch", 0);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (op->recv_initial_metadata) {
/* substitute our callback for the higher callback */
calld->recv_initial_metadata =
op->payload->recv_initial_metadata.recv_initial_metadata;
calld->ops_recv_initial_metadata_ready =
op->payload->recv_initial_metadata.recv_initial_metadata_ready;
op->payload->recv_initial_metadata.recv_initial_metadata_ready =
&calld->on_initial_md_ready;
} else if (op->send_trailing_metadata) {
GRPC_LOG_IF_ERROR(
"grpc_metadata_batch_filter",
grpc_metadata_batch_filter(
op->payload->send_trailing_metadata.send_trailing_metadata,
lr_trailing_md_filter, elem,
"LR trailing metadata filtering error"));
const char* ServerLoadReportingCallData::GetStatusTagForStatus(
grpc_status_code status) {
switch (status) {
case GRPC_STATUS_OK:
return ::grpc::load_reporter::kCallStatusOk;
case GRPC_STATUS_UNKNOWN:
case GRPC_STATUS_DEADLINE_EXCEEDED:
case GRPC_STATUS_UNIMPLEMENTED:
case GRPC_STATUS_INTERNAL:
case GRPC_STATUS_UNAVAILABLE:
case GRPC_STATUS_DATA_LOSS:
return ::grpc::load_reporter::kCallStatusServerError;
default:
return ::grpc::load_reporter::kCallStatusClientError;
}
grpc_call_next_op(elem, op);
}
const grpc_channel_filter grpc_server_load_reporting_filter = {
lr_start_transport_stream_op_batch,
grpc_channel_next_op,
sizeof(call_data),
init_call_elem,
grpc_call_stack_ignore_set_pollset_or_pollset_set,
destroy_call_elem,
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
grpc_channel_next_get_info,
"load_reporting"};
} // namespace grpc

@ -21,10 +21,105 @@
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/load_reporting/server_load_reporting_plugin.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/cpp/common/channel_filter.h"
extern const grpc_channel_filter grpc_server_load_reporting_filter;
namespace grpc {
class ServerLoadReportingChannelData : public ChannelData {
public:
grpc_error* Init(grpc_channel_element* elem,
grpc_channel_element_args* args) override;
// Getters.
const char* peer_identity() { return peer_identity_; }
size_t peer_identity_len() { return peer_identity_len_; }
private:
// The peer's authenticated identity.
char* peer_identity_ = nullptr;
size_t peer_identity_len_ = 0;
};
class ServerLoadReportingCallData : public CallData {
public:
grpc_error* Init(grpc_call_element* elem,
const grpc_call_element_args* args) override;
void Destroy(grpc_call_element* elem, const grpc_call_final_info* final_info,
grpc_closure* then_call_closure) override;
void StartTransportStreamOpBatch(grpc_call_element* elem,
TransportStreamOpBatch* op) override;
private:
// From the peer_string_ in calld, extracts the client IP string (owned by
// caller), e.g., "01020a0b". Upon failure, set the output pointer to null and
// size to zero.
void GetCensusSafeClientIpString(char** client_ip_string, size_t* size);
// Concatenates the client IP address and the load reporting token, then
// stores the result into the call data.
void StoreClientIpAndLrToken(const char* lr_token, size_t lr_token_len);
// This matches the classification of the status codes in
// googleapis/google/rpc/code.proto.
static const char* GetStatusTagForStatus(grpc_status_code status);
// Records the call start.
static void RecvInitialMetadataReady(void* arg, grpc_error* err);
// From the initial metadata, extracts the service_method_, target_host_, and
// client_ip_and_lr_token_.
static grpc_filtered_mdelem RecvInitialMetadataFilter(void* user_data,
grpc_mdelem md);
// Records the other call metrics.
static grpc_filtered_mdelem SendTrailingMetadataFilter(void* user_data,
grpc_mdelem md);
// The peer string (a member of the recv_initial_metadata op). Note that
// gpr_atm itself is a pointer type here, making "peer_string_" effectively a
// double pointer.
const gpr_atm* peer_string_;
// The received initial metadata (a member of the recv_initial_metadata op).
// When it is ready, we will extract some data from it via
// recv_initial_metadata_ready_ closure, before the original
// recv_initial_metadata_ready closure,
MetadataBatch* recv_initial_metadata_;
// The original recv_initial_metadata closure, which is wrapped by our own
// closure (recv_initial_metadata_ready_) to capture the incoming initial
// metadata.
grpc_closure* original_recv_initial_metadata_ready_;
// The closure that wraps the original closure. Scheduled when
// recv_initial_metadata_ is ready.
grpc_closure recv_initial_metadata_ready_;
// Corresponds to the :path header.
grpc_slice service_method_;
// The backend host that the client thinks it's talking to. This may be
// different from the actual backend in the case of, for example,
// load-balanced targets. We store a copy of the metadata slice in order to
// lowercase it. */
char* target_host_;
size_t target_host_len_;
// The client IP address (including a length prefix) and the load reporting
// token.
char* client_ip_and_lr_token_;
size_t client_ip_and_lr_token_len_;
static constexpr char kEncodedIpv4AddressLengthString[] = "08";
static constexpr char kEncodedIpv6AddressLengthString[] = "32";
static constexpr char kEmptyAddressLengthString[] = "00";
static constexpr size_t kLengthPrefixSize = 2;
};
} // namespace grpc
#endif /* GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_SERVER_LOAD_REPORTING_FILTER_H \
*/

@ -1,71 +0,0 @@
/*
*
* Copyright 2016 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 <limits.h>
#include <string.h>
#include <grpc/load_reporting.h>
#include <grpc/support/alloc.h>
#include <grpc/support/sync.h>
#include "src/core/ext/filters/load_reporting/server_load_reporting_filter.h"
#include "src/core/ext/filters/load_reporting/server_load_reporting_plugin.h"
#include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/channel_init.h"
static bool is_load_reporting_enabled(const grpc_channel_args* a) {
return grpc_channel_arg_get_bool(
grpc_channel_args_find(a, GRPC_ARG_ENABLE_LOAD_REPORTING), false);
}
static bool maybe_add_server_load_reporting_filter(
grpc_channel_stack_builder* builder, void* arg) {
const grpc_channel_args* args =
grpc_channel_stack_builder_get_channel_arguments(builder);
const grpc_channel_filter* filter =
static_cast<const grpc_channel_filter*>(arg);
grpc_channel_stack_builder_iterator* it =
grpc_channel_stack_builder_iterator_find(builder, filter->name);
const bool already_has_load_reporting_filter =
!grpc_channel_stack_builder_iterator_is_end(it);
grpc_channel_stack_builder_iterator_destroy(it);
if (is_load_reporting_enabled(args) && !already_has_load_reporting_filter) {
return grpc_channel_stack_builder_prepend_filter(builder, filter, nullptr,
nullptr);
}
return true;
}
grpc_arg grpc_load_reporting_enable_arg() {
return grpc_channel_arg_integer_create((char*)GRPC_ARG_ENABLE_LOAD_REPORTING,
1);
}
/* Plugin registration */
void grpc_server_load_reporting_plugin_init(void) {
grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
maybe_add_server_load_reporting_filter,
(void*)&grpc_server_load_reporting_filter);
}
void grpc_server_load_reporting_plugin_shutdown() {}

@ -1,61 +0,0 @@
/*
*
* Copyright 2016 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_LOAD_REPORTING_SERVER_LOAD_REPORTING_PLUGIN_H
#define GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_SERVER_LOAD_REPORTING_PLUGIN_H
#include <grpc/support/port_platform.h>
#include <grpc/impl/codegen/grpc_types.h>
#include "src/core/lib/channel/channel_stack.h"
/** Identifiers for the invocation point of the users LR callback */
typedef enum grpc_load_reporting_source {
GRPC_LR_POINT_UNKNOWN = 0,
GRPC_LR_POINT_CHANNEL_CREATION,
GRPC_LR_POINT_CHANNEL_DESTRUCTION,
GRPC_LR_POINT_CALL_CREATION,
GRPC_LR_POINT_CALL_DESTRUCTION
} grpc_load_reporting_source;
/** Call information to be passed to the provided LR callback. */
typedef struct grpc_load_reporting_call_data {
const grpc_load_reporting_source source; /**< point of last data update. */
/** Unique identifier for the channel associated with the data */
intptr_t channel_id;
/** Unique identifier for the call associated with the data. If the call
* hasn't been created yet, it'll have a value of zero. */
intptr_t call_id;
/** Only valid when \a source is \a GRPC_LR_POINT_CALL_DESTRUCTION, that is,
* once the call has completed */
const grpc_call_final_info* final_info;
const char* initial_md_string; /**< value string for LR's initial md key */
const char* trailing_md_string; /**< value string for LR's trailing md key */
const char* method_name; /**< Corresponds to :path header */
} grpc_load_reporting_call_data;
/** Return a \a grpc_arg enabling load reporting */
grpc_arg grpc_load_reporting_enable_arg();
#endif /* GRPC_CORE_EXT_FILTERS_LOAD_REPORTING_SERVER_LOAD_REPORTING_PLUGIN_H \
*/

@ -139,22 +139,27 @@ static bool update_list(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
static void report_stall(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
const char* staller) {
gpr_log(
GPR_DEBUG,
"%s:%p stream %d stalled by %s [fc:pending=%" PRIdPTR
":pending-compressed=%" PRIdPTR ":flowed=%" PRId64
":peer_initwin=%d:t_win=%" PRId64 ":s_win=%d:s_delta=%" PRId64 "]",
t->peer_string, t, s->id, staller, s->flow_controlled_buffer.length,
s->compressed_data_buffer.length, s->flow_controlled_bytes_flowed,
t->settings[GRPC_ACKED_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
t->flow_control->remote_window(),
static_cast<uint32_t> GPR_MAX(
0,
s->flow_control->remote_window_delta() +
(int64_t)t->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]),
s->flow_control->remote_window_delta());
if (grpc_flowctl_trace.enabled()) {
gpr_log(
GPR_DEBUG,
"%s:%p stream %d moved to stalled list by %s. This is FULLY expected "
"to happen in a healthy program that is not seeing flow control stalls."
" However, if you know that there are unwanted stalls, here is some "
"helpful data: [fc:pending=%" PRIdPTR ":pending-compressed=%" PRIdPTR
":flowed=%" PRId64 ":peer_initwin=%d:t_win=%" PRId64
":s_win=%d:s_delta=%" PRId64 "]",
t->peer_string, t, s->id, staller, s->flow_controlled_buffer.length,
s->compressed_data_buffer.length, s->flow_controlled_bytes_flowed,
t->settings[GRPC_ACKED_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
t->flow_control->remote_window(),
static_cast<uint32_t> GPR_MAX(
0,
s->flow_control->remote_window_delta() +
(int64_t)t->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]),
s->flow_control->remote_window_delta());
}
}
static bool stream_ref_if_not_destroyed(gpr_refcount* r) {

@ -28,7 +28,6 @@
#include <stdlib.h>
#include <string.h>
#include "src/core/lib/channel/channelz_registry.h"
#include "src/core/lib/channel/status_util.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
@ -40,16 +39,17 @@
#include "src/core/lib/transport/error_utils.h"
namespace grpc_core {
namespace channelz {
ChannelTrace::TraceEvent::TraceEvent(
Severity severity, grpc_slice data,
RefCountedPtr<ChannelTrace> referenced_tracer, ReferencedType type)
RefCountedPtr<ChannelNode> referenced_channel, ReferencedType type)
: severity_(severity),
data_(data),
timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(),
GPR_CLOCK_REALTIME)),
next_(nullptr),
referenced_tracer_(std::move(referenced_tracer)),
referenced_channel_(std::move(referenced_channel)),
referenced_type_(type) {}
ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data)
@ -62,15 +62,13 @@ ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data)
ChannelTrace::TraceEvent::~TraceEvent() { grpc_slice_unref_internal(data_); }
ChannelTrace::ChannelTrace(size_t max_events)
: channel_uuid_(-1),
num_events_logged_(0),
: num_events_logged_(0),
list_size_(0),
max_list_size_(max_events),
head_trace_(nullptr),
tail_trace_(nullptr) {
if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0
gpr_mu_init(&tracer_mu_);
channel_uuid_ = ChannelzRegistry::Register(this);
time_created_ = grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(),
GPR_CLOCK_REALTIME);
}
@ -83,12 +81,9 @@ ChannelTrace::~ChannelTrace() {
it = it->next();
Delete<TraceEvent>(to_free);
}
ChannelzRegistry::Unregister(channel_uuid_);
gpr_mu_destroy(&tracer_mu_);
}
intptr_t ChannelTrace::GetUuid() const { return channel_uuid_; }
void ChannelTrace::AddTraceEventHelper(TraceEvent* new_trace_event) {
++num_events_logged_;
// first event case
@ -117,20 +112,21 @@ void ChannelTrace::AddTraceEvent(Severity severity, grpc_slice data) {
void ChannelTrace::AddTraceEventReferencingChannel(
Severity severity, grpc_slice data,
RefCountedPtr<ChannelTrace> referenced_tracer) {
RefCountedPtr<ChannelNode> referenced_channel) {
if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0
// create and fill up the new event
AddTraceEventHelper(
New<TraceEvent>(severity, data, std::move(referenced_tracer), Channel));
AddTraceEventHelper(New<TraceEvent>(
severity, data, std::move(referenced_channel), ReferencedType::Channel));
}
void ChannelTrace::AddTraceEventReferencingSubchannel(
Severity severity, grpc_slice data,
RefCountedPtr<ChannelTrace> referenced_tracer) {
RefCountedPtr<ChannelNode> referenced_subchannel) {
if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0
// create and fill up the new event
AddTraceEventHelper(New<TraceEvent>(
severity, data, std::move(referenced_tracer), Subchannel));
AddTraceEventHelper(New<TraceEvent>(severity, data,
std::move(referenced_subchannel),
ReferencedType::Subchannel));
}
namespace {
@ -193,22 +189,24 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const {
json_iterator =
grpc_json_create_child(json_iterator, json, "timestamp",
fmt_time(timestamp_), GRPC_JSON_STRING, true);
if (referenced_tracer_ != nullptr) {
if (referenced_channel_ != nullptr) {
char* uuid_str;
gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_tracer_->channel_uuid_);
gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_channel_->channel_uuid());
grpc_json* child_ref = grpc_json_create_child(
json_iterator, json,
(referenced_type_ == Channel) ? "channelRef" : "subchannelRef", nullptr,
GRPC_JSON_OBJECT, false);
(referenced_type_ == ReferencedType::Channel) ? "channelRef"
: "subchannelRef",
nullptr, GRPC_JSON_OBJECT, false);
json_iterator = grpc_json_create_child(
nullptr, child_ref,
(referenced_type_ == Channel) ? "channelId" : "subchannelId", uuid_str,
GRPC_JSON_STRING, true);
(referenced_type_ == ReferencedType::Channel) ? "channelId"
: "subchannelId",
uuid_str, GRPC_JSON_STRING, true);
json_iterator = child_ref;
}
}
char* ChannelTrace::RenderTrace() const {
grpc_json* ChannelTrace::RenderJSON() const {
if (!max_list_size_)
return nullptr; // tracing is disabled if max_events == 0
grpc_json* json = grpc_json_create(GRPC_JSON_OBJECT);
@ -219,7 +217,7 @@ char* ChannelTrace::RenderTrace() const {
grpc_json_create_child(json_iterator, json, "numEventsLogged",
num_events_logged_str, GRPC_JSON_STRING, true);
json_iterator =
grpc_json_create_child(json_iterator, json, "creationTime",
grpc_json_create_child(json_iterator, json, "creationTimestamp",
fmt_time(time_created_), GRPC_JSON_STRING, true);
grpc_json* events = grpc_json_create_child(json_iterator, json, "events",
nullptr, GRPC_JSON_ARRAY, false);
@ -231,9 +229,8 @@ char* ChannelTrace::RenderTrace() const {
it->RenderTraceEvent(json_iterator);
it = it->next();
}
char* json_str = grpc_json_dump_to_string(json, 0);
grpc_json_destroy(json);
return json_str;
return json;
}
} // namespace channelz
} // namespace grpc_core

@ -28,18 +28,18 @@
#include "src/core/lib/json/json.h"
namespace grpc_core {
namespace channelz {
class ChannelNode;
// Object used to hold live data for a channel. This data is exposed via the
// channelz service:
// https://github.com/grpc/proposal/blob/master/A14-channelz.md
class ChannelTrace : public RefCounted<ChannelTrace> {
class ChannelTrace {
public:
ChannelTrace(size_t max_events);
~ChannelTrace();
// returns the tracer's uuid
intptr_t GetUuid() const;
enum Severity {
Unset = 0, // never to be used
Info, // we start at 1 to avoid using proto default values
@ -59,34 +59,30 @@ class ChannelTrace : public RefCounted<ChannelTrace> {
// created a new subchannel, then it would record that with a TraceEvent
// referencing the new subchannel.
//
// TODO(ncteisen): Once channelz is implemented, the events should reference
// the overall channelz object, not just the ChannelTrace object.
// TODO(ncteisen): as this call is used more and more throughout the gRPC
// stack, determine if it makes more sense to accept a char* instead of a
// slice.
void AddTraceEventReferencingChannel(
Severity severity, grpc_slice data,
RefCountedPtr<ChannelTrace> referenced_tracer);
RefCountedPtr<ChannelNode> referenced_channel);
void AddTraceEventReferencingSubchannel(
Severity severity, grpc_slice data,
RefCountedPtr<ChannelTrace> referenced_tracer);
RefCountedPtr<ChannelNode> referenced_subchannel);
// Returns the tracing data rendered as a grpc json string.
// The string is owned by the caller and must be freed.
char* RenderTrace() const;
// Creates and returns the raw grpc_json object, so a parent channelz
// object may incorporate the json before rendering.
grpc_json* RenderJSON() const;
private:
// Types of objects that can be references by trace events.
enum ReferencedType { Channel, Subchannel };
enum class ReferencedType { Channel, Subchannel };
// Private class to encapsulate all the data and bookkeeping needed for a
// a trace event.
class TraceEvent {
public:
// Constructor for a TraceEvent that references a different channel.
// TODO(ncteisen): once channelz is implemented, this should reference the
// overall channelz object, not just the ChannelTrace object
TraceEvent(Severity severity, grpc_slice data,
RefCountedPtr<ChannelTrace> referenced_tracer,
RefCountedPtr<ChannelNode> referenced_channel,
ReferencedType type);
// Constructor for a TraceEvent that does not reverence a different
@ -109,7 +105,7 @@ class ChannelTrace : public RefCounted<ChannelTrace> {
gpr_timespec timestamp_;
TraceEvent* next_;
// the tracer object for the (sub)channel that this trace event refers to.
RefCountedPtr<ChannelTrace> referenced_tracer_;
RefCountedPtr<ChannelNode> referenced_channel_;
// the type that the referenced tracer points to. Unused if this trace
// does not point to any channel or subchannel
ReferencedType referenced_type_;
@ -119,7 +115,6 @@ class ChannelTrace : public RefCounted<ChannelTrace> {
void AddTraceEventHelper(TraceEvent* new_trace_event);
gpr_mu tracer_mu_;
intptr_t channel_uuid_;
uint64_t num_events_logged_;
size_t list_size_;
size_t max_list_size_;
@ -128,6 +123,7 @@ class ChannelTrace : public RefCounted<ChannelTrace> {
gpr_timespec time_created_;
};
} // namespace channelz
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_H */

@ -0,0 +1,188 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <grpc/impl/codegen/port_platform.h>
#include "src/core/lib/channel/channelz.h"
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "src/core/lib/channel/channelz_registry.h"
#include "src/core/lib/channel/status_util.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/error_utils.h"
namespace grpc_core {
namespace channelz {
namespace {
// TODO(ncteisen): move this function to a common helper location.
//
// returns an allocated string that represents tm according to RFC-3339, and,
// more specifically, follows:
// https://developers.google.com/protocol-buffers/docs/proto3#json
//
// "Uses RFC 3339, where generated output will always be Z-normalized and uses
// 0, 3, 6 or 9 fractional digits."
char* fmt_time(gpr_timespec tm) {
char time_buffer[35];
char ns_buffer[11]; // '.' + 9 digits of precision
struct tm* tm_info = localtime((const time_t*)&tm.tv_sec);
strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%H:%M:%S", tm_info);
snprintf(ns_buffer, 11, ".%09d", tm.tv_nsec);
// This loop trims off trailing zeros by inserting a null character that the
// right point. We iterate in chunks of three because we want 0, 3, 6, or 9
// fractional digits.
for (int i = 7; i >= 1; i -= 3) {
if (ns_buffer[i] == '0' && ns_buffer[i + 1] == '0' &&
ns_buffer[i + 2] == '0') {
ns_buffer[i] = '\0';
// Edge case in which all fractional digits were 0.
if (i == 1) {
ns_buffer[0] = '\0';
}
} else {
break;
}
}
char* full_time_str;
gpr_asprintf(&full_time_str, "%s%sZ", time_buffer, ns_buffer);
return full_time_str;
}
// TODO(ncteisen); move this to json library
grpc_json* add_num_str(grpc_json* parent, grpc_json* it, const char* name,
int64_t num) {
char* num_str;
gpr_asprintf(&num_str, "%" PRId64, num);
return grpc_json_create_child(it, parent, name, num_str, GRPC_JSON_STRING,
true);
}
} // namespace
ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes)
: channel_(channel), target_(nullptr), channel_uuid_(-1) {
trace_.Init(channel_tracer_max_nodes);
target_ = UniquePtr<char>(grpc_channel_get_target(channel_));
channel_uuid_ = ChannelzRegistry::Register(this);
gpr_atm_no_barrier_store(&last_call_started_millis_,
(gpr_atm)ExecCtx::Get()->Now());
}
ChannelNode::~ChannelNode() {
trace_.Destroy();
ChannelzRegistry::Unregister(channel_uuid_);
}
void ChannelNode::RecordCallStarted() {
gpr_atm_no_barrier_fetch_add(&calls_started_, (gpr_atm)1);
gpr_atm_no_barrier_store(&last_call_started_millis_,
(gpr_atm)ExecCtx::Get()->Now());
}
grpc_connectivity_state ChannelNode::GetConnectivityState() {
if (channel_ == nullptr) {
return GRPC_CHANNEL_SHUTDOWN;
} else {
// TODO(ncteisen): re-enable this once we have cleaned up all of the
// internal dependency issues.
// return grpc_channel_check_connectivity_state(channel_, false);
return GRPC_CHANNEL_IDLE;
}
}
char* ChannelNode::RenderJSON() {
// We need to track these three json objects to build our object
grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json* json = top_level_json;
grpc_json* json_iterator = nullptr;
// create and fill the ref child
json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr,
GRPC_JSON_OBJECT, false);
json = json_iterator;
json_iterator = nullptr;
json_iterator = add_num_str(json, json_iterator, "channelId", channel_uuid_);
// reset json iterators to top level object
json = top_level_json;
json_iterator = nullptr;
// create and fill the data child.
grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr,
GRPC_JSON_OBJECT, false);
json = data;
json_iterator = nullptr;
// create and fill the connectivity state child.
grpc_connectivity_state connectivity_state = GetConnectivityState();
json_iterator = grpc_json_create_child(json_iterator, json, "state", nullptr,
GRPC_JSON_OBJECT, false);
json = json_iterator;
grpc_json_create_child(nullptr, json, "state",
grpc_connectivity_state_name(connectivity_state),
GRPC_JSON_STRING, false);
// reset the parent to be the data object.
json = data;
json_iterator = grpc_json_create_child(
json_iterator, json, "target", target_.get(), GRPC_JSON_STRING, false);
// fill in the channel trace if applicable
grpc_json* trace = trace_->RenderJSON();
if (trace != nullptr) {
// we manuall link up and fill the child since it was created for us in
// ChannelTrace::RenderJSON
json_iterator = grpc_json_link_child(json, trace, json_iterator);
trace->parent = json;
trace->value = nullptr;
trace->key = "trace";
trace->owns_value = false;
}
// reset the parent to be the data object.
json = data;
json_iterator = nullptr;
// We use -1 as sentinel values since proto default value for integers is
// zero, and the confuses the parser into thinking the value weren't present
json_iterator =
add_num_str(json, json_iterator, "callsStarted", calls_started_);
json_iterator =
add_num_str(json, json_iterator, "callsSucceeded", calls_succeeded_);
json_iterator =
add_num_str(json, json_iterator, "callsFailed", calls_failed_);
gpr_timespec ts =
grpc_millis_to_timespec(last_call_started_millis_, GPR_CLOCK_REALTIME);
json_iterator =
grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp",
fmt_time(ts), GRPC_JSON_STRING, true);
// render and return the over json object
char* json_str = grpc_json_dump_to_string(top_level_json, 0);
grpc_json_destroy(top_level_json);
return json_str;
}
} // namespace channelz
} // namespace grpc_core

@ -0,0 +1,85 @@
/*
*
* 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_LIB_CHANNEL_CHANNELZ_H
#define GRPC_CORE_LIB_CHANNEL_CHANNELZ_H
#include <grpc/impl/codegen/port_platform.h>
#include <grpc/grpc.h>
#include "src/core/lib/channel/channel_trace.h"
#include "src/core/lib/gprpp/manual_constructor.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/json/json.h"
namespace grpc_core {
namespace channelz {
namespace testing {
class ChannelNodePeer;
}
class ChannelNode : public RefCounted<ChannelNode> {
public:
ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes);
~ChannelNode();
void RecordCallStarted();
void RecordCallFailed() {
gpr_atm_no_barrier_fetch_add(&calls_failed_, (gpr_atm(1)));
}
void RecordCallSucceeded() {
gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1)));
}
char* RenderJSON();
ChannelTrace* trace() { return trace_.get(); }
void set_channel_destroyed() {
GPR_ASSERT(channel_ != nullptr);
channel_ = nullptr;
}
intptr_t channel_uuid() { return channel_uuid_; }
private:
// testing peer friend.
friend class testing::ChannelNodePeer;
// helper for getting connectivity state.
grpc_connectivity_state GetConnectivityState();
grpc_channel* channel_ = nullptr;
UniquePtr<char> target_;
gpr_atm calls_started_ = 0;
gpr_atm calls_succeeded_ = 0;
gpr_atm calls_failed_ = 0;
gpr_atm last_call_started_millis_ = 0;
intptr_t channel_uuid_;
ManualConstructor<ChannelTrace> trace_;
};
} // namespace channelz
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNELZ_H */

@ -105,7 +105,7 @@ class ThreadInternalsPosix
GPR_ASSERT(pthread_attr_destroy(&attr) == 0);
if (!success) {
if (!(*success)) {
/* don't use gpr_free, as this was allocated using malloc (see above) */
free(info);
grpc_core::Fork::DecThreadCount();

@ -104,8 +104,10 @@ struct pollable {
int epfd;
grpc_wakeup_fd wakeup;
// only for type fd... one ref to the owner fd
grpc_fd* owner_fd;
// The following are relevant only for type PO_FD
grpc_fd* owner_fd; // Set to the owner_fd if the type is PO_FD
gpr_mu owner_orphan_mu; // Synchronizes access to owner_orphaned field
bool owner_orphaned; // Is the owner fd orphaned
grpc_pollset_set* pollset_set;
pollable* next;
@ -338,21 +340,45 @@ static void ref_by(grpc_fd* fd, int n) {
GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0);
}
#ifndef NDEBUG
#define INVALIDATE_FD(fd) invalidate_fd(fd)
/* Since an fd is never really destroyed (i.e gpr_free() is not called), it is
* hard to cases where fd fields are accessed even after calling fd_destroy().
* The following invalidates fd fields to make catching such errors easier */
static void invalidate_fd(grpc_fd* fd) {
fd->fd = -1;
fd->salt = -1;
gpr_atm_no_barrier_store(&fd->refst, -1);
memset(&fd->orphan_mu, -1, sizeof(fd->orphan_mu));
memset(&fd->pollable_mu, -1, sizeof(fd->pollable_mu));
fd->pollable_obj = nullptr;
fd->on_done_closure = nullptr;
gpr_atm_no_barrier_store(&fd->read_notifier_pollset, 0);
memset(&fd->iomgr_object, -1, sizeof(fd->iomgr_object));
fd->track_err = false;
}
#else
#define INVALIDATE_FD(fd)
#endif
/* Uninitialize and add to the freelist */
static void fd_destroy(void* arg, grpc_error* error) {
grpc_fd* fd = static_cast<grpc_fd*>(arg);
/* Add the fd to the freelist */
grpc_iomgr_unregister_object(&fd->iomgr_object);
POLLABLE_UNREF(fd->pollable_obj, "fd_pollable");
gpr_mu_destroy(&fd->pollable_mu);
gpr_mu_destroy(&fd->orphan_mu);
gpr_mu_lock(&fd_freelist_mu);
fd->freelist_next = fd_freelist;
fd_freelist = fd;
fd->read_closure->DestroyEvent();
fd->write_closure->DestroyEvent();
fd->error_closure->DestroyEvent();
INVALIDATE_FD(fd);
/* Add the fd to the freelist */
gpr_mu_lock(&fd_freelist_mu);
fd->freelist_next = fd_freelist;
fd_freelist = fd;
gpr_mu_unlock(&fd_freelist_mu);
}
@ -408,20 +434,18 @@ static grpc_fd* fd_create(int fd, const char* name, bool track_err) {
new_fd->error_closure.Init();
}
gpr_mu_init(&new_fd->pollable_mu);
gpr_mu_init(&new_fd->orphan_mu);
new_fd->pollable_obj = nullptr;
gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1);
new_fd->fd = fd;
new_fd->track_err = track_err;
new_fd->salt = gpr_atm_no_barrier_fetch_add(&g_fd_salt, 1);
gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1);
gpr_mu_init(&new_fd->orphan_mu);
gpr_mu_init(&new_fd->pollable_mu);
new_fd->pollable_obj = nullptr;
new_fd->read_closure->InitEvent();
new_fd->write_closure->InitEvent();
new_fd->error_closure->InitEvent();
gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
new_fd->freelist_next = nullptr;
new_fd->on_done_closure = nullptr;
gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
char* fd_name;
gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
@ -432,6 +456,8 @@ static grpc_fd* fd_create(int fd, const char* name, bool track_err) {
}
#endif
gpr_free(fd_name);
new_fd->track_err = track_err;
return new_fd;
}
@ -446,6 +472,17 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd,
gpr_mu_lock(&fd->orphan_mu);
// Get the fd->pollable_obj and set the owner_orphaned on that pollable to
// true so that the pollable will no longer access its owner_fd field.
gpr_mu_lock(&fd->pollable_mu);
pollable* pollable_obj = fd->pollable_obj;
gpr_mu_unlock(&fd->pollable_mu);
if (pollable_obj) {
gpr_mu_lock(&pollable_obj->owner_orphan_mu);
pollable_obj->owner_orphaned = true;
}
fd->on_done_closure = on_done;
/* If release_fd is not NULL, we should be relinquishing control of the file
@ -467,6 +504,10 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd,
GRPC_CLOSURE_SCHED(fd->on_done_closure, GRPC_ERROR_NONE);
if (pollable_obj) {
gpr_mu_unlock(&pollable_obj->owner_orphan_mu);
}
gpr_mu_unlock(&fd->orphan_mu);
UNREF_BY(fd, 2, reason); /* Drop the reference */
@ -551,6 +592,8 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) {
gpr_mu_init(&(*p)->mu);
(*p)->epfd = epfd;
(*p)->owner_fd = nullptr;
gpr_mu_init(&(*p)->owner_orphan_mu);
(*p)->owner_orphaned = false;
(*p)->pollset_set = nullptr;
(*p)->next = (*p)->prev = *p;
(*p)->root_worker = nullptr;
@ -590,6 +633,7 @@ static void pollable_unref(pollable* p, int line, const char* reason) {
GRPC_FD_TRACE("pollable_unref: Closing epfd: %d", p->epfd);
close(p->epfd);
grpc_wakeup_fd_destroy(&p->wakeup);
gpr_mu_destroy(&p->owner_orphan_mu);
gpr_free(p);
}
}
@ -846,10 +890,15 @@ static void fd_become_writable(grpc_fd* fd) { fd->write_closure->SetReady(); }
static void fd_has_errors(grpc_fd* fd) { fd->error_closure->SetReady(); }
static grpc_error* fd_get_or_become_pollable(grpc_fd* fd, pollable** p) {
/* Get the pollable_obj attached to this fd. If none is attached, create a new
* pollable object (of type PO_FD), attach it to the fd and return it
*
* Note that if a pollable object is already attached to the fd, it may be of
* either PO_FD or PO_MULTI type */
static grpc_error* get_fd_pollable(grpc_fd* fd, pollable** p) {
gpr_mu_lock(&fd->pollable_mu);
grpc_error* error = GRPC_ERROR_NONE;
static const char* err_desc = "fd_get_or_become_pollable";
static const char* err_desc = "get_fd_pollable";
if (fd->pollable_obj == nullptr) {
if (append_error(&error, pollable_create(PO_FD, &fd->pollable_obj),
err_desc)) {
@ -1186,7 +1235,7 @@ static grpc_error* pollset_transition_pollable_from_empty_to_fd_locked(
}
append_error(&error, pollset_kick_all(pollset), err_desc);
POLLABLE_UNREF(pollset->active_pollable, "pollset");
append_error(&error, fd_get_or_become_pollable(fd, &pollset->active_pollable),
append_error(&error, get_fd_pollable(fd, &pollset->active_pollable),
err_desc);
return error;
}
@ -1230,9 +1279,8 @@ static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) {
error = pollset_transition_pollable_from_empty_to_fd_locked(pollset, fd);
break;
case PO_FD:
gpr_mu_lock(&po_at_start->owner_fd->orphan_mu);
if ((gpr_atm_no_barrier_load(&pollset->active_pollable->owner_fd->refst) &
1) == 0) {
gpr_mu_lock(&po_at_start->owner_orphan_mu);
if (po_at_start->owner_orphaned) {
error =
pollset_transition_pollable_from_empty_to_fd_locked(pollset, fd);
} else {
@ -1240,7 +1288,7 @@ static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) {
error =
pollset_transition_pollable_from_fd_to_multi_locked(pollset, fd);
}
gpr_mu_unlock(&po_at_start->owner_fd->orphan_mu);
gpr_mu_unlock(&po_at_start->owner_orphan_mu);
break;
case PO_MULTI:
error = pollable_add_fd(pollset->active_pollable, fd);
@ -1276,16 +1324,17 @@ static grpc_error* pollset_as_multipollable_locked(grpc_pollset* pollset,
append_error(&error, pollset_kick_all(pollset), err_desc);
break;
case PO_FD:
gpr_mu_lock(&po_at_start->owner_fd->orphan_mu);
if ((gpr_atm_no_barrier_load(&pollset->active_pollable->owner_fd->refst) &
1) == 0) {
gpr_mu_lock(&po_at_start->owner_orphan_mu);
if (po_at_start->owner_orphaned) {
// Unlock before Unref'ing the pollable
gpr_mu_unlock(&po_at_start->owner_orphan_mu);
POLLABLE_UNREF(pollset->active_pollable, "pollset");
error = pollable_create(PO_MULTI, &pollset->active_pollable);
} else {
error = pollset_transition_pollable_from_fd_to_multi_locked(pollset,
nullptr);
gpr_mu_unlock(&po_at_start->owner_orphan_mu);
}
gpr_mu_unlock(&po_at_start->owner_fd->orphan_mu);
break;
case PO_MULTI:
break;

@ -45,6 +45,9 @@ typedef struct grpc_combiner grpc_combiner;
/* The exec_ctx's thread is (potentially) owned by a call or channel: care
should be given to not delete said call/channel from this exec_ctx */
#define GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP 2
/* This exec ctx was initialized by an internal thread, and should not
be counted by fork handlers */
#define GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD 4
extern grpc_closure_scheduler* grpc_schedule_on_exec_ctx;
@ -93,7 +96,9 @@ class ExecCtx {
/** Parameterised Constructor */
ExecCtx(uintptr_t fl) : flags_(fl) {
grpc_core::Fork::IncExecCtxCount();
if (!(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags_)) {
grpc_core::Fork::IncExecCtxCount();
}
Set(this);
}
@ -102,7 +107,9 @@ class ExecCtx {
flags_ |= GRPC_EXEC_CTX_FLAG_IS_FINISHED;
Flush();
Set(last_exec_ctx_);
grpc_core::Fork::DecExecCtxCount();
if (!(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags_)) {
grpc_core::Fork::DecExecCtxCount();
}
}
/** Disallow copy and assignment operators */

@ -145,7 +145,7 @@ static void executor_thread(void* arg) {
thread_state* ts = static_cast<thread_state*>(arg);
gpr_tls_set(&g_this_thread_state, (intptr_t)ts);
grpc_core::ExecCtx exec_ctx(0);
grpc_core::ExecCtx exec_ctx(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD);
size_t subtract_depth = 0;
for (;;) {

@ -70,6 +70,8 @@ static size_t count_objects(void) {
return n;
}
size_t grpc_iomgr_count_objects_for_testing(void) { return count_objects(); }
static void dump_objects(const char* kind) {
grpc_iomgr_object* obj;
for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) {

@ -23,6 +23,8 @@
#include "src/core/lib/iomgr/port.h"
#include <stdlib.h>
/** Initializes the iomgr. */
void grpc_iomgr_init();
@ -33,4 +35,7 @@ void grpc_iomgr_start();
* exec_ctx. */
void grpc_iomgr_shutdown();
/* Exposed only for testing */
size_t grpc_iomgr_count_objects_for_testing();
#endif /* GRPC_CORE_LIB_IOMGR_IOMGR_H */

@ -23,12 +23,21 @@
#include <stddef.h>
// TODO(juanlishen): The following functions might be simple enough to implement
// ourselves, so that they don't cause any portability hassle.
/* A wrapper for htons on POSIX and Windows */
uint16_t grpc_htons(uint16_t hostshort);
/* A wrapper for ntohs on POSIX and WINDOWS */
uint16_t grpc_ntohs(uint16_t netshort);
/* A wrapper for htonl on POSIX and Windows */
uint32_t grpc_htonl(uint32_t hostlong);
/* A wrapper for ntohl on POSIX and WINDOWS */
uint32_t grpc_ntohl(uint32_t netlong);
/* A wrapper for inet_pton on POSIX and WINDOWS */
int grpc_inet_pton(int af, const char* src, void* dst);

@ -339,6 +339,10 @@ uint16_t grpc_htons(uint16_t hostshort) { return htons(hostshort); }
uint16_t grpc_ntohs(uint16_t netshort) { return ntohs(netshort); }
uint32_t grpc_htonl(uint32_t hostlong) { return htonl(hostlong); }
uint32_t grpc_ntohl(uint32_t netlong) { return ntohl(netlong); }
int grpc_inet_pton(int af, const char* src, void* dst) {
return inet_pton(af, src, dst);
}

@ -33,6 +33,10 @@ uint16_t grpc_htons(uint16_t hostshort) { return htons(hostshort); }
uint16_t grpc_ntohs(uint16_t netshort) { return ntohs(netshort); }
uint32_t grpc_htonl(uint32_t hostlong) { return htonl(hostlong); }
uint32_t grpc_ntohl(uint32_t netlong) { return ntohl(netlong); }
int grpc_inet_pton(int af, const char* src, void* dst) {
return inet_pton(af, src, dst);
}

@ -31,6 +31,10 @@ uint16_t grpc_htons(uint16_t hostshort) { return htons(hostshort); }
uint16_t grpc_ntohs(uint16_t netshort) { return ntohs(netshort); }
uint32_t grpc_htonl(uint32_t hostlong) { return htonl(hostlong); }
uint32_t grpc_ntohl(uint32_t netlong) { return ntohl(netlong); }
int grpc_inet_pton(int af, const char* src, void* dst) {
return inet_pton(af, src, dst);
}

@ -265,7 +265,7 @@ static void timer_thread_cleanup(completed_thread* ct) {
static void timer_thread(void* completed_thread_ptr) {
// this threads exec_ctx: we try to run things through to completion here
// since it's easy to spin up new threads
grpc_core::ExecCtx exec_ctx(0);
grpc_core::ExecCtx exec_ctx(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD);
timer_main_loop();
timer_thread_cleanup(static_cast<completed_thread*>(completed_thread_ptr));
@ -277,7 +277,6 @@ static void start_threads(void) {
g_threaded = true;
start_timer_thread_and_unlock();
} else {
g_threaded = false;
gpr_mu_unlock(&g_mu);
}
}

@ -21,6 +21,7 @@
#include <string.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/gpr/arena.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/surface/api_trace.h"
@ -99,10 +100,10 @@ void grpc_client_security_context_destroy(void* ctx) {
}
/* --- grpc_server_security_context --- */
grpc_server_security_context* grpc_server_security_context_create(void) {
grpc_server_security_context* grpc_server_security_context_create(
gpr_arena* arena) {
return static_cast<grpc_server_security_context*>(
gpr_zalloc(sizeof(grpc_server_security_context)));
gpr_arena_alloc(arena, sizeof(grpc_server_security_context)));
}
void grpc_server_security_context_destroy(void* ctx) {
@ -112,7 +113,6 @@ void grpc_server_security_context_destroy(void* ctx) {
if (c->extension.instance != nullptr && c->extension.destroy != nullptr) {
c->extension.destroy(c->extension.instance);
}
gpr_free(ctx);
}
/* --- grpc_auth_context --- */

@ -26,6 +26,8 @@
extern grpc_core::DebugOnlyTraceFlag grpc_trace_auth_context_refcount;
struct gpr_arena;
/* --- grpc_auth_context ---
High level authentication context object. Can optionally be chained. */
@ -101,7 +103,8 @@ typedef struct {
grpc_security_context_extension extension;
} grpc_server_security_context;
grpc_server_security_context* grpc_server_security_context_create(void);
grpc_server_security_context* grpc_server_security_context_create(
gpr_arena* arena);
void grpc_server_security_context_destroy(void* ctx);
/* --- Channel args for auth context --- */

@ -214,7 +214,7 @@ static grpc_error* init_call_elem(grpc_call_element* elem,
// Create server security context. Set its auth context from channel
// data and save it in the call context.
grpc_server_security_context* server_ctx =
grpc_server_security_context_create();
grpc_server_security_context_create(args->arena);
server_ctx->auth_context = grpc_auth_context_create(chand->auth_context);
calld->auth_context = server_ctx->auth_context;
if (args->context[GRPC_CONTEXT_SECURITY].value != nullptr) {

@ -489,6 +489,12 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args,
&call->pollent);
}
grpc_core::channelz::ChannelNode* channelz_channel =
grpc_channel_get_channelz_node(call->channel);
if (channelz_channel != nullptr) {
channelz_channel->RecordCallStarted();
}
grpc_slice_unref_internal(path);
return error;
@ -531,7 +537,6 @@ static void release_call(void* call, grpc_error* error) {
GRPC_CHANNEL_INTERNAL_UNREF(channel, "call");
}
static void set_status_value_directly(grpc_status_code status, void* dest);
static void destroy_call(void* call, grpc_error* error) {
GPR_TIMER_SCOPE("destroy_call", 0);
size_t i;
@ -1087,13 +1092,12 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b) {
if (b->idx.named.grpc_status != nullptr) {
grpc_status_code status_code =
grpc_get_status_code_from_metadata(b->idx.named.grpc_status->md);
grpc_error* error =
status_code == GRPC_STATUS_OK
? GRPC_ERROR_NONE
: grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Error received from peer"),
GRPC_ERROR_INT_GRPC_STATUS,
static_cast<intptr_t>(status_code));
grpc_error* error = GRPC_ERROR_NONE;
if (status_code != GRPC_STATUS_OK) {
error = grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error received from peer"),
GRPC_ERROR_INT_GRPC_STATUS, static_cast<intptr_t>(status_code));
}
if (b->idx.named.grpc_message != nullptr) {
error = grpc_error_set_str(
error, GRPC_ERROR_STR_GRPC_MESSAGE,
@ -1109,6 +1113,8 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b) {
publish_app_metadata(call, b, true);
}
gpr_arena* grpc_call_get_arena(grpc_call* call) { return call->arena; }
grpc_call_stack* grpc_call_get_call_stack(grpc_call* call) {
return CALL_STACK_FROM_CALL(call);
}
@ -1260,6 +1266,15 @@ static void post_batch_completion(batch_control* bctl) {
get_final_status(call, set_cancelled_value,
call->final_op.server.cancelled, nullptr, nullptr);
}
grpc_core::channelz::ChannelNode* channelz_channel =
grpc_channel_get_channelz_node(call->channel);
if (channelz_channel != nullptr) {
if (*call->final_op.client.status != GRPC_STATUS_OK) {
channelz_channel->RecordCallFailed();
} else {
channelz_channel->RecordCallSucceeded();
}
}
GRPC_ERROR_UNREF(error);
error = GRPC_ERROR_NONE;
}

@ -71,6 +71,8 @@ void grpc_call_internal_unref(grpc_call* call);
#define GRPC_CALL_INTERNAL_UNREF(call, reason) grpc_call_internal_unref(call)
#endif
gpr_arena* grpc_call_get_arena(grpc_call* call);
grpc_call_stack* grpc_call_get_call_stack(grpc_call* call);
grpc_call_error grpc_call_start_batch_and_execute(grpc_call* call,

@ -32,6 +32,7 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_trace.h"
#include "src/core/lib/channel/channelz.h"
#include "src/core/lib/debug/stats.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/manual_constructor.h"
@ -66,7 +67,7 @@ struct grpc_channel {
gpr_mu registered_call_mu;
registered_call* registered_calls;
grpc_core::RefCountedPtr<grpc_core::ChannelTrace> tracer;
grpc_core::RefCountedPtr<grpc_core::channelz::ChannelNode> channelz_channel;
char* target;
};
@ -103,6 +104,7 @@ grpc_channel* grpc_channel_create_with_builder(
channel->target = target;
channel->is_client = grpc_channel_stack_type_is_client(channel_stack_type);
size_t channel_tracer_max_nodes = 0; // default to off
bool channelz_enabled = false;
gpr_mu_init(&channel->registered_call_mu);
channel->registered_calls = nullptr;
@ -141,15 +143,20 @@ grpc_channel* grpc_channel_create_with_builder(
const grpc_integer_options options = {0, 0, INT_MAX};
channel_tracer_max_nodes =
(size_t)grpc_channel_arg_get_integer(&args->args[i], options);
} else if (0 == strcmp(args->args[i].key, GRPC_ARG_ENABLE_CHANNELZ)) {
channelz_enabled = grpc_channel_arg_get_bool(&args->args[i], false);
}
}
grpc_channel_args_destroy(args);
channel->tracer = grpc_core::MakeRefCounted<grpc_core::ChannelTrace>(
channel_tracer_max_nodes);
channel->tracer->AddTraceEvent(
grpc_core::ChannelTrace::Severity::Info,
grpc_slice_from_static_string("Channel created"));
if (channelz_enabled) {
channel->channelz_channel =
grpc_core::MakeRefCounted<grpc_core::channelz::ChannelNode>(
channel, channel_tracer_max_nodes);
channel->channelz_channel->trace()->AddTraceEvent(
grpc_core::channelz::ChannelTrace::Severity::Info,
grpc_slice_from_static_string("Channel created"));
}
return channel;
}
@ -184,12 +191,9 @@ static grpc_channel_args* build_channel_args(
return grpc_channel_args_copy_and_add(input_args, new_args, num_new_args);
}
char* grpc_channel_get_trace(grpc_channel* channel) {
return channel->tracer->RenderTrace();
}
intptr_t grpc_channel_get_uuid(grpc_channel* channel) {
return channel->tracer->GetUuid();
grpc_core::channelz::ChannelNode* grpc_channel_get_channelz_node(
grpc_channel* channel) {
return channel->channelz_channel.get();
}
grpc_channel* grpc_channel_create(const char* target,
@ -395,6 +399,10 @@ void grpc_channel_internal_unref(grpc_channel* c REF_ARG) {
static void destroy_channel(void* arg, grpc_error* error) {
grpc_channel* channel = static_cast<grpc_channel*>(arg);
if (channel->channelz_channel != nullptr) {
channel->channelz_channel->set_channel_destroyed();
channel->channelz_channel.reset();
}
grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CHANNEL(channel));
while (channel->registered_calls) {
registered_call* rc = channel->registered_calls;
@ -403,7 +411,6 @@ static void destroy_channel(void* arg, grpc_error* error) {
GRPC_MDELEM_UNREF(rc->authority);
gpr_free(rc);
}
channel->tracer.reset();
gpr_mu_destroy(&channel->registered_call_mu);
gpr_free(channel->target);
gpr_free(channel);

@ -23,6 +23,7 @@
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/channel/channelz.h"
#include "src/core/lib/surface/channel_stack_type.h"
grpc_channel* grpc_channel_create(const char* target,
@ -50,6 +51,9 @@ grpc_call* grpc_channel_create_pollset_set_call(
/** Get a (borrowed) pointer to this channels underlying channel stack */
grpc_channel_stack* grpc_channel_get_channel_stack(grpc_channel* channel);
grpc_core::channelz::ChannelNode* grpc_channel_get_channelz_node(
grpc_channel* channel);
/** Get a grpc_mdelem of grpc-status: X where X is the numeric value of
status_code.

@ -30,8 +30,6 @@ void grpc_client_channel_init(void);
void grpc_client_channel_shutdown(void);
void grpc_tsi_alts_init(void);
void grpc_tsi_alts_shutdown(void);
void grpc_server_load_reporting_plugin_init(void);
void grpc_server_load_reporting_plugin_shutdown(void);
void grpc_register_built_in_plugins(void) {
grpc_register_plugin(grpc_http_filters_init,
@ -44,6 +42,4 @@ void grpc_register_built_in_plugins(void) {
grpc_client_channel_shutdown);
grpc_register_plugin(grpc_tsi_alts_init,
grpc_tsi_alts_shutdown);
grpc_register_plugin(grpc_server_load_reporting_plugin_init,
grpc_server_load_reporting_plugin_shutdown);
}

@ -46,8 +46,6 @@ void grpc_resolver_dns_native_init(void);
void grpc_resolver_dns_native_shutdown(void);
void grpc_resolver_sockaddr_init(void);
void grpc_resolver_sockaddr_shutdown(void);
void grpc_server_load_reporting_plugin_init(void);
void grpc_server_load_reporting_plugin_shutdown(void);
void grpc_max_age_filter_init(void);
void grpc_max_age_filter_shutdown(void);
void grpc_message_size_filter_init(void);
@ -84,8 +82,6 @@ void grpc_register_built_in_plugins(void) {
grpc_resolver_dns_native_shutdown);
grpc_register_plugin(grpc_resolver_sockaddr_init,
grpc_resolver_sockaddr_shutdown);
grpc_register_plugin(grpc_server_load_reporting_plugin_init,
grpc_server_load_reporting_plugin_shutdown);
grpc_register_plugin(grpc_max_age_filter_init,
grpc_max_age_filter_shutdown);
grpc_register_plugin(grpc_message_size_filter_init,

@ -38,8 +38,6 @@ void grpc_resolver_sockaddr_init(void);
void grpc_resolver_sockaddr_shutdown(void);
void grpc_resolver_fake_init(void);
void grpc_resolver_fake_shutdown(void);
void grpc_server_load_reporting_plugin_init(void);
void grpc_server_load_reporting_plugin_shutdown(void);
void grpc_lb_policy_grpclb_init(void);
void grpc_lb_policy_grpclb_shutdown(void);
void grpc_lb_policy_pick_first_init(void);
@ -74,8 +72,6 @@ void grpc_register_built_in_plugins(void) {
grpc_resolver_sockaddr_shutdown);
grpc_register_plugin(grpc_resolver_fake_init,
grpc_resolver_fake_shutdown);
grpc_register_plugin(grpc_server_load_reporting_plugin_init,
grpc_server_load_reporting_plugin_shutdown);
grpc_register_plugin(grpc_lb_policy_grpclb_init,
grpc_lb_policy_grpclb_shutdown);
grpc_register_plugin(grpc_lb_policy_pick_first_init,

@ -2,7 +2,6 @@
/* Generated by nanopb-0.3.7-dev */
#include "src/core/tsi/alts/handshaker/altscontext.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.

@ -5,7 +5,6 @@
#define PB_GRPC_GCP_ALTSCONTEXT_PB_H_INCLUDED
#include "pb.h"
#include "src/core/tsi/alts/handshaker/transport_security_common.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.

@ -2,7 +2,6 @@
/* Generated by nanopb-0.3.7-dev */
#include "src/core/tsi/alts/handshaker/handshaker.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.

@ -5,7 +5,6 @@
#define PB_GRPC_GCP_HANDSHAKER_PB_H_INCLUDED
#include "pb.h"
#include "src/core/tsi/alts/handshaker/transport_security_common.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.

@ -2,7 +2,6 @@
/* Generated by nanopb-0.3.7-dev */
#include "src/core/tsi/alts/handshaker/transport_security_common.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.

@ -1,13 +1,62 @@
# Overview
This directory contains source code for C++ implementation of gRPC.
A C++ implementation of gRPC
To install gRPC for C++ on your system, follow the instructions to build from source
[here](../../INSTALL.md). This also installs the protocol buffer compiler
`protoc` (if you don't have it already), and the C++ gRPC plugin for `protoc`.
# To start using gRPC C++
# Documentation
In the C++ world, there's no universally accepted standard for managing project dependencies.
Therefore, gRPC supports several major build systems, which should satisfy most users.
## bazel
We recommend using Bazel for projects that use gRPC as it will give you the best developer experience
(easy handling of dependencies that support bazel & fast builds).
To add gRPC as a dependency in bazel:
1. determine commit SHA for the grpc release you want to use
2. Use the [http_archive](https://docs.bazel.build/versions/master/be/workspace.html#http_archive) bazel rule to include gRPC source
```
http_archive(
name = "grpc",
urls = [
"https://github.com/grpc/grpc/archive/YOUR_GRPC_COMMIT_SHA.tar.gz",
],
strip_prefix = "grpc-YOUR_GRPC_COMMIT_SHA",
)
```
NOTE: currently bazel is only supported for building gRPC on Linux.
## make
Currently the default choice for building on UNIX based systems is `make`.
To install gRPC for C++ on your system using `make`, follow the [Building gRPC C++](../../BUILDING.md)
instructions to build from source and then install locally using `make install`.
This also installs the protocol buffer compiler `protoc` (if you don't have it already),
and the C++ gRPC plugin for `protoc`.
WARNING: After installing with `make install` there is no easy way to uninstall, which can cause issues
if you later want to remove the grpc and/or protobuf installation or upgrade to a newer version.
## cmake
`cmake` is the default build option on Windows, but also works on Linux, MacOS. `cmake` has good
support for crosscompiling and can be used for targeting Android platform.
If your project is using cmake, there are several ways to add gRPC dependency.
- install gRPC via cmake first and then locate it with `find_package(gRPC CONFIG)`. [Example](../../examples/cpp/helloworld/CMakeLists.txt)
- via cmake's `ExternalProject_Add` using a technique called "superbuild". [Example](../../examples/cpp/helloworld/cmake_externalproject/CMakeLists.txt)
- add gRPC source tree to your project (preferrably as a git submodule) and add it to your cmake project with `add_subdirectory`. [Example](../../examples/cpp/helloworld/CMakeLists.txt)
## Packaging systems
There's no standard packaging system for C++. We've looked into supporting some (e.g. Conan and vcpkg) but we are not there yet.
Contributions and community-maintained packages for popular packaging systems are welcome!
## Examples & Additional Documentation
You can find out how to build and run our simplest gRPC C++ example in our
[C++ quick start](../../examples/cpp).
@ -25,7 +74,6 @@ documentation site at [grpc.io](https://grpc.io), specifically:
APIs.
# Examples
# To start developing gRPC C++
Code examples for gRPC C++ live in this repository's
[examples/cpp](../../examples/cpp) directory.
For instructions on how to build gRPC C++ from source, follow the [Building gRPC C++](../../BUILDING.md) instructions.

@ -207,6 +207,18 @@ class TransportStreamOpBatch {
op_->payload->context[GRPC_CONTEXT_TRACING].value);
}
const gpr_atm* get_peer_string() const {
if (op_->send_initial_metadata &&
op_->payload->send_initial_metadata.peer_string != nullptr) {
return op_->payload->send_initial_metadata.peer_string;
} else if (op_->recv_initial_metadata &&
op_->payload->recv_initial_metadata.peer_string != nullptr) {
return op_->payload->recv_initial_metadata.peer_string;
} else {
return nullptr;
}
}
private:
grpc_transport_stream_op_batch* op_; // Not owned.
MetadataBatch send_initial_metadata_;

@ -0,0 +1,71 @@
/*
*
* 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_SRC_CPP_SERVER_LOAD_REPORTER_UTIL_H
#define GRPC_SRC_CPP_SERVER_LOAD_REPORTER_UTIL_H
#include <grpc/impl/codegen/port_platform.h>
namespace grpc {
namespace load_reporter {
constexpr size_t kLbIdLength = 8;
constexpr size_t kIpv4AddressLength = 8;
constexpr size_t kIpv6AddressLength = 32;
constexpr char kInvalidLbId[] = "<INVALID_LBID_238dsb234890rb>";
// Call statuses.
constexpr char kCallStatusOk[] = "OK";
constexpr char kCallStatusServerError[] = "5XX";
constexpr char kCallStatusClientError[] = "4XX";
// Tag keys.
constexpr char kTagKeyToken[] = "token";
constexpr char kTagKeyHost[] = "host";
constexpr char kTagKeyUserId[] = "user_id";
constexpr char kTagKeyStatus[] = "status";
constexpr char kTagKeyMetricName[] = "metric_name";
// Measure names.
constexpr char kMeasureStartCount[] = "grpc.io/lb/start_count";
constexpr char kMeasureEndCount[] = "grpc.io/lb/end_count";
constexpr char kMeasureEndBytesSent[] = "grpc.io/lb/bytes_sent";
constexpr char kMeasureEndBytesReceived[] = "grpc.io/lb/bytes_received";
constexpr char kMeasureEndLatencyMs[] = "grpc.io/lb/latency_ms";
constexpr char kMeasureOtherCallMetric[] = "grpc.io/lb/other_call_metric";
// View names.
constexpr char kViewStartCount[] = "grpc.io/lb_view/start_count";
constexpr char kViewEndCount[] = "grpc.io/lb_view/end_count";
constexpr char kViewEndBytesSent[] = "grpc.io/lb_view/bytes_sent";
constexpr char kViewEndBytesReceived[] = "grpc.io/lb_view/bytes_received";
constexpr char kViewEndLatencyMs[] = "grpc.io/lb_view/latency_ms";
constexpr char kViewOtherCallMetricCount[] =
"grpc.io/lb_view/other_call_metric_count";
constexpr char kViewOtherCallMetricValue[] =
"grpc.io/lb_view/other_call_metric_value";
} // namespace load_reporter
} // namespace grpc
#endif // GRPC_SRC_CPP_SERVER_LOAD_REPORTER_UTIL_H

@ -0,0 +1,36 @@
/*
*
* 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_SRC_CPP_SERVER_LOAD_REPORTER_GET_CPU_STATS_H
#define GRPC_SRC_CPP_SERVER_LOAD_REPORTER_GET_CPU_STATS_H
#include <grpc/impl/codegen/port_platform.h>
#include <utility>
namespace grpc {
namespace load_reporter {
// Reads the CPU stats (in a pair of busy and total numbers) from the system.
// The units of the stats should be the same.
std::pair<uint64_t, uint64_t> GetCpuStatsImpl();
} // namespace load_reporter
} // namespace grpc
#endif // GRPC_SRC_CPP_SERVER_LOAD_REPORTER_GET_CPU_STATS_H

@ -0,0 +1,45 @@
/*
*
* 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>
#ifdef GPR_LINUX
#include <cstdio>
#include "src/cpp/server/load_reporter/get_cpu_stats.h"
namespace grpc {
namespace load_reporter {
std::pair<uint64_t, uint64_t> GetCpuStatsImpl() {
uint64_t busy = 0, total = 0;
FILE* fp;
fp = fopen("/proc/stat", "r");
uint64_t user, nice, system, idle;
fscanf(fp, "cpu %lu %lu %lu %lu", &user, &nice, &system, &idle);
fclose(fp);
busy = user + nice + system;
total = busy + idle;
return std::make_pair(busy, total);
}
} // namespace load_reporter
} // namespace grpc
#endif // GPR_LINUX

@ -0,0 +1,45 @@
/*
*
* 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>
#ifdef GPR_APPLE
#include <mach/mach.h>
#include "src/cpp/server/load_reporter/get_cpu_stats.h"
namespace grpc {
namespace load_reporter {
std::pair<uint64_t, uint64_t> GetCpuStatsImpl() {
uint64_t busy = 0, total = 0;
host_cpu_load_info_data_t cpuinfo;
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO,
(host_info_t)&cpuinfo, &count) == KERN_SUCCESS) {
for (int i = 0; i < CPU_STATE_MAX; i++) total += cpuinfo.cpu_ticks[i];
busy = total - cpuinfo.cpu_ticks[CPU_STATE_IDLE];
}
return std::make_pair(busy, total);
}
} // namespace load_reporter
} // namespace grpc
#endif // GPR_APPLE

@ -0,0 +1,40 @@
/*
*
* 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>
#if !defined(GPR_LINUX) && !defined(GPR_WINDOWS) && !defined(GPR_APPLE)
#include <grpc/support/log.h>
#include "src/cpp/server/load_reporter/get_cpu_stats.h"
namespace grpc {
namespace load_reporter {
std::pair<uint64_t, uint64_t> GetCpuStatsImpl() {
uint64_t busy = 0, total = 0;
gpr_log(GPR_ERROR,
"Platforms other than Linux, Windows, and MacOS are not supported.");
return std::make_pair(busy, total);
}
} // namespace load_reporter
} // namespace grpc
#endif // !defined(GPR_LINUX) && !defined(GPR_WINDOWS) && !defined(GPR_APPLE)

@ -0,0 +1,55 @@
/*
*
* 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>
#ifdef GPR_WINDOWS
#include <windows.h>
#include <cstdint>
#include "src/cpp/server/load_reporter/get_cpu_stats.h"
namespace grpc {
namespace load_reporter {
namespace {
uint64_t FiletimeToInt(const FILETIME& ft) {
ULARGE_INTEGER i;
i.LowPart = ft.dwLowDateTime;
i.HighPart = ft.dwHighDateTime;
return i.QuadPart;
}
} // namespace
std::pair<uint64_t, uint64_t> GetCpuStatsImpl() {
uint64_t busy = 0, total = 0;
FILETIME idle, kernel, user;
if (GetSystemTimes(&idle, &kernel, &user) != 0) {
total = FiletimeToInt(kernel) + FiletimeToInt(user);
busy = total - FiletimeToInt(idle);
}
return std::make_pair(busy, total);
}
} // namespace load_reporter
} // namespace grpc
#endif // GPR_WINDOWS

@ -16,11 +16,15 @@
*
*/
#include <grpc/impl/codegen/port_platform.h>
#include <stdio.h>
#include <cstdlib>
#include <set>
#include <unordered_map>
#include <vector>
#include "src/core/lib/iomgr/socket_utils.h"
#include "src/cpp/server/load_reporter/load_data_store.h"
namespace grpc {
@ -73,6 +77,67 @@ const typename C::value_type* RandomElement(const C& container) {
} // namespace
LoadRecordKey::LoadRecordKey(const grpc::string& client_ip_and_token,
grpc::string user_id)
: user_id_(std::move(user_id)) {
GPR_ASSERT(client_ip_and_token.size() >= 2);
int ip_hex_size;
GPR_ASSERT(sscanf(client_ip_and_token.substr(0, 2).c_str(), "%d",
&ip_hex_size) == 1);
GPR_ASSERT(ip_hex_size == 0 || ip_hex_size == kIpv4AddressLength ||
ip_hex_size == kIpv6AddressLength);
size_t cur_pos = 2;
client_ip_hex_ = client_ip_and_token.substr(cur_pos, ip_hex_size);
cur_pos += ip_hex_size;
if (client_ip_and_token.size() - cur_pos < kLbIdLength) {
lb_id_ = kInvalidLbId;
lb_tag_ = "";
} else {
lb_id_ = client_ip_and_token.substr(cur_pos, kLbIdLength);
lb_tag_ = client_ip_and_token.substr(cur_pos + kLbIdLength);
}
}
grpc::string LoadRecordKey::GetClientIpBytes() const {
if (client_ip_hex_.empty()) {
return "";
} else if (client_ip_hex_.size() == kIpv4AddressLength) {
uint32_t ip_bytes;
if (sscanf(client_ip_hex_.c_str(), "%x", &ip_bytes) != 1) {
gpr_log(GPR_ERROR,
"Can't parse client IP (%s) from a hex string to an integer.",
client_ip_hex_.c_str());
return "";
}
ip_bytes = grpc_htonl(ip_bytes);
return grpc::string(reinterpret_cast<const char*>(&ip_bytes),
sizeof(ip_bytes));
} else if (client_ip_hex_.size() == kIpv6AddressLength) {
uint32_t ip_bytes[4];
for (size_t i = 0; i < 4; ++i) {
if (sscanf(client_ip_hex_.substr(i * 8, (i + 1) * 8).c_str(), "%x",
ip_bytes + i) != 1) {
gpr_log(
GPR_ERROR,
"Can't parse client IP part (%s) from a hex string to an integer.",
client_ip_hex_.substr(i * 8, (i + 1) * 8).c_str());
return "";
}
ip_bytes[i] = grpc_htonl(ip_bytes[i]);
}
return grpc::string(reinterpret_cast<const char*>(ip_bytes),
sizeof(ip_bytes));
} else {
GPR_UNREACHABLE_CODE(return "");
}
}
LoadRecordValue::LoadRecordValue(grpc::string metric_name, uint64_t num_calls,
double total_metric_value) {
call_metrics_.emplace(std::move(metric_name),
CallMetricValue(num_calls, total_metric_value));
}
void PerBalancerStore::MergeRow(const LoadRecordKey& key,
const LoadRecordValue& value) {
// During suspension, the load data received will be dropped.

@ -28,12 +28,11 @@
#include <grpc/support/log.h>
#include <grpcpp/impl/codegen/config.h>
#include "src/cpp/server/load_reporter/constants.h"
namespace grpc {
namespace load_reporter {
constexpr char kInvalidLbId[] = "<INVALID_LBID_238dsb234890rb>";
constexpr uint8_t kLbIdLen = 8;
// The load data storage is organized in hierarchy. The LoadDataStore is the
// top-level data store. In LoadDataStore, for each host we keep a
// PerHostStore, in which for each balancer we keep a PerBalancerStore. Each
@ -68,13 +67,16 @@ class CallMetricValue {
// The key of a load record.
class LoadRecordKey {
public:
explicit LoadRecordKey(grpc::string lb_id, grpc::string lb_tag,
grpc::string user_id, grpc::string client_ip_hex)
LoadRecordKey(grpc::string lb_id, grpc::string lb_tag, grpc::string user_id,
grpc::string client_ip_hex)
: lb_id_(std::move(lb_id)),
lb_tag_(std::move(lb_tag)),
user_id_(std::move(user_id)),
client_ip_hex_(std::move(client_ip_hex)) {}
// Parses the input client_ip_and_token to set client IP, LB ID, and LB tag.
LoadRecordKey(const grpc::string& client_ip_and_token, grpc::string user_id);
grpc::string ToString() const {
return "[lb_id_=" + lb_id_ + ", lb_tag_=" + lb_tag_ +
", user_id_=" + user_id_ + ", client_ip_hex_=" + client_ip_hex_ +
@ -86,6 +88,9 @@ class LoadRecordKey {
user_id_ == other.user_id_ && client_ip_hex_ == other.client_ip_hex_;
}
// Gets the client IP bytes in network order (i.e., big-endian).
grpc::string GetClientIpBytes() const;
// Getters.
const grpc::string& lb_id() const { return lb_id_; }
const grpc::string& lb_tag() const { return lb_tag_; }
@ -119,8 +124,8 @@ class LoadRecordKey {
class LoadRecordValue {
public:
explicit LoadRecordValue(uint64_t start_count = 0, uint64_t ok_count = 0,
uint64_t error_count = 0, double bytes_sent = 0,
double bytes_recv = 0, double latency_ms = 0)
uint64_t error_count = 0, uint64_t bytes_sent = 0,
uint64_t bytes_recv = 0, uint64_t latency_ms = 0)
: start_count_(start_count),
ok_count_(ok_count),
error_count_(error_count),
@ -128,6 +133,9 @@ class LoadRecordValue {
bytes_recv_(bytes_recv),
latency_ms_(latency_ms) {}
LoadRecordValue(grpc::string metric_name, uint64_t num_calls,
double total_metric_value);
void MergeFrom(const LoadRecordValue& other) {
start_count_ += other.start_count_;
ok_count_ += other.ok_count_;
@ -164,9 +172,9 @@ class LoadRecordValue {
uint64_t start_count() const { return start_count_; }
uint64_t ok_count() const { return ok_count_; }
uint64_t error_count() const { return error_count_; }
double bytes_sent() const { return bytes_sent_; }
double bytes_recv() const { return bytes_recv_; }
double latency_ms() const { return latency_ms_; }
uint64_t bytes_sent() const { return bytes_sent_; }
uint64_t bytes_recv() const { return bytes_recv_; }
uint64_t latency_ms() const { return latency_ms_; }
const std::unordered_map<grpc::string, CallMetricValue>& call_metrics()
const {
return call_metrics_;
@ -176,9 +184,9 @@ class LoadRecordValue {
uint64_t start_count_ = 0;
uint64_t ok_count_ = 0;
uint64_t error_count_ = 0;
double bytes_sent_ = 0;
double bytes_recv_ = 0;
double latency_ms_ = 0;
uint64_t bytes_sent_ = 0;
uint64_t bytes_recv_ = 0;
uint64_t latency_ms_ = 0;
std::unordered_map<grpc::string, CallMetricValue> call_metrics_;
};

@ -0,0 +1,498 @@
/*
*
* 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/impl/codegen/port_platform.h>
#include <stdint.h>
#include <stdio.h>
#include <chrono>
#include <ctime>
#include "src/cpp/server/load_reporter/constants.h"
#include "src/cpp/server/load_reporter/get_cpu_stats.h"
#include "src/cpp/server/load_reporter/load_reporter.h"
#include "opencensus/stats/internal/set_aggregation_window.h"
namespace grpc {
namespace load_reporter {
CpuStatsProvider::CpuStatsSample CpuStatsProviderDefaultImpl::GetCpuStats() {
return GetCpuStatsImpl();
}
CensusViewProvider::CensusViewProvider()
: tag_key_token_(::opencensus::stats::TagKey::Register(kTagKeyToken)),
tag_key_host_(::opencensus::stats::TagKey::Register(kTagKeyHost)),
tag_key_user_id_(::opencensus::stats::TagKey::Register(kTagKeyUserId)),
tag_key_status_(::opencensus::stats::TagKey::Register(kTagKeyStatus)),
tag_key_metric_name_(
::opencensus::stats::TagKey::Register(kTagKeyMetricName)) {
// One view related to starting a call.
auto vd_start_count =
::opencensus::stats::ViewDescriptor()
.set_name(kViewStartCount)
.set_measure(kMeasureStartCount)
.set_aggregation(::opencensus::stats::Aggregation::Sum())
.add_column(tag_key_token_)
.add_column(tag_key_host_)
.add_column(tag_key_user_id_)
.set_description(
"Delta count of calls started broken down by <token, host, "
"user_id>.");
::opencensus::stats::SetAggregationWindow(
::opencensus::stats::AggregationWindow::Delta(), &vd_start_count);
view_descriptor_map_.emplace(kViewStartCount, vd_start_count);
// Four views related to ending a call.
// If this view is set as Count of kMeasureEndBytesSent (in hope of saving one
// measure), it's infeasible to prepare fake data for testing. That's because
// the OpenCensus API to make up view data will add the input data as separate
// measurements instead of setting the data values directly.
auto vd_end_count =
::opencensus::stats::ViewDescriptor()
.set_name((kViewEndCount))
.set_measure((kMeasureEndCount))
.set_aggregation(::opencensus::stats::Aggregation::Sum())
.add_column(tag_key_token_)
.add_column(tag_key_host_)
.add_column(tag_key_user_id_)
.add_column(tag_key_status_)
.set_description(
"Delta count of calls ended broken down by <token, host, "
"user_id, status>.");
::opencensus::stats::SetAggregationWindow(
::opencensus::stats::AggregationWindow::Delta(), &vd_end_count);
view_descriptor_map_.emplace(kViewEndCount, vd_end_count);
auto vd_end_bytes_sent =
::opencensus::stats::ViewDescriptor()
.set_name((kViewEndBytesSent))
.set_measure((kMeasureEndBytesSent))
.set_aggregation(::opencensus::stats::Aggregation::Sum())
.add_column(tag_key_token_)
.add_column(tag_key_host_)
.add_column(tag_key_user_id_)
.add_column(tag_key_status_)
.set_description(
"Delta sum of bytes sent broken down by <token, host, user_id, "
"status>.");
::opencensus::stats::SetAggregationWindow(
::opencensus::stats::AggregationWindow::Delta(), &vd_end_bytes_sent);
view_descriptor_map_.emplace(kViewEndBytesSent, vd_end_bytes_sent);
auto vd_end_bytes_received =
::opencensus::stats::ViewDescriptor()
.set_name((kViewEndBytesReceived))
.set_measure((kMeasureEndBytesReceived))
.set_aggregation(::opencensus::stats::Aggregation::Sum())
.add_column(tag_key_token_)
.add_column(tag_key_host_)
.add_column(tag_key_user_id_)
.add_column(tag_key_status_)
.set_description(
"Delta sum of bytes received broken down by <token, host, "
"user_id, status>.");
::opencensus::stats::SetAggregationWindow(
::opencensus::stats::AggregationWindow::Delta(), &vd_end_bytes_received);
view_descriptor_map_.emplace(kViewEndBytesReceived, vd_end_bytes_received);
auto vd_end_latency_ms =
::opencensus::stats::ViewDescriptor()
.set_name((kViewEndLatencyMs))
.set_measure((kMeasureEndLatencyMs))
.set_aggregation(::opencensus::stats::Aggregation::Sum())
.add_column(tag_key_token_)
.add_column(tag_key_host_)
.add_column(tag_key_user_id_)
.add_column(tag_key_status_)
.set_description(
"Delta sum of latency in ms broken down by <token, host, "
"user_id, status>.");
::opencensus::stats::SetAggregationWindow(
::opencensus::stats::AggregationWindow::Delta(), &vd_end_latency_ms);
view_descriptor_map_.emplace(kViewEndLatencyMs, vd_end_latency_ms);
// Two views related to other call metrics.
auto vd_metric_call_count =
::opencensus::stats::ViewDescriptor()
.set_name((kViewOtherCallMetricCount))
.set_measure((kMeasureOtherCallMetric))
.set_aggregation(::opencensus::stats::Aggregation::Count())
.add_column(tag_key_token_)
.add_column(tag_key_host_)
.add_column(tag_key_user_id_)
.add_column(tag_key_metric_name_)
.set_description(
"Delta count of calls broken down by <token, host, user_id, "
"metric_name>.");
::opencensus::stats::SetAggregationWindow(
::opencensus::stats::AggregationWindow::Delta(), &vd_metric_call_count);
view_descriptor_map_.emplace(kViewOtherCallMetricCount, vd_metric_call_count);
auto vd_metric_value =
::opencensus::stats::ViewDescriptor()
.set_name((kViewOtherCallMetricValue))
.set_measure((kMeasureOtherCallMetric))
.set_aggregation(::opencensus::stats::Aggregation::Sum())
.add_column(tag_key_token_)
.add_column(tag_key_host_)
.add_column(tag_key_user_id_)
.add_column(tag_key_metric_name_)
.set_description(
"Delta sum of call metric value broken down "
"by <token, host, user_id, metric_name>.");
::opencensus::stats::SetAggregationWindow(
::opencensus::stats::AggregationWindow::Delta(), &vd_metric_value);
view_descriptor_map_.emplace(kViewOtherCallMetricValue, vd_metric_value);
}
double CensusViewProvider::GetRelatedViewDataRowDouble(
const ViewDataMap& view_data_map, const char* view_name,
size_t view_name_len, const std::vector<grpc::string>& tag_values) {
auto it_vd = view_data_map.find(grpc::string(view_name, view_name_len));
GPR_ASSERT(it_vd != view_data_map.end());
auto it_row = it_vd->second.double_data().find(tag_values);
GPR_ASSERT(it_row != it_vd->second.double_data().end());
return it_row->second;
}
CensusViewProviderDefaultImpl::CensusViewProviderDefaultImpl() {
for (const auto& p : view_descriptor_map()) {
const grpc::string& view_name = p.first;
const ::opencensus::stats::ViewDescriptor& vd = p.second;
// We need to use pair's piecewise ctor here, otherwise the deleted copy
// ctor of View will be called.
view_map_.emplace(std::piecewise_construct,
std::forward_as_tuple(view_name),
std::forward_as_tuple(vd));
}
}
CensusViewProvider::ViewDataMap CensusViewProviderDefaultImpl::FetchViewData() {
gpr_log(GPR_DEBUG, "[CVP %p] Starts fetching Census view data.", this);
ViewDataMap view_data_map;
for (auto& p : view_map_) {
const grpc::string& view_name = p.first;
::opencensus::stats::View& view = p.second;
if (view.IsValid()) {
view_data_map.emplace(view_name, view.GetData());
gpr_log(GPR_DEBUG, "[CVP %p] Fetched view data (view: %s).", this,
view_name.c_str());
} else {
gpr_log(
GPR_DEBUG,
"[CVP %p] Can't fetch view data because view is invalid (view: %s).",
this, view_name.c_str());
}
}
return view_data_map;
}
grpc::string LoadReporter::GenerateLbId() {
while (true) {
if (next_lb_id_ > UINT32_MAX) {
gpr_log(GPR_ERROR, "[LR %p] The LB ID exceeds the max valid value!",
this);
return "";
}
int64_t lb_id = next_lb_id_++;
// Overflow should never happen.
GPR_ASSERT(lb_id >= 0);
// Convert to padded hex string for a 32-bit LB ID. E.g, "0000ca5b".
char buf[kLbIdLength + 1];
snprintf(buf, sizeof(buf), "%08lx", lb_id);
grpc::string lb_id_str(buf, kLbIdLength);
// The client may send requests with LB ID that has never been allocated
// by this load reporter. Those IDs are tracked and will be skipped when
// we generate a new ID.
if (!load_data_store_.IsTrackedUnknownBalancerId(lb_id_str)) {
return lb_id_str;
}
}
}
::grpc::lb::v1::LoadBalancingFeedback
LoadReporter::GenerateLoadBalancingFeedback() {
std::unique_lock<std::mutex> lock(feedback_mu_);
auto now = std::chrono::system_clock::now();
// Discard records outside the window until there is only one record
// outside the window, which is used as the base for difference.
while (feedback_records_.size() > 1 &&
!IsRecordInWindow(feedback_records_[1], now)) {
feedback_records_.pop_front();
}
if (feedback_records_.size() < 2) {
return ::grpc::lb::v1::LoadBalancingFeedback::default_instance();
}
// Find the longest range with valid ends.
LoadBalancingFeedbackRecord* oldest = &feedback_records_[0];
LoadBalancingFeedbackRecord* newest =
&feedback_records_[feedback_records_.size() - 1];
while (newest > oldest &&
(newest->cpu_limit == 0 || oldest->cpu_limit == 0)) {
// A zero limit means that the system info reading was failed, so these
// records can't be used to calculate CPU utilization.
if (newest->cpu_limit == 0) --newest;
if (oldest->cpu_limit == 0) ++oldest;
}
if (newest - oldest < 1 || oldest->end_time == newest->end_time ||
newest->cpu_limit == oldest->cpu_limit) {
return ::grpc::lb::v1::LoadBalancingFeedback::default_instance();
}
uint64_t rpcs = 0;
uint64_t errors = 0;
for (LoadBalancingFeedbackRecord* p = newest; p != oldest; --p) {
// Because these two numbers are counters, the oldest record shouldn't be
// included.
rpcs += p->rpcs;
errors += p->errors;
}
double cpu_usage = newest->cpu_usage - oldest->cpu_usage;
double cpu_limit = newest->cpu_limit - oldest->cpu_limit;
std::chrono::duration<double> duration_seconds =
newest->end_time - oldest->end_time;
lock.unlock();
::grpc::lb::v1::LoadBalancingFeedback feedback;
feedback.set_server_utilization(static_cast<float>(cpu_usage / cpu_limit));
feedback.set_calls_per_second(
static_cast<float>(rpcs / duration_seconds.count()));
feedback.set_errors_per_second(
static_cast<float>(errors / duration_seconds.count()));
return feedback;
}
::google::protobuf::RepeatedPtrField<::grpc::lb::v1::Load>
LoadReporter::GenerateLoads(const grpc::string& hostname,
const grpc::string& lb_id) {
std::lock_guard<std::mutex> lock(store_mu_);
auto assigned_stores = load_data_store_.GetAssignedStores(hostname, lb_id);
GPR_ASSERT(assigned_stores != nullptr);
GPR_ASSERT(!assigned_stores->empty());
::google::protobuf::RepeatedPtrField<::grpc::lb::v1::Load> loads;
for (PerBalancerStore* per_balancer_store : *assigned_stores) {
GPR_ASSERT(!per_balancer_store->IsSuspended());
if (!per_balancer_store->load_record_map().empty()) {
for (const auto& p : per_balancer_store->load_record_map()) {
const auto& key = p.first;
const auto& value = p.second;
auto load = loads.Add();
load->set_load_balance_tag(key.lb_tag());
load->set_user_id(key.user_id());
load->set_client_ip_address(key.GetClientIpBytes());
load->set_num_calls_started(static_cast<int64_t>(value.start_count()));
load->set_num_calls_finished_without_error(
static_cast<int64_t>(value.ok_count()));
load->set_num_calls_finished_with_error(
static_cast<int64_t>(value.error_count()));
load->set_total_bytes_sent(static_cast<int64_t>(value.bytes_sent()));
load->set_total_bytes_received(
static_cast<int64_t>(value.bytes_recv()));
load->mutable_total_latency()->set_seconds(
static_cast<int64_t>(value.latency_ms() / 1000));
load->mutable_total_latency()->set_nanos(
(static_cast<int32_t>(value.latency_ms()) % 1000) * 1000000);
for (const auto& p : value.call_metrics()) {
const grpc::string& metric_name = p.first;
const CallMetricValue& metric_value = p.second;
auto call_metric_data = load->add_metric_data();
call_metric_data->set_metric_name(metric_name);
call_metric_data->set_num_calls_finished_with_metric(
metric_value.num_calls());
call_metric_data->set_total_metric_value(
metric_value.total_metric_value());
}
if (per_balancer_store->lb_id() != lb_id) {
// This per-balancer store is an orphan assigned to this receiving
// balancer.
AttachOrphanLoadId(load, *per_balancer_store);
}
}
per_balancer_store->ClearLoadRecordMap();
}
if (per_balancer_store->IsNumCallsInProgressChangedSinceLastReport()) {
auto load = loads.Add();
load->set_num_calls_in_progress(
per_balancer_store->GetNumCallsInProgressForReport());
if (per_balancer_store->lb_id() != lb_id) {
// This per-balancer store is an orphan assigned to this receiving
// balancer.
AttachOrphanLoadId(load, *per_balancer_store);
}
}
}
return loads;
}
void LoadReporter::AttachOrphanLoadId(
::grpc::lb::v1::Load* load, const PerBalancerStore& per_balancer_store) {
if (per_balancer_store.lb_id() == kInvalidLbId) {
load->set_load_key_unknown(true);
} else {
load->set_load_key_unknown(false);
load->mutable_orphaned_load_identifier()->set_load_key(
per_balancer_store.load_key());
load->mutable_orphaned_load_identifier()->set_load_balancer_id(
per_balancer_store.lb_id());
}
}
void LoadReporter::AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors) {
CpuStatsProvider::CpuStatsSample cpu_stats;
if (cpu_stats_provider_ != nullptr) {
cpu_stats = cpu_stats_provider_->GetCpuStats();
} else {
// This will make the load balancing feedback generation a no-op.
cpu_stats = {0, 0};
}
std::unique_lock<std::mutex> lock(feedback_mu_);
feedback_records_.emplace_back(std::chrono::system_clock::now(), rpcs, errors,
cpu_stats.first, cpu_stats.second);
}
void LoadReporter::ReportStreamCreated(const grpc::string& hostname,
const grpc::string& lb_id,
const grpc::string& load_key) {
std::lock_guard<std::mutex> lock(store_mu_);
load_data_store_.ReportStreamCreated(hostname, lb_id, load_key);
gpr_log(GPR_INFO,
"[LR %p] Report stream created (host: %s, LB ID: %s, load key: %s).",
this, hostname.c_str(), lb_id.c_str(), load_key.c_str());
}
void LoadReporter::ReportStreamClosed(const grpc::string& hostname,
const grpc::string& lb_id) {
std::lock_guard<std::mutex> lock(store_mu_);
load_data_store_.ReportStreamClosed(hostname, lb_id);
gpr_log(GPR_INFO, "[LR %p] Report stream closed (host: %s, LB ID: %s).", this,
hostname.c_str(), lb_id.c_str());
}
void LoadReporter::ProcessViewDataCallStart(
const CensusViewProvider::ViewDataMap& view_data_map) {
auto it = view_data_map.find(kViewStartCount);
if (it != view_data_map.end()) {
// Note that the data type for any Sum view is double, whatever the data
// type of the original measure.
for (const auto& p : it->second.double_data()) {
const std::vector<grpc::string>& tag_values = p.first;
const uint64_t start_count = static_cast<uint64_t>(p.second);
const grpc::string& client_ip_and_token = tag_values[0];
const grpc::string& host = tag_values[1];
const grpc::string& user_id = tag_values[2];
LoadRecordKey key(client_ip_and_token, user_id);
LoadRecordValue value = LoadRecordValue(start_count);
{
std::unique_lock<std::mutex> lock(store_mu_);
load_data_store_.MergeRow(host, key, value);
}
}
}
}
void LoadReporter::ProcessViewDataCallEnd(
const CensusViewProvider::ViewDataMap& view_data_map) {
uint64_t total_end_count = 0;
uint64_t total_error_count = 0;
auto it = view_data_map.find(kViewEndCount);
if (it != view_data_map.end()) {
// Note that the data type for any Sum view is double, whatever the data
// type of the original measure.
for (const auto& p : it->second.double_data()) {
const std::vector<grpc::string>& tag_values = p.first;
const uint64_t end_count = static_cast<uint64_t>(p.second);
const grpc::string& client_ip_and_token = tag_values[0];
const grpc::string& host = tag_values[1];
const grpc::string& user_id = tag_values[2];
const grpc::string& status = tag_values[3];
// This is due to a bug reported internally of Java server load reporting
// implementation.
// TODO(juanlishen): Check whether this situation happens in OSS C++.
if (client_ip_and_token.size() == 0) {
gpr_log(GPR_DEBUG,
"Skipping processing Opencensus record with empty "
"client_ip_and_token tag.");
continue;
}
LoadRecordKey key(client_ip_and_token, user_id);
const uint64_t bytes_sent =
CensusViewProvider::GetRelatedViewDataRowDouble(
view_data_map, kViewEndBytesSent, sizeof(kViewEndBytesSent) - 1,
tag_values);
const uint64_t bytes_received =
CensusViewProvider::GetRelatedViewDataRowDouble(
view_data_map, kViewEndBytesReceived,
sizeof(kViewEndBytesReceived) - 1, tag_values);
const uint64_t latency_ms =
CensusViewProvider::GetRelatedViewDataRowDouble(
view_data_map, kViewEndLatencyMs, sizeof(kViewEndLatencyMs) - 1,
tag_values);
uint64_t ok_count = 0;
uint64_t error_count = 0;
total_end_count += end_count;
if (std::strcmp(status.c_str(), kCallStatusOk) == 0) {
ok_count = end_count;
} else {
error_count = end_count;
total_error_count += end_count;
}
LoadRecordValue value = LoadRecordValue(
0, ok_count, error_count, bytes_sent, bytes_received, latency_ms);
{
std::unique_lock<std::mutex> lock(store_mu_);
load_data_store_.MergeRow(host, key, value);
}
}
}
AppendNewFeedbackRecord(total_end_count, total_error_count);
}
void LoadReporter::ProcessViewDataOtherCallMetrics(
const CensusViewProvider::ViewDataMap& view_data_map) {
auto it = view_data_map.find(kViewOtherCallMetricCount);
if (it != view_data_map.end()) {
for (const auto& p : it->second.int_data()) {
const std::vector<grpc::string>& tag_values = p.first;
const int64_t num_calls = p.second;
const grpc::string& client_ip_and_token = tag_values[0];
const grpc::string& host = tag_values[1];
const grpc::string& user_id = tag_values[2];
const grpc::string& metric_name = tag_values[3];
LoadRecordKey key(client_ip_and_token, user_id);
const double total_metric_value =
CensusViewProvider::GetRelatedViewDataRowDouble(
view_data_map, kViewOtherCallMetricValue,
sizeof(kViewOtherCallMetricValue) - 1, tag_values);
LoadRecordValue value = LoadRecordValue(
metric_name, static_cast<uint64_t>(num_calls), total_metric_value);
{
std::unique_lock<std::mutex> lock(store_mu_);
load_data_store_.MergeRow(host, key, value);
}
}
}
}
void LoadReporter::FetchAndSample() {
gpr_log(GPR_DEBUG,
"[LR %p] Starts fetching Census view data and sampling LB feedback "
"record.",
this);
CensusViewProvider::ViewDataMap view_data_map =
census_view_provider_->FetchViewData();
ProcessViewDataCallStart(view_data_map);
ProcessViewDataCallEnd(view_data_map);
ProcessViewDataOtherCallMetrics(view_data_map);
}
} // namespace load_reporter
} // namespace grpc

@ -0,0 +1,225 @@
/*
*
* 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_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_REPORTER_H
#define GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_REPORTER_H
#include <grpc/support/port_platform.h>
#include <atomic>
#include <chrono>
#include <deque>
#include <vector>
#include <grpc/support/log.h>
#include <grpcpp/impl/codegen/config.h>
#include "src/cpp/server/load_reporter/load_data_store.h"
#include "src/proto/grpc/lb/v1/load_reporter.grpc.pb.h"
#include "opencensus/stats/stats.h"
namespace grpc {
namespace load_reporter {
// The interface to get the Census stats. Abstracted for mocking.
class CensusViewProvider {
public:
// Maps from the view name to the view data.
using ViewDataMap =
std::unordered_map<grpc::string, ::opencensus::stats::ViewData>;
// Maps from the view name to the view descriptor.
using ViewDescriptorMap =
std::unordered_map<grpc::string, ::opencensus::stats::ViewDescriptor>;
CensusViewProvider();
virtual ~CensusViewProvider() = default;
// Fetches the view data accumulated since last fetching, and returns it as a
// map from the view name to the view data.
virtual ViewDataMap FetchViewData() = 0;
// A helper function that gets a row with the input tag values from the view
// data. Only used when we know that row must exist because we have seen a row
// with the same tag values in a related view data. Several ViewData's are
// considered related if their views are based on the measures that are always
// recorded at the same time.
double static GetRelatedViewDataRowDouble(
const ViewDataMap& view_data_map, const char* view_name,
size_t view_name_len, const std::vector<grpc::string>& tag_values);
protected:
const ViewDescriptorMap& view_descriptor_map() const {
return view_descriptor_map_;
}
private:
ViewDescriptorMap view_descriptor_map_;
// Tag keys.
::opencensus::stats::TagKey tag_key_token_;
::opencensus::stats::TagKey tag_key_host_;
::opencensus::stats::TagKey tag_key_user_id_;
::opencensus::stats::TagKey tag_key_status_;
::opencensus::stats::TagKey tag_key_metric_name_;
};
// The default implementation fetches the real stats from Census.
class CensusViewProviderDefaultImpl : public CensusViewProvider {
public:
CensusViewProviderDefaultImpl();
ViewDataMap FetchViewData() override;
private:
std::unordered_map<grpc::string, ::opencensus::stats::View> view_map_;
};
// The interface to get the CPU stats. Abstracted for mocking.
class CpuStatsProvider {
public:
// The used and total amounts of CPU usage.
using CpuStatsSample = std::pair<uint64_t, uint64_t>;
virtual ~CpuStatsProvider() = default;
// Gets the cumulative used CPU and total CPU resource.
virtual CpuStatsSample GetCpuStats() = 0;
};
// The default implementation reads CPU jiffies from the system to calculate CPU
// utilization.
class CpuStatsProviderDefaultImpl : public CpuStatsProvider {
public:
CpuStatsSample GetCpuStats() override;
};
// Maintains all the load data and load reporting streams.
class LoadReporter {
public:
// TODO(juanlishen): Allow config for providers from users.
LoadReporter(uint32_t feedback_sample_window_seconds,
std::unique_ptr<CensusViewProvider> census_view_provider,
std::unique_ptr<CpuStatsProvider> cpu_stats_provider)
: feedback_sample_window_seconds_(feedback_sample_window_seconds),
census_view_provider_(std::move(census_view_provider)),
cpu_stats_provider_(std::move(cpu_stats_provider)) {
// Append the initial record so that the next real record can have a base.
AppendNewFeedbackRecord(0, 0);
}
// Fetches the latest data from Census and merge it into the data store.
// Also adds a new sample to the LB feedback sliding window.
// Thread-unsafe. (1). The access to the load data store and feedback records
// has locking. (2). The access to the Census view provider and CPU stats
// provider lacks locking, but we only access these two members in this method
// (in testing, we also access them when setting up expectation). So the
// invocations of this method must be serialized.
void FetchAndSample();
// Generates a report for that host and balancer. The report contains
// all the stats data accumulated between the last report (i.e., the last
// consumption) and the last fetch from Census (i.e., the last production).
// Thread-safe.
::google::protobuf::RepeatedPtrField<::grpc::lb::v1::Load> GenerateLoads(
const grpc::string& hostname, const grpc::string& lb_id);
// The feedback is calculated from the stats data recorded in the sliding
// window. Outdated records are discarded.
// Thread-safe.
::grpc::lb::v1::LoadBalancingFeedback GenerateLoadBalancingFeedback();
// Wrapper around LoadDataStore::ReportStreamCreated.
// Thread-safe.
void ReportStreamCreated(const grpc::string& hostname,
const grpc::string& lb_id,
const grpc::string& load_key);
// Wrapper around LoadDataStore::ReportStreamClosed.
// Thread-safe.
void ReportStreamClosed(const grpc::string& hostname,
const grpc::string& lb_id);
// Generates a unique LB ID of length kLbIdLength. Returns an empty string
// upon failure. Thread-safe.
grpc::string GenerateLbId();
// Accessors only for testing.
CensusViewProvider* census_view_provider() {
return census_view_provider_.get();
}
CpuStatsProvider* cpu_stats_provider() { return cpu_stats_provider_.get(); }
private:
struct LoadBalancingFeedbackRecord {
std::chrono::system_clock::time_point end_time;
uint64_t rpcs;
uint64_t errors;
uint64_t cpu_usage;
uint64_t cpu_limit;
LoadBalancingFeedbackRecord(
const std::chrono::system_clock::time_point& end_time, uint64_t rpcs,
uint64_t errors, uint64_t cpu_usage, uint64_t cpu_limit)
: end_time(end_time),
rpcs(rpcs),
errors(errors),
cpu_usage(cpu_usage),
cpu_limit(cpu_limit) {}
};
// Finds the view data about starting call from the view_data_map and merges
// the data to the load data store.
void ProcessViewDataCallStart(
const CensusViewProvider::ViewDataMap& view_data_map);
// Finds the view data about ending call from the view_data_map and merges the
// data to the load data store.
void ProcessViewDataCallEnd(
const CensusViewProvider::ViewDataMap& view_data_map);
// Finds the view data about the customized call metrics from the
// view_data_map and merges the data to the load data store.
void ProcessViewDataOtherCallMetrics(
const CensusViewProvider::ViewDataMap& view_data_map);
bool IsRecordInWindow(const LoadBalancingFeedbackRecord& record,
std::chrono::system_clock::time_point now) {
return record.end_time > now - feedback_sample_window_seconds_;
}
void AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors);
// Extracts an OrphanedLoadIdentifier from the per-balancer store and attaches
// it to the load.
void AttachOrphanLoadId(::grpc::lb::v1::Load* load,
const PerBalancerStore& per_balancer_store);
std::atomic<int64_t> next_lb_id_{0};
const std::chrono::seconds feedback_sample_window_seconds_;
std::mutex feedback_mu_;
std::deque<LoadBalancingFeedbackRecord> feedback_records_;
// TODO(juanlishen): Lock in finer grain. Locking the whole store may be
// too expensive.
std::mutex store_mu_;
LoadDataStore load_data_store_;
std::unique_ptr<CensusViewProvider> census_view_provider_;
std::unique_ptr<CpuStatsProvider> cpu_stats_provider_;
};
} // namespace load_reporter
} // namespace grpc
#endif // GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_REPORTER_H

@ -42,7 +42,7 @@ If you are a user of gRPC C#, go to Usage section above.
- [dotnet SDK](https://www.microsoft.com/net/core)
- [Mono 4+](https://www.mono-project.com/) (only needed for Linux and MacOS)
- Prerequisites mentioned in [INSTALL.md](../../INSTALL.md#pre-requisites)
- Prerequisites mentioned in [BUILDING.md](../../BUILDING.md#pre-requisites)
to be able to compile the native code.
**Windows, Linux or Mac OS X**
@ -93,6 +93,6 @@ THE NATIVE DEPENDENCY
Internally, gRPC C# uses a native library written in C (gRPC C core) and invokes its functionality via P/Invoke. The fact that a native library is used should be fully transparent to the users and just installing the `Grpc.Core` NuGet package is the only step needed to use gRPC C# on all supported platforms.
[API Reference]: https://grpc.io/grpc/csharp/
[API Reference]: https://grpc.io/grpc/csharp/api/Grpc.Core.html
[Helloworld Example]: ../../examples/csharp/helloworld
[RouteGuide Tutorial]: https://grpc.io/docs/tutorials/basic/csharp.html

@ -55,4 +55,19 @@ typedef NS_ENUM(NSInteger, GRPCCompressAlgorithm) {
timeout:(int)timeout
forHost:(nonnull NSString *)host;
/** Enable/Disable automatic retry of gRPC calls on the channel. If automatic retry is enabled, the
* retry is controlled by server's service config. If automatic retry is disabled, failed calls are
* immediately returned to the application layer. */
+ (void)enableRetry:(BOOL)enabled forHost:(nonnull NSString *)host;
/** Set channel connection timeout and backoff parameters. All parameters are positive integers in
* milliseconds. Set a parameter to 0 to make gRPC use default value for that parameter.
*
* Refer to gRPC's doc at https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md for the
* details of each parameter. */
+ (void)setMinConnectTimeout:(unsigned int)timeout
initialBackoff:(unsigned int)initialBackoff
maxBackoff:(unsigned int)maxBackoff
forHost:(nonnull NSString *)host;
@end

@ -64,4 +64,19 @@
hostConfig.keepaliveTimeout = timeout;
}
+ (void)enableRetry:(BOOL)enabled forHost:(nonnull NSString *)host {
GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
hostConfig.retryEnabled = enabled;
}
+ (void)setMinConnectTimeout:(unsigned int)timeout
initialBackoff:(unsigned int)initialBackoff
maxBackoff:(unsigned int)maxBackoff
forHost:(nonnull NSString *)host {
GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
hostConfig.minConnectTimeout = timeout;
hostConfig.initialConnectBackoff = initialBackoff;
hostConfig.maxConnectBackoff = maxBackoff;
}
@end

@ -38,6 +38,11 @@ struct grpc_channel_credentials;
@property(nonatomic) int keepaliveInterval;
@property(nonatomic) int keepaliveTimeout;
@property(nonatomic) id logContext;
@property(nonatomic) BOOL retryEnabled;
@property(nonatomic) unsigned int minConnectTimeout;
@property(nonatomic) unsigned int initialConnectBackoff;
@property(nonatomic) unsigned int maxConnectBackoff;
/** The following properties should only be modified for testing: */

@ -85,6 +85,7 @@ static NSMutableDictionary *kHostCache;
_secure = YES;
kHostCache[address] = self;
_compressAlgorithm = GRPC_COMPRESS_NONE;
_retryEnabled = YES;
}
#ifndef GRPC_CFSTREAM
[GRPCConnectivityMonitor registerObserver:self selector:@selector(connectivityChange:)];
@ -240,6 +241,20 @@ static NSMutableDictionary *kHostCache;
args[@GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER] = [NSNumber numberWithInt:1];
}
if (_retryEnabled == NO) {
args[@GRPC_ARG_ENABLE_RETRIES] = [NSNumber numberWithInt:0];
}
if (_minConnectTimeout > 0) {
args[@GRPC_ARG_MIN_RECONNECT_BACKOFF_MS] = [NSNumber numberWithInt:_minConnectTimeout];
}
if (_initialConnectBackoff > 0) {
args[@GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS] = [NSNumber numberWithInt:_initialConnectBackoff];
}
if (_maxConnectBackoff > 0) {
args[@GRPC_ARG_MAX_RECONNECT_BACKOFF_MS] = [NSNumber numberWithInt:_maxConnectBackoff];
}
return args;
}

@ -0,0 +1,92 @@
# gRPC iOS Network Transition Behaviors
Network connectivity on an iOS device may transition between cellular, WIFI, or
no network connectivity. This document describes how these network changes
should be handled by gRPC and current known issues.
## Expected Network Transition Behaviors
The expected gRPC iOS channel and network transition behaviors are:
* Channel connection to a particular host is established at the time of
starting the first call to the channel and remains connected for future calls
to the same host.
* If the underlying connection to the remote host is broken, the channel is
disconnected and enters TRANSIENT\_FAILURE state.
* A channel is broken if the channel connection is no longer viable. This
happens when
* The network interface is no longer available, e.g. WiFi or cellular
interface is turned off or goes offline, airplane mode turned on, etc;
* The underlying TCP connection is no longer valid, e.g. WiFi connects to
another hotspot, cellular data switched from LTE to 4G, etc;
* A network interface more preferable by the OS is valid, e.g. WiFi gets
connected when the channel is already connected via cellular.
* A channel in TRANSIENT\_FAILURE state attempts reconnection on start of the
next call to the same host, but only after a certain backoff period (see
corresponding
[doc](https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md)).
During the backoff period, any call to the same host will wait until the
first of the following events occur:
* Connection succeeded; calls will be made using this channel;
* Conncetion failed; calls will be failed and return UNAVAILABLE status code;
* The call's deadline is reached; the call will fail and return
DEADLINE\_EXCEEDED status code.
The length of backoff period of a channel is reset whenever a connection
attempt is successful.
## Implementations
### gRPC iOS with TCP Sockets
gRPC's default implementation is to use TCP sockets for networking. It turns
out that although Apple supports this type of usage, it is [not recommended by
Apple](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/SocketsAndStreams/SocketsAndStreams.html)
and has some issues described below.
#### Issues with TCP Sockets
The TCP sockets on iOS is flawed in that it does not reflect the viability of
the channel connection. Particularly, we observed the following issues when
using TCP sockets:
* When a TCP socket connection is established on cellular data and WiFi
becomes available, the TCP socket neither return an error event nor continue
sending/receiving data on it, but still accepts write on it.
* A TCP socket does not report certain events that happen in the
background. When a TCP connection breaks in the background for the reason
like WiFi connects to another hotspot, the socket neither return an error nor
continue sending/receiving data on it, but still accepts write on it.
In both situations, the user will see the call hang for an extended period of
time before the TCP socket times out.
#### gRPC iOS library's resolution to TCP socket issues
We introduced
[`ConnectivityMonitor`](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/SocketsAndStreams/SocketsAndStreams.html)
in gRPC iOS library v0.14.0 to alleviate these issues in TCP sockets,
which changes the network transition behaviors a bit.
We classify network connectivity state of the device into three categories
based on flags obtained from `SCNetworkReachability` API:
| Reachable | ConnectionRequired | IsWWAN | **Category** |
|:---------:|:------------------:|:------:|:------------:|
| 0 | X | X | None |
| X | 1 | X | None |
| 1 | 0 | 0 | WiFi |
| 1 | 0 | 1 | Cellular |
Whenever there is a transition of network between two of these categories, all
previously existing channels are assumed to be broken and are actively
destroyed. If there is an unfinished call, the call should return with status
code `UNAVAILABLE`.
`ConnectivityMonitor` is able to detect the scenario of the first issue above
and actively destroy the channels. However, the second issue is not resolvable.
To solve that issue the best solution is to switch to CFStream implementation
which eliminates all of them.
### gRPC iOS with CFStream
gRPC iOS with CFStream implementation (introduced in v1.13.0) uses Apple's
networking API to make connections. It resolves the issues with TCP sockets
mentioned above. Users are recommended to use this implementation rather than
TCP socket implementation. The detailed behavior of streams in CFStream is not
documented by Apple, but our experiments show that it accords to the expected
behaviors. With CFStream implementation, an event is always received when the
underlying connection is no longer viable. For more detailed information and
usages of CFStream implementation, refer to the
[user guide](https://github.com/grpc/grpc/blob/master/src/objective-c/README-CFSTREAM.md).

@ -0,0 +1,32 @@
[![Cocoapods](https://img.shields.io/cocoapods/v/gRPC.svg)](https://cocoapods.org/pods/gRPC)
# gRPC Objective-C with CFStream
gRPC Objective-C library now provides the option to use Apple's CFStream API (rather than TCP
sockets) for networking. Using CFStream resolves a bunch of network connectivity transition issues
(see the [doc](https://github.com/grpc/grpc/blob/master/src/objective-c/NetworkTransitionBehavior.md)
for more information).
CFStream integration is now in experimental state. You will need explicit opt-in to use it to get
the benefits of resolving the issues above. We expect to make CFStream the default networking
interface that gRPC uses when it is ready for production.
## Usage
If you use gRPC following the instructions in
[README.md](https://github.com/grpc/grpc/blob/master/src/objective-c/README.md):
- Simply replace the
dependency on `gRPC-ProtoRPC` with `gRPC-ProtoRPC/CFStream`. The build system will take care of
everything else and switch networking to CFStream.
If your project directly depends on podspecs other than `gRPC-ProtoRPC` (e.g. `gRPC` or
`gRPC-Core`):
- Make your projects depend on subspecs corresponding to CFStream in each gRPC podspec. For
`gRPC-Core`, you will need to make sure that the completion queue you create is of type
`GRPC_CQ_NON_POLLING`. This is expected to be fixed soon so that you do not have to modify the
completion queue type.
## Notes
- Currently we do not support platforms other than iOS, although it is likely that this integration
can run on MacOS targets with Apple's compiler.
- Let us know if you meet any issue by filing issue and ping @muxi.

@ -548,4 +548,47 @@ static GRPCProtoMethod *kFullDuplexCallMethod;
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
}
- (void)testTimeoutBackoffWithTimeout:(double)timeout Backoff:(double)backoff {
const double maxConnectTime = timeout > backoff ? timeout : backoff;
const double kMargin = 0.1;
__weak XCTestExpectation *completion = [self expectationWithDescription:@"Timeout in a second."];
NSString *const kDummyAddress = [NSString stringWithFormat:@"8.8.8.8:1"];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kDummyAddress
path:@""
requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
[GRPCCall setMinConnectTimeout:timeout * 1000
initialBackoff:backoff * 1000
maxBackoff:0
forHost:kDummyAddress];
NSDate *startTime = [NSDate date];
id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(id value) {
XCTAssert(NO, @"Received message. Should not reach here");
}
completionHandler:^(NSError *errorOrNil) {
XCTAssertNotNil(errorOrNil, @"Finished with no error");
// The call must fail before maxConnectTime. However there is no lower bound on the time
// taken for connection. A shorter time happens when connection is actively refused
// by 8.8.8.8:1 before maxConnectTime elapsed.
XCTAssertLessThan([[NSDate date] timeIntervalSinceDate:startTime],
maxConnectTime + kMargin);
[completion fulfill];
}];
[call startWithWriteable:responsesWriteable];
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
}
// The numbers of the following three tests are selected to be smaller than the default values of
// initial backoff (1s) and min_connect_timeout (20s), so that if they fail we know the default
// values fail to be overridden by the channel args.
- (void)testTimeoutBackoff2 {
[self testTimeoutBackoffWithTimeout:0.7 Backoff:0.3];
}
- (void)testTimeoutBackoff3 {
[self testTimeoutBackoffWithTimeout:0.3 Backoff:0.7];
}
@end

@ -232,12 +232,13 @@ class BaseStub
*
* @return \Closure
*/
private function _GrpcUnaryUnary($channel, $deserialize)
private function _GrpcUnaryUnary($channel)
{
return function ($method,
$argument,
$deserialize,
array $metadata = [],
array $options = []) use ($channel, $deserialize) {
array $options = []) use ($channel) {
$call = new UnaryCall(
$channel,
$method,
@ -268,11 +269,12 @@ class BaseStub
*
* @return \Closure
*/
private function _GrpcStreamUnary($channel, $deserialize)
private function _GrpcStreamUnary($channel)
{
return function ($method,
$deserialize,
array $metadata = [],
array $options = []) use ($channel, $deserialize) {
array $options = []) use ($channel) {
$call = new ClientStreamingCall(
$channel,
$method,
@ -303,12 +305,13 @@ class BaseStub
*
* @return \Closure
*/
private function _GrpcUnaryStream($channel, $deserialize)
private function _GrpcUnaryStream($channel)
{
return function ($method,
$argument,
$deserialize,
array $metadata = [],
array $options = []) use ($channel, $deserialize) {
array $options = []) use ($channel) {
$call = new ServerStreamingCall(
$channel,
$method,
@ -339,11 +342,12 @@ class BaseStub
*
* @return \Closure
*/
private function _GrpcStreamStream($channel, $deserialize)
private function _GrpcStreamStream($channel)
{
return function ($method,
$deserialize,
array $metadata = [],
array $options = []) use ($channel ,$deserialize) {
array $options = []) use ($channel) {
$call = new BidiStreamingCall(
$channel,
$method,
@ -375,23 +379,25 @@ class BaseStub
*
* @return \Closure
*/
private function _UnaryUnaryCallFactory($channel, $deserialize)
private function _UnaryUnaryCallFactory($channel)
{
if (is_a($channel, 'Grpc\Internal\InterceptorChannel')) {
return function ($method,
$argument,
$deserialize,
array $metadata = [],
array $options = []) use ($channel, $deserialize) {
array $options = []) use ($channel) {
return $channel->getInterceptor()->interceptUnaryUnary(
$method,
$argument,
$deserialize,
$metadata,
$options,
$this->_UnaryUnaryCallFactory($channel->getNext(), $deserialize)
$this->_UnaryUnaryCallFactory($channel->getNext())
);
};
}
return $this->_GrpcUnaryUnary($channel, $deserialize);
return $this->_GrpcUnaryUnary($channel);
}
/**
@ -402,23 +408,25 @@ class BaseStub
*
* @return \Closure
*/
private function _UnaryStreamCallFactory($channel, $deserialize)
private function _UnaryStreamCallFactory($channel)
{
if (is_a($channel, 'Grpc\Internal\InterceptorChannel')) {
return function ($method,
$argument,
$deserialize,
array $metadata = [],
array $options = []) use ($channel, $deserialize) {
array $options = []) use ($channel) {
return $channel->getInterceptor()->interceptUnaryStream(
$method,
$argument,
$deserialize,
$metadata,
$options,
$this->_UnaryStreamCallFactory($channel->getNext(), $deserialize)
$this->_UnaryStreamCallFactory($channel->getNext())
);
};
}
return $this->_GrpcUnaryStream($channel, $deserialize);
return $this->_GrpcUnaryStream($channel);
}
/**
@ -429,21 +437,23 @@ class BaseStub
*
* @return \Closure
*/
private function _StreamUnaryCallFactory($channel, $deserialize)
private function _StreamUnaryCallFactory($channel)
{
if (is_a($channel, 'Grpc\Internal\InterceptorChannel')) {
return function ($method,
$deserialize,
array $metadata = [],
array $options = []) use ($channel, $deserialize) {
array $options = []) use ($channel) {
return $channel->getInterceptor()->interceptStreamUnary(
$method,
$deserialize,
$metadata,
$options,
$this->_StreamUnaryCallFactory($channel->getNext(), $deserialize)
$this->_StreamUnaryCallFactory($channel->getNext())
);
};
}
return $this->_GrpcStreamUnary($channel, $deserialize);
return $this->_GrpcStreamUnary($channel);
}
/**
@ -454,21 +464,23 @@ class BaseStub
*
* @return \Closure
*/
private function _StreamStreamCallFactory($channel, $deserialize)
private function _StreamStreamCallFactory($channel)
{
if (is_a($channel, 'Grpc\Internal\InterceptorChannel')) {
return function ($method,
$deserialize,
array $metadata = [],
array $options = []) use ($channel, $deserialize) {
array $options = []) use ($channel) {
return $channel->getInterceptor()->interceptStreamStream(
$method,
$deserialize,
$metadata,
$options,
$this->_StreamStreamCallFactory($channel->getNext(), $deserialize)
$this->_StreamStreamCallFactory($channel->getNext())
);
};
}
return $this->_GrpcStreamStream($channel, $deserialize);
return $this->_GrpcStreamStream($channel);
}
/* This class is intended to be subclassed by generated code, so
@ -493,8 +505,8 @@ class BaseStub
array $metadata = [],
array $options = []
) {
$call_factory = $this->_UnaryUnaryCallFactory($this->channel, $deserialize);
$call = $call_factory($method, $argument, $metadata, $options);
$call_factory = $this->_UnaryUnaryCallFactory($this->channel);
$call = $call_factory($method, $argument, $deserialize, $metadata, $options);
return $call;
}
@ -516,8 +528,8 @@ class BaseStub
array $metadata = [],
array $options = []
) {
$call_factory = $this->_StreamUnaryCallFactory($this->channel, $deserialize);
$call = $call_factory($method, $metadata, $options);
$call_factory = $this->_StreamUnaryCallFactory($this->channel);
$call = $call_factory($method, $deserialize, $metadata, $options);
return $call;
}
@ -541,8 +553,8 @@ class BaseStub
array $metadata = [],
array $options = []
) {
$call_factory = $this->_UnaryStreamCallFactory($this->channel, $deserialize);
$call = $call_factory($method, $argument, $metadata, $options);
$call_factory = $this->_UnaryStreamCallFactory($this->channel);
$call = $call_factory($method, $argument, $deserialize, $metadata, $options);
return $call;
}
@ -563,8 +575,8 @@ class BaseStub
array $metadata = [],
array $options = []
) {
$call_factory = $this->_StreamStreamCallFactory($this->channel, $deserialize);
$call = $call_factory($method, $metadata, $options);
$call_factory = $this->_StreamStreamCallFactory($this->channel);
$call = $call_factory($method, $deserialize, $metadata, $options);
return $call;
}
}

@ -21,6 +21,8 @@ namespace Grpc;
/**
* Represents an interceptor that intercept RPC invocations before call starts.
* There is one proposal related to the argument $deserialize under the review.
* The proposal link is https://github.com/grpc/proposal/pull/86.
* This is an EXPERIMENTAL API.
*/
class Interceptor
@ -28,39 +30,43 @@ class Interceptor
public function interceptUnaryUnary(
$method,
$argument,
$deserialize,
array $metadata = [],
array $options = [],
$continuation
) {
return $continuation($method, $argument, $metadata, $options);
return $continuation($method, $argument, $deserialize, $metadata, $options);
}
public function interceptStreamUnary(
$method,
$deserialize,
array $metadata = [],
array $options = [],
$continuation
) {
return $continuation($method, $metadata, $options);
return $continuation($method, $deserialize, $metadata, $options);
}
public function interceptUnaryStream(
$method,
$argument,
$deserialize,
array $metadata = [],
array $options = [],
$continuation
) {
return $continuation($method, $argument, $metadata, $options);
return $continuation($method, $argument, $deserialize, $metadata, $options);
}
public function interceptStreamStream(
$method,
$deserialize,
array $metadata = [],
array $options = [],
$continuation
) {
return $continuation($method, $metadata, $options);
return $continuation($method, $deserialize, $metadata, $options);
}
/**

@ -94,17 +94,18 @@ class ChangeMetadataInterceptor extends Grpc\Interceptor
{
public function interceptUnaryUnary($method,
$argument,
$deserialize,
array $metadata = [],
array $options = [],
$continuation)
{
$metadata["foo"] = array('interceptor_from_unary_request');
return $continuation($method, $argument, $metadata, $options);
return $continuation($method, $argument, $deserialize, $metadata, $options);
}
public function interceptStreamUnary($method, array $metadata = [], array $options = [], $continuation)
public function interceptStreamUnary($method, $deserialize, array $metadata = [], array $options = [], $continuation)
{
$metadata["foo"] = array('interceptor_from_stream_request');
return $continuation($method, $metadata, $options);
return $continuation($method, $deserialize, $metadata, $options);
}
}
@ -112,6 +113,7 @@ class ChangeMetadataInterceptor2 extends Grpc\Interceptor
{
public function interceptUnaryUnary($method,
$argument,
$deserialize,
array $metadata = [],
array $options = [],
$continuation)
@ -121,9 +123,10 @@ class ChangeMetadataInterceptor2 extends Grpc\Interceptor
} else {
$metadata["bar"] = array('interceptor_from_unary_request');
}
return $continuation($method, $argument, $metadata, $options);
return $continuation($method, $argument, $deserialize, $metadata, $options);
}
public function interceptStreamUnary($method,
$deserialize,
array $metadata = [],
array $options = [],
$continuation)
@ -133,7 +136,7 @@ class ChangeMetadataInterceptor2 extends Grpc\Interceptor
} else {
$metadata["bar"] = array('interceptor_from_stream_request');
}
return $continuation($method, $metadata, $options);
return $continuation($method, $deserialize, $metadata, $options);
}
}
@ -166,17 +169,18 @@ class ChangeRequestInterceptor extends Grpc\Interceptor
{
public function interceptUnaryUnary($method,
$argument,
$deserialize,
array $metadata = [],
array $options = [],
$continuation)
{
$argument->setData('intercepted_unary_request');
return $continuation($method, $argument, $metadata, $options);
return $continuation($method, $argument, $deserialize, $metadata, $options);
}
public function interceptStreamUnary($method, array $metadata = [], array $options = [], $continuation)
public function interceptStreamUnary($method, $deserialize, array $metadata = [], array $options = [], $continuation)
{
return new ChangeRequestCall(
$continuation($method, $metadata, $options)
$continuation($method, $deserialize, $metadata, $options)
);
}
}

@ -1,4 +1,4 @@
// Copyright 2018 gRPC authors.
// 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.
@ -12,20 +12,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// This file defines an interface for exporting monitoring information
// out of gRPC servers. See the full design at
// https://github.com/grpc/proposal/blob/master/A14-channelz.md
//
// The canonical version of this proto can be found at
// https://github.com/grpc/grpc-proto/blob/master/grpc/channelz/v1/channelz.proto
syntax = "proto3";
package grpc.channelz;
package grpc.channelz.v1;
import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
// See go/grpc-channelz.
option go_package = "google.golang.org/grpc/channelz/grpc_channelz_v1";
option java_multiple_files = true;
option java_package = "io.grpc.channelz.v1";
option java_outer_classname = "ChannelzProto";
// Channel is a logical grouping of channels, subchannels, and sockets.
message Channel {
// The identifier for this channel.
// The identifier for this channel. This should bet set.
ChannelRef ref = 1;
// Data specific to this channel.
ChannelData data = 2;
@ -43,7 +53,7 @@ message Channel {
repeated SubchannelRef subchannel_ref = 4;
// There are no ordering guarantees on the order of sockets.
repeated SocketRef socket = 5;
repeated SocketRef socket_ref = 5;
}
// Subchannel is a logical grouping of channels, subchannels, and sockets.
@ -67,7 +77,7 @@ message Subchannel {
repeated SubchannelRef subchannel_ref = 4;
// There are no ordering guarantees on the order of sockets.
repeated SocketRef socket = 5;
repeated SocketRef socket_ref = 5;
}
// These come from the specified states in this document:
@ -84,20 +94,23 @@ message ChannelConnectivityState {
State state = 1;
}
// Channel data is data related to a specific Channel or Subchannel.
message ChannelData {
// The connectivity state of the channel or subchannel. Implementations
// should always set this.
ChannelConnectivityState state = 1;
// The target this channel originally tried to connect to. May be absent
string target = 2;
// A trace of recent events on the channel. May be absent.
ChannelTrace trace = 3;
// The number of calls started on the channel
int64 calls_started = 4;
// The number of calls that have completed with an OK status
int64 calls_succeeded = 5;
// The number of calls that have a completed with a non-OK status
// The number of calls that have completed with a non-OK status
int64 calls_failed = 6;
// The last time a call was started on the channel.
@ -130,26 +143,29 @@ message ChannelTraceEvent {
}
}
// ChannelTrace represents the recent events that have occurred on the channel.
message ChannelTrace {
// Number of events ever logged in this tracing object. This can differ from
// events.size() because events can be overwritten or garbage collected by
// implementations.
int64 num_events_logged = 1;
// Time that this channel was created.
google.protobuf.Timestamp creation_time = 2;
google.protobuf.Timestamp creation_timestamp = 2;
// List of events that have occurred on this channel.
repeated ChannelTraceEvent events = 3;
}
// ChannelRef is a reference to a Channel.
message ChannelRef {
// The globally unique id for this channel. Must be a positive number.
int64 channel_id = 1;
// An optional name associated with the channel.
string name = 2;
// Intentionally don't use field numbers from other refs.
reserved 3, 4, 5, 6;
reserved 3, 4, 5, 6, 7, 8;
}
// ChannelRef is a reference to a Subchannel.
message SubchannelRef {
// The globally unique id for this subchannel. Must be a positive number.
int64 subchannel_id = 7;
@ -159,6 +175,7 @@ message SubchannelRef {
reserved 1, 2, 3, 4, 5, 6;
}
// SocketRef is a reference to a Socket.
message SocketRef {
int64 socket_id = 3;
// An optional name associated with the socket.
@ -167,8 +184,9 @@ message SocketRef {
reserved 1, 2, 5, 6, 7, 8;
}
// ServerRef is a reference to a Server.
message ServerRef {
// A globally unique identifier for this server. Must be a positive number.
// A globally unique identifier for this server. Must be a positive number.
int64 server_id = 5;
// An optional name associated with the server.
string name = 6;
@ -176,16 +194,22 @@ message ServerRef {
reserved 1, 2, 3, 4, 7, 8;
}
// Server represents a single server. There may be multiple servers in a single
// program.
message Server {
// The identifier for a Server. This should be set.
ServerRef ref = 1;
// The associated data of the Server.
ServerData data = 2;
// The sockets that the server is listening on. There are no ordering
// guarantees.
// guarantees. This may be absent.
repeated SocketRef listen_socket = 3;
}
// ServerData is data for a specific Server.
message ServerData {
// A trace of recent events on the server. May be absent.
ChannelTrace trace = 1;
// The number of incoming calls started on the server
@ -201,13 +225,17 @@ message ServerData {
// Information about an actual connection. Pronounced "sock-ay".
message Socket {
// The identifier for the Socket.
SocketRef ref = 1;
// Data specific to this Socket.
SocketData data = 2;
// The locally bound address.
Address local = 3;
// The remote bound address. May be absent.
Address remote = 4;
// Security details for this socket. May be absent if not available, or
// there is no security on the socket.
Security security = 5;
// Optional, represents the name of the remote endpoint, if different than
@ -215,17 +243,23 @@ message Socket {
string remote_name = 6;
}
// SocketData is data associated for a specific Socket. The fields present
// are specific to the implementation, so there may be minor differences in
// the semantics. (e.g. flow control windows)
message SocketData {
// The number of streams that have been started.
int64 streams_started = 1;
// The number of streams that have ended successfully with the EoS bit set for
// both end points
// The number of streams that have ended successfully:
// On client side, received frame with eos bit set;
// On server side, sent frame with eos bit set.
int64 streams_succeeded = 2;
// The number of incoming streams that have a completed with a non-OK status
// The number of streams that have ended unsuccessfully:
// On client side, ended without receiving frame with eos bit set;
// On server side, ended without sending frame with eos bit set.
int64 streams_failed = 3;
// The number of messages successfully sent on this socket.
// The number of grpc messages successfully sent on this socket.
int64 messages_sent = 4;
// The number of grpc messages received on this socket.
int64 messages_received = 5;
// The number of keep alives sent. This is typically implemented with HTTP/2
@ -254,12 +288,14 @@ message SocketData {
// include stream level or TCP level flow control info.
google.protobuf.Int64Value remote_flow_control_window = 12;
// Socket options set on this socket. May be absent.
repeated SocketOption option = 13;
}
// Address represents the address used to create the socket.
message Address {
message TcpIpAddress {
// Either the IPv4 or IPv6 address in bytes. Will either be 4 bytes or 16
// Either the IPv4 or IPv6 address in bytes. Will be either 4 bytes or 16
// bytes in length.
bytes ip_address = 1;
// 0-64k, or -1 if not appropriate.
@ -271,7 +307,7 @@ message Address {
}
// An address type not included above.
message OtherAddress {
// The human readable version of the value.
// The human readable version of the value. This value should be set.
string name = 1;
// The actual address message.
google.protobuf.Any value = 2;
@ -284,12 +320,17 @@ message Address {
}
}
// Security represents details about how secure the socket is.
message Security {
message Tls {
// The key exchange used. e.g. X25519
string key_exchange = 1;
// The cipher used. e.g. AES_128_GCM.
string cipher = 2;
oneof cipher_suite {
// The cipher suite name in the RFC 4346 format:
// https://tools.ietf.org/html/rfc4346#appendix-C
string standard_name = 1;
// Some other way to describe the cipher suite if
// the RFC 4346 name is not available.
string other_name = 2;
}
// the certificate used by this endpoint.
bytes local_certificate = 3;
// the certificate used by the remote endpoint.
@ -307,7 +348,11 @@ message Security {
}
}
// SocketOption represents socket options for a socket. Specifically, these
// are the options returned by getsockopt().
message SocketOption {
// The full name of the socket option. Typically this will be the upper case
// name, such as "SO_REUSEPORT".
string name = 1;
// The human readable value of this socket option. At least one of value or
// additional will be set.
@ -323,12 +368,17 @@ message SocketOptionTimeout {
google.protobuf.Duration duration = 1;
}
// For use with SocketOption's additional field. This is primarily used for
// SO_LINGER.
message SocketOptionLinger {
// active maps to `struct linger.l_onoff`
bool active = 1;
// duration maps to `struct linger.l_linger`
google.protobuf.Duration duration = 2;
}
// Tcp info for SOL_TCP, TCP_INFO
// For use with SocketOption's additional field. Tcp info for
// SOL_TCP and TCP_INFO.
message SocketOptionTcpInfo {
uint32 tcpi_state = 1;
@ -366,8 +416,10 @@ message SocketOptionTcpInfo {
uint32 tcpi_reordering = 29;
}
// Channelz is a service exposed by gRPC servers that provides detailed debug
// information.
service Channelz {
// Gets all root channels (e.g. channels the application has directly
// Gets all root channels (i.e. channels the application has directly
// created). This does not include subchannels nor non-top level channels.
rpc GetTopChannels(GetTopChannelsRequest) returns (GetTopChannelsResponse);
// Gets all servers that exist in the process.
@ -382,6 +434,22 @@ service Channelz {
rpc GetSocket(GetSocketRequest) returns (GetSocketResponse);
}
message GetTopChannelsRequest {
// start_channel_id indicates that only channels at or above this id should be
// included in the results.
int64 start_channel_id = 1;
}
message GetTopChannelsResponse {
// list of channels that the connection detail service knows about. Sorted in
// ascending channel_id order.
repeated Channel channel = 1;
// If set, indicates that the list of channels is the final list. Requesting
// more channels can only return more if they are created after this RPC
// completes.
bool end = 2;
}
message GetServersRequest {
// start_server_id indicates that only servers at or above this id should be
// included in the results.
@ -415,42 +483,35 @@ message GetServerSocketsResponse {
bool end = 2;
}
message GetTopChannelsRequest {
// start_channel_id indicates that only channels at or above this id should be
// included in the results.
int64 start_channel_id = 1;
}
message GetTopChannelsResponse {
// list of channels that the connection detail service knows about. Sorted in
// ascending channel_id order.
repeated Channel channel = 1;
// If set, indicates that the list of channels is the final list. Requesting
// more channels can only return more if they are created after this RPC
// completes.
bool end = 2;
}
message GetChannelRequest {
// channel_id is the identifier of the specific channel to get.
int64 channel_id = 1;
}
message GetChannelResponse {
// The Channel that corresponds to the requested channel_id. This field
// should be set.
Channel channel = 1;
}
message GetSubchannelRequest {
// subchannel_id is the identifier of the specific subchannel to get.
int64 subchannel_id = 1;
}
message GetSubchannelResponse {
// The Subchannel that corresponds to the requested subchannel_id. This
// field should be set.
Subchannel subchannel = 1;
}
message GetSocketRequest {
// socket_id is the identifier of the specific socket to get.
int64 socket_id = 1;
}
message GetSocketResponse {
// The Socket that corresponds to the requested socket_id. This field
// should be set.
Socket socket = 1;
}

@ -14,11 +14,24 @@
licenses(["notice"]) # Apache v2
load("//bazel:grpc_build_system.bzl", "grpc_proto_library", "grpc_package")
load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
grpc_package(name = "lb", visibility = "public")
grpc_package(
name = "lb",
visibility = "public",
)
grpc_proto_library(
name = "load_balancer_proto",
srcs = ["load_balancer.proto"],
srcs = [
"load_balancer.proto",
],
well_known_protos = True,
)
grpc_proto_library(
name = "load_reporter_proto",
srcs = ["load_reporter.proto"],
has_services = True,
well_known_protos = True,
)

@ -1,4 +1,4 @@
// Copyright 2016 gRPC authors.
// Copyright 2015 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.
@ -12,42 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// This file defines the GRPCLB LoadBalancing protocol.
//
// The canonical version of this proto can be found at
// https://github.com/grpc/grpc-proto/blob/master/grpc/lb/v1/load_balancer.proto
syntax = "proto3";
package grpc.lb.v1;
message Duration {
// Signed seconds of the span of time. Must be from -315,576,000,000
// to +315,576,000,000 inclusive.
int64 seconds = 1;
// Signed fractions of a second at nanosecond resolution of the span
// of time. Durations less than one second are represented with a 0
// `seconds` field and a positive or negative `nanos` field. For durations
// of one second or more, a non-zero value for the `nanos` field must be
// of the same sign as the `seconds` field. Must be from -999,999,999
// to +999,999,999 inclusive.
int32 nanos = 2;
}
message Timestamp {
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
// Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive.
int64 seconds = 1;
// Non-negative fractions of a second at nanosecond resolution. Negative
// second values with fractions must still have non-negative nanos values
// that count forward in time. Must be from 0 to 999,999,999
// inclusive.
int32 nanos = 2;
}
option go_package = "google.golang.org/grpc/balancer/grpclb/grpc_lb_v1";
option java_multiple_files = true;
option java_outer_classname = "LoadBalancerProto";
option java_package = "io.grpc.grpclb";
service LoadBalancer {
// Bidirectional rpc to get a list of servers.
rpc BalanceLoad(stream LoadBalanceRequest)
returns (stream LoadBalanceResponse);
rpc BalanceLoad(stream LoadBalanceRequest) returns (stream LoadBalanceResponse);
}
message LoadBalanceRequest {
@ -62,8 +45,8 @@ message LoadBalanceRequest {
}
message InitialLoadBalanceRequest {
// The name of the load balanced service (e.g., balancer.service.com). The max
// length of the name is 256 bytes.
// The name of the load balanced service (e.g., service.googleapis.com). Its
// length should be less than 256 bytes.
// The name might include a port number. How to handle the port number is up
// to the balancer.
string name = 1;
@ -82,7 +65,7 @@ message ClientStatsPerToken {
// count except the timestamp should be reset to zero after reporting the stats.
message ClientStats {
// The timestamp of generating the report.
Timestamp timestamp = 1;
google.protobuf.Timestamp timestamp = 1;
// The total number of RPCs that started.
int64 num_calls_started = 2;
@ -125,7 +108,7 @@ message InitialLoadBalanceResponse {
// This interval defines how often the client should send the client stats
// to the load balancer. Stats should only be reported when the duration is
// positive.
Duration client_stats_report_interval = 2;
google.protobuf.Duration client_stats_report_interval = 2;
}
message ServerList {
@ -149,13 +132,13 @@ message Server {
// A resolved port number for the server.
int32 port = 2;
// An opaque but printable token given to the frontend for each pick. All
// frontend requests for that pick must include the token in its initial
// metadata. The token is used by the backend to verify the request and to
// allow the backend to report load to the gRPC LB system. The token is also
// used in client stats for reporting dropped calls.
// An opaque but printable token for load reporting. The client must include
// the token of the picked server into the initial metadata when it starts a
// call to that server. The token is used by the server to verify the request
// and to allow the server to report load to the gRPC LB system. The token is
// also used in client stats for reporting dropped calls.
//
// Its length is variable but less than 50 bytes.
// Its length can be variable but must be less than 50 bytes.
string load_balance_token = 3;
// Indicates whether this particular request should be dropped by the client.

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

Loading…
Cancel
Save