aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--BUILD43
-rw-r--r--BUILDING.md (renamed from INSTALL.md)110
-rw-r--r--CMakeLists.txt189
-rw-r--r--CONCEPTS.md63
-rw-r--r--CONTRIBUTING.md31
-rw-r--r--Makefile207
-rw-r--r--README.md120
-rw-r--r--bazel/grpc_build_system.bzl3
-rw-r--r--bazel/grpc_deps.bzl41
-rw-r--r--build.yaml68
-rw-r--r--config.m410
-rw-r--r--config.w3213
-rw-r--r--doc/command_line_tool.md2
-rw-r--r--examples/cpp/README.md2
-rw-r--r--examples/cpp/cpptutorial.md4
-rw-r--r--examples/cpp/helloworld/README.md4
-rw-r--r--examples/cpp/route_guide/README.md6
-rw-r--r--gRPC-C++.podspec2
-rw-r--r--gRPC-Core.podspec6
-rw-r--r--grpc.def2
-rw-r--r--grpc.gemspec4
-rw-r--r--grpc.gyp20
-rw-r--r--include/grpc/grpc.h8
-rw-r--r--include/grpc/grpc_security.h31
-rw-r--r--include/grpc/impl/codegen/grpc_types.h4
-rw-r--r--include/grpcpp/impl/codegen/call.h4
-rw-r--r--include/grpcpp/opencensus.h41
-rw-r--r--package.xml4
-rw-r--r--src/core/ext/filters/client_channel/client_channel.cc1004
-rw-r--r--src/core/ext/filters/deadline/deadline_filter.cc28
-rw-r--r--src/core/ext/filters/deadline/deadline_filter.h10
-rw-r--r--src/core/ext/filters/http/client/http_client_filter.cc19
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.cc35
-rw-r--r--src/core/ext/transport/chttp2/transport/writing.cc37
-rw-r--r--src/core/ext/transport/cronet/transport/cronet_transport.cc19
-rw-r--r--src/core/ext/transport/inproc/inproc_transport.cc52
-rw-r--r--src/core/lib/channel/channel_trace.cc49
-rw-r--r--src/core/lib/channel/channel_trace.h30
-rw-r--r--src/core/lib/channel/channelz.cc185
-rw-r--r--src/core/lib/channel/channelz.h85
-rw-r--r--src/core/lib/channel/connected_channel.cc9
-rw-r--r--src/core/lib/gprpp/inlined_vector.h2
-rw-r--r--src/core/lib/iomgr/call_combiner.h80
-rw-r--r--src/core/lib/iomgr/closure.h5
-rw-r--r--src/core/lib/iomgr/socket_utils.h9
-rw-r--r--src/core/lib/iomgr/socket_utils_common_posix.cc4
-rw-r--r--src/core/lib/iomgr/socket_utils_uv.cc4
-rw-r--r--src/core/lib/iomgr/socket_utils_windows.cc4
-rw-r--r--src/core/lib/security/credentials/google_default/google_default_credentials.cc3
-rw-r--r--src/core/lib/security/credentials/ssl/ssl_credentials.cc20
-rw-r--r--src/core/lib/security/security_connector/security_connector.cc35
-rw-r--r--src/core/lib/security/security_connector/security_connector.h1
-rw-r--r--src/core/lib/surface/call.cc108
-rw-r--r--src/core/lib/surface/channel.cc33
-rw-r--r--src/core/lib/surface/channel.h4
-rw-r--r--src/core/lib/transport/transport.cc29
-rw-r--r--src/core/lib/transport/transport.h22
-rw-r--r--src/core/lib/transport/transport_op_string.cc7
-rw-r--r--src/cpp/README.md64
-rw-r--r--src/cpp/client/secure_credentials.cc3
-rw-r--r--src/cpp/ext/filters/census/channel_filter.cc (renamed from test/core/statistics/performance_test.cc)19
-rw-r--r--src/cpp/ext/filters/census/channel_filter.h (renamed from test/core/statistics/multiple_writers_test.cc)27
-rw-r--r--src/cpp/ext/filters/census/client_filter.cc165
-rw-r--r--src/cpp/ext/filters/census/client_filter.h104
-rw-r--r--src/cpp/ext/filters/census/context.cc132
-rw-r--r--src/cpp/ext/filters/census/context.h126
-rw-r--r--src/cpp/ext/filters/census/grpc_context.cc (renamed from src/core/ext/census/grpc_context.cc)0
-rw-r--r--src/cpp/ext/filters/census/grpc_plugin.cc130
-rw-r--r--src/cpp/ext/filters/census/grpc_plugin.h111
-rw-r--r--src/cpp/ext/filters/census/measures.cc129
-rw-r--r--src/cpp/ext/filters/census/measures.h46
-rw-r--r--src/cpp/ext/filters/census/rpc_encoding.cc39
-rw-r--r--src/cpp/ext/filters/census/rpc_encoding.h284
-rw-r--r--src/cpp/ext/filters/census/server_filter.cc198
-rw-r--r--src/cpp/ext/filters/census/server_filter.h101
-rw-r--r--src/cpp/ext/filters/census/views.cc491
-rw-r--r--src/csharp/Grpc.Core/Interceptors/CallInvokerExtensions.cs1
-rw-r--r--src/csharp/Grpc.Core/Interceptors/ChannelExtensions.cs1
-rw-r--r--src/csharp/Grpc.Core/Interceptors/ClientInterceptorContext.cs1
-rw-r--r--src/csharp/Grpc.Core/Interceptors/Interceptor.cs1
-rw-r--r--src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs3
-rw-r--r--src/csharp/README.md4
-rw-r--r--src/csharp/ext/grpc_csharp_ext.c5
-rw-r--r--src/objective-c/GRPCClient/private/GRPCHost.m4
-rw-r--r--src/php/ext/grpc/channel_credentials.c2
-rw-r--r--src/proto/census/census.options3
-rw-r--r--src/proto/census/census.proto307
-rw-r--r--src/proto/census/trace_context.options0
-rw-r--r--src/proto/census/trace_context.proto29
-rw-r--r--src/proto/grpc/channelz/channelz.proto143
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi4
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi7
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py3
-rw-r--r--src/python/grpcio_testing/MANIFEST.in3
-rw-r--r--src/python/grpcio_testing/README.rst10
-rwxr-xr-xsrc/ruby/end2end/multiple_killed_watching_threads_driver.rb4
-rw-r--r--src/ruby/end2end/package_with_underscore_checker.rb54
-rw-r--r--src/ruby/end2end/protos/package_with_underscore/data.proto (renamed from src/ruby/spec/pb/package_with_underscore/data.proto)0
-rw-r--r--src/ruby/end2end/protos/package_with_underscore/service.proto (renamed from src/ruby/spec/pb/package_with_underscore/service.proto)0
-rw-r--r--src/ruby/ext/grpc/rb_channel_credentials.c6
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.c4
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.h8
-rw-r--r--src/ruby/lib/grpc/generic/active_call.rb2
-rw-r--r--src/ruby/spec/call_credentials_spec.rb2
-rw-r--r--src/ruby/spec/call_spec.rb2
-rw-r--r--src/ruby/spec/channel_credentials_spec.rb2
-rw-r--r--src/ruby/spec/channel_spec.rb2
-rw-r--r--src/ruby/spec/client_auth_spec.rb13
-rw-r--r--src/ruby/spec/client_server_spec.rb2
-rw-r--r--src/ruby/spec/compression_options_spec.rb2
-rw-r--r--src/ruby/spec/error_sanity_spec.rb2
-rw-r--r--src/ruby/spec/generic/client_stub_spec.rb2
-rw-r--r--src/ruby/spec/generic/rpc_desc_spec.rb2
-rw-r--r--src/ruby/spec/generic/rpc_server_pool_spec.rb2
-rw-r--r--src/ruby/spec/generic/service_spec.rb2
-rw-r--r--src/ruby/spec/google_rpc_status_utils_spec.rb13
-rw-r--r--src/ruby/spec/pb/duplicate/codegen_spec.rb1
-rw-r--r--src/ruby/spec/pb/health/checker_spec.rb2
-rw-r--r--src/ruby/spec/pb/package_with_underscore/checker_spec.rb51
-rw-r--r--src/ruby/spec/server_credentials_spec.rb2
-rw-r--r--src/ruby/spec/server_spec.rb2
-rw-r--r--src/ruby/spec/spec_helper.rb1
-rw-r--r--src/ruby/spec/support/services.rb2
-rw-r--r--src/ruby/spec/time_consts_spec.rb2
-rw-r--r--templates/CMakeLists.txt.template6
-rw-r--r--templates/config.m4.template5
-rw-r--r--templates/config.w32.template5
-rw-r--r--test/core/bad_ssl/bad_ssl_test.cc2
-rw-r--r--test/core/channel/BUILD18
-rw-r--r--test/core/channel/channel_trace_test.cc196
-rw-r--r--test/core/channel/channelz_test.cc216
-rw-r--r--test/core/end2end/end2end_nosec_tests.cc8
-rw-r--r--test/core/end2end/end2end_tests.cc8
-rw-r--r--test/core/end2end/fixtures/h2_oauth2.cc2
-rw-r--r--test/core/end2end/fixtures/h2_ssl.cc2
-rw-r--r--test/core/end2end/fixtures/h2_ssl_proxy.cc4
-rw-r--r--test/core/end2end/fuzzers/api_fuzzer.cc3
-rwxr-xr-xtest/core/end2end/gen_build_yaml.py1
-rwxr-xr-xtest/core/end2end/generate_tests.bzl1
-rw-r--r--test/core/end2end/h2_ssl_cert_test.cc4
-rw-r--r--test/core/end2end/h2_ssl_session_reuse_test.cc2
-rw-r--r--test/core/end2end/tests/channelz.cc299
-rw-r--r--test/core/gprpp/inlined_vector_test.cc2
-rw-r--r--test/core/handshake/BUILD18
-rw-r--r--test/core/handshake/client_ssl.cc4
-rw-r--r--test/core/handshake/verify_peer_options.cc275
-rw-r--r--test/core/security/BUILD4
-rw-r--r--test/core/statistics/census_log_tests.h36
-rw-r--r--test/core/statistics/census_stub_test.cc62
-rw-r--r--test/core/statistics/multiple_writers_circular_buffer_test.cc31
-rw-r--r--test/core/statistics/quick_test.cc39
-rw-r--r--test/core/statistics/rpc_stats_test.cc183
-rw-r--r--test/core/statistics/small_log_test.cc31
-rw-r--r--test/core/surface/num_external_connectivity_watchers_test.cc2
-rw-r--r--test/core/surface/public_headers_must_be_c89.c2
-rw-r--r--test/core/surface/sequential_connectivity_test.cc2
-rw-r--r--test/core/transport/BUILD1
-rw-r--r--test/core/tsi/alts/crypt/BUILD1
-rw-r--r--test/core/tsi/alts/frame_protector/BUILD4
-rw-r--r--test/core/tsi/alts/handshaker/BUILD5
-rw-r--r--test/core/tsi/alts/zero_copy_frame_protector/BUILD3
-rw-r--r--test/core/util/BUILD5
-rw-r--r--test/core/util/lsan_suppressions.txt (renamed from tools/lsan_suppressions.txt)0
-rw-r--r--test/core/util/tsan_suppressions.txt (renamed from tools/tsan_suppressions.txt)0
-rw-r--r--test/core/util/ubsan_suppressions.txt (renamed from tools/ubsan_suppressions.txt)0
-rw-r--r--test/cpp/client/BUILD1
-rw-r--r--test/cpp/ext/filters/census/BUILD42
-rw-r--r--test/cpp/ext/filters/census/stats_plugin_end2end_test.cc376
-rw-r--r--test/cpp/microbenchmarks/BUILD13
-rw-r--r--test/cpp/microbenchmarks/bm_call_create.cc24
-rw-r--r--test/cpp/microbenchmarks/bm_opencensus_plugin.cc118
-rw-r--r--test/cpp/util/BUILD2
-rw-r--r--test/cpp/util/channel_trace_proto_helper.cc41
-rw-r--r--test/cpp/util/channel_trace_proto_helper.h1
-rwxr-xr-xtest/distrib/python/test_packages.sh16
-rw-r--r--tools/bazel.rc6
-rw-r--r--tools/doxygen/Doxyfile.c++.internal1
-rw-r--r--tools/doxygen/Doxyfile.core.internal4
-rw-r--r--tools/internal_ci/linux/grpc_tsan_on_foundry.sh2
-rwxr-xr-xtools/run_tests/artifacts/build_artifact_python.sh8
-rw-r--r--tools/run_tests/generated/configs.json8
-rw-r--r--tools/run_tests/generated/sources_and_headers.json85
-rw-r--r--tools/run_tests/generated/tests.json857
-rwxr-xr-xtools/run_tests/helper_scripts/build_ruby.sh3
-rwxr-xr-xtools/run_tests/helper_scripts/run_ruby.sh3
-rwxr-xr-xtools/run_tests/helper_scripts/run_ruby_end2end_tests.sh21
-rw-r--r--tools/run_tests/python_utils/filter_pull_request_tests.py2
-rw-r--r--tools/run_tests/python_utils/upload_rbe_results.py2
-rwxr-xr-xtools/run_tests/run_tests.py2
-rwxr-xr-xtools/run_tests/sanity/check_bazel_workspace.py2
-rw-r--r--vsprojects/.gitignore12
-rw-r--r--vsprojects/README.md11
192 files changed, 6682 insertions, 2336 deletions
diff --git a/BUILD b/BUILD
index 44b877705e..0cbf9a9884 100644
--- a/BUILD
+++ b/BUILD
@@ -485,10 +485,7 @@ grpc_cc_library(
grpc_cc_library(
name = "census",
srcs = [
- "src/core/ext/census/grpc_context.cc",
- ],
- external_deps = [
- "nanopb",
+ "src/cpp/ext/filters/census/grpc_context.cc",
],
language = "c++",
public_hdrs = [
@@ -679,6 +676,7 @@ grpc_cc_library(
"src/core/lib/channel/channel_stack_builder.cc",
"src/core/lib/channel/channel_trace.cc",
"src/core/lib/channel/channelz_registry.cc",
+ "src/core/lib/channel/channelz.cc",
"src/core/lib/channel/connected_channel.cc",
"src/core/lib/channel/handshaker.cc",
"src/core/lib/channel/handshaker_factory.cc",
@@ -826,6 +824,7 @@ grpc_cc_library(
"src/core/lib/channel/channel_stack_builder.h",
"src/core/lib/channel/channel_trace.h",
"src/core/lib/channel/channelz_registry.h",
+ "src/core/lib/channel/channelz.h",
"src/core/lib/channel/connected_channel.h",
"src/core/lib/channel/context.h",
"src/core/lib/channel/handshaker.h",
@@ -1990,4 +1989,40 @@ 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/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/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/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",
+ ],
+ language = "c++",
+ external_deps = [
+ "absl-base",
+ "absl-time",
+ "opencensus-trace",
+ "opencensus-stats",
+ ],
+ deps = [
+ ":census",
+ ":grpc++",
+ ],
+)
+
grpc_generate_one_off_targets()
diff --git a/INSTALL.md b/BUILDING.md
index a61af3479c..e1d63a7461 100644
--- a/INSTALL.md
+++ b/BUILDING.md
@@ -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.*
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4dc8d98b87..6ac0ec181a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,6 +39,7 @@ set(gRPC_INSTALL_SHAREDIR "share/grpc" CACHE STRING "Installation directory for
# Options
option(gRPC_BUILD_TESTS "Build tests" OFF)
option(gRPC_BUILD_CODEGEN "Build codegen" ON)
+option(gRPC_BUILD_CSHARP_EXT "Build C# extensions" ON)
set(gRPC_INSTALL_default ON)
if (NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
@@ -309,6 +310,9 @@ endif()
if(_gRPC_PLATFORM_LINUX)
add_dependencies(buildtests_c handshake_server_with_readahead_handshaker)
endif()
+if(_gRPC_PLATFORM_LINUX)
+add_dependencies(buildtests_c handshake_verify_peer_options)
+endif()
add_dependencies(buildtests_c histogram_test)
add_dependencies(buildtests_c hpack_parser_test)
add_dependencies(buildtests_c hpack_table_test)
@@ -540,6 +544,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)
@@ -591,7 +596,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)
@@ -932,6 +936,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
@@ -1221,7 +1226,7 @@ add_library(grpc
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/core/ext/census/grpc_context.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
src/core/ext/filters/http/client_authority_filter.cc
@@ -1327,6 +1332,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
@@ -1713,6 +1719,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
@@ -2018,6 +2025,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
@@ -2302,6 +2310,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
@@ -2524,7 +2533,7 @@ add_library(grpc_unsecure
third_party/nanopb/pb_encode.c
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
- src/core/ext/census/grpc_context.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
src/core/ext/filters/http/client_authority_filter.cc
@@ -3134,6 +3143,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
@@ -3307,10 +3317,7 @@ add_library(grpc++_cronet
src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc
src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc
src/core/ext/transport/chttp2/server/chttp2_server.cc
- src/core/ext/census/grpc_context.cc
- third_party/nanopb/pb_common.c
- third_party/nanopb/pb_decode.c
- third_party/nanopb/pb_encode.c
+ src/cpp/ext/filters/census/grpc_context.cc
)
if(WIN32 AND MSVC)
@@ -5020,50 +5027,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)
-
if (gRPC_BUILD_CODEGEN)
add_library(qps
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
@@ -5170,6 +5133,7 @@ target_link_libraries(qps
endif (gRPC_BUILD_CODEGEN)
endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_CSHARP_EXT)
add_library(grpc_csharp_ext SHARED
src/csharp/ext/grpc_csharp_ext.c
@@ -5216,6 +5180,7 @@ if (gRPC_INSTALL)
)
endif()
+endif (gRPC_BUILD_CSHARP_EXT)
if (gRPC_BUILD_TESTS)
add_library(bad_client_test
@@ -5316,6 +5281,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
@@ -5436,6 +5402,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
@@ -7494,6 +7461,38 @@ target_link_libraries(handshake_server_with_readahead_handshaker
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX)
+
+add_executable(handshake_verify_peer_options
+ test/core/handshake/verify_peer_options.cc
+)
+
+
+target_include_directories(handshake_verify_peer_options
+ 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(handshake_verify_peer_options
+ ${_gRPC_SSL_LIBRARIES}
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ grpc_test_util
+ grpc
+ gpr_test_util
+ gpr
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
add_executable(histogram_test
test/core/util/histogram_test.cc
@@ -10766,6 +10765,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
@@ -12644,47 +12690,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
diff --git a/CONCEPTS.md b/CONCEPTS.md
new file mode 100644
index 0000000000..034d58e427
--- /dev/null
+++ b/CONCEPTS.md
@@ -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.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2f90ccf281..abd7a5eb78 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -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
diff --git a/Makefile b/Makefile
index ab6045191d..71bcff8241 100644
--- a/Makefile
+++ b/Makefile
@@ -1012,6 +1012,7 @@ grpc_verify_jwt: $(BINDIR)/$(CONFIG)/grpc_verify_jwt
handshake_client: $(BINDIR)/$(CONFIG)/handshake_client
handshake_server: $(BINDIR)/$(CONFIG)/handshake_server
handshake_server_with_readahead_handshaker: $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker
+handshake_verify_peer_options: $(BINDIR)/$(CONFIG)/handshake_verify_peer_options
histogram_test: $(BINDIR)/$(CONFIG)/histogram_test
hpack_parser_fuzzer_test: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test
hpack_parser_test: $(BINDIR)/$(CONFIG)/hpack_parser_test
@@ -1121,6 +1122,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
@@ -1165,7 +1167,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
@@ -1381,9 +1382,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
@@ -1454,6 +1455,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/handshake_client \
$(BINDIR)/$(CONFIG)/handshake_server \
$(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker \
+ $(BINDIR)/$(CONFIG)/handshake_verify_peer_options \
$(BINDIR)/$(CONFIG)/histogram_test \
$(BINDIR)/$(CONFIG)/hpack_parser_test \
$(BINDIR)/$(CONFIG)/hpack_table_test \
@@ -1617,6 +1619,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 \
@@ -1654,7 +1657,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 \
@@ -1793,6 +1795,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 \
@@ -1830,7 +1833,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 \
@@ -2009,6 +2011,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/handshake_server || ( echo test handshake_server failed ; exit 1 )
$(E) "[RUN] Testing handshake_server_with_readahead_handshaker"
$(Q) $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker || ( echo test handshake_server_with_readahead_handshaker failed ; exit 1 )
+ $(E) "[RUN] Testing handshake_verify_peer_options"
+ $(Q) $(BINDIR)/$(CONFIG)/handshake_verify_peer_options || ( echo test handshake_verify_peer_options failed ; exit 1 )
$(E) "[RUN] Testing histogram_test"
$(Q) $(BINDIR)/$(CONFIG)/histogram_test || ( echo test histogram_test failed ; exit 1 )
$(E) "[RUN] Testing hpack_parser_test"
@@ -2229,6 +2233,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"
@@ -2289,8 +2295,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"
@@ -3307,6 +3311,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 \
@@ -3596,7 +3601,7 @@ LIBGRPC_SRC = \
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/core/ext/census/grpc_context.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 \
src/core/ext/filters/http/client_authority_filter.cc \
@@ -3701,6 +3706,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 \
@@ -4085,6 +4091,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 \
@@ -4381,6 +4388,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 \
@@ -4643,6 +4651,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 \
@@ -4865,7 +4874,7 @@ LIBGRPC_UNSECURE_SRC = \
third_party/nanopb/pb_encode.c \
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
- src/core/ext/census/grpc_context.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 \
src/core/ext/filters/http/client_authority_filter.cc \
@@ -5463,6 +5472,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 \
@@ -5636,10 +5646,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc \
src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc \
src/core/ext/transport/chttp2/server/chttp2_server.cc \
- src/core/ext/census/grpc_context.cc \
- third_party/nanopb/pb_common.c \
- third_party/nanopb/pb_decode.c \
- third_party/nanopb/pb_encode.c \
+ src/cpp/ext/filters/census/grpc_context.cc \
PUBLIC_HEADERS_CXX += \
include/grpc++/alarm.h \
@@ -7219,55 +7226,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 \
@@ -9973,6 +9931,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 \
@@ -10090,6 +10049,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 \
@@ -12472,6 +12432,38 @@ endif
endif
+HANDSHAKE_VERIFY_PEER_OPTIONS_SRC = \
+ test/core/handshake/verify_peer_options.cc \
+
+HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HANDSHAKE_VERIFY_PEER_OPTIONS_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/handshake_verify_peer_options: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/handshake_verify_peer_options: $(HANDSHAKE_VERIFY_PEER_OPTIONS_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) $(HANDSHAKE_VERIFY_PEER_OPTIONS_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)/handshake_verify_peer_options
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/handshake/verify_peer_options.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_handshake_verify_peer_options: $(HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(HANDSHAKE_VERIFY_PEER_OPTIONS_OBJS:.o=.dep)
+endif
+endif
+
+
HISTOGRAM_TEST_SRC = \
test/core/util/histogram_test.cc \
@@ -16391,6 +16383,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 \
@@ -18238,49 +18277,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 \
@@ -24316,7 +24312,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)
diff --git a/README.md b/README.md
index 21a9910e3e..23964e7fc6 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl
index 0a1edeb31c..73147bf3ac 100644
--- a/bazel/grpc_build_system.bzl
+++ b/bazel/grpc_build_system.bzl
@@ -60,7 +60,7 @@ def _maybe_update_cc_library_hdrs(hdrs):
def grpc_cc_library(name, srcs = [], public_hdrs = [], hdrs = [],
external_deps = [], deps = [], standalone = False,
language = "C++", testonly = False, visibility = None,
- alwayslink = 0):
+ alwayslink = 0, data = []):
copts = []
if language.upper() == "C":
copts = if_not_windows(["-std=c99"])
@@ -85,6 +85,7 @@ def grpc_cc_library(name, srcs = [], public_hdrs = [], hdrs = [],
"include"
],
alwayslink = alwayslink,
+ data = data,
)
def grpc_proto_plugin(name, srcs = [], deps = []):
diff --git a/bazel/grpc_deps.bzl b/bazel/grpc_deps.bzl
index f7e62f1219..7c349dbcdc 100644
--- a/bazel/grpc_deps.bzl
+++ b/bazel/grpc_deps.bzl
@@ -9,6 +9,16 @@ def grpc_deps():
)
native.bind(
+ name = "absl-base",
+ actual = "@com_google_absl//absl/base",
+ )
+
+ native.bind(
+ name = "absl-time",
+ actual = "@com_google_absl//absl/time:time",
+ )
+
+ native.bind(
name = "libssl",
actual = "@boringssl//:ssl",
)
@@ -73,6 +83,21 @@ def grpc_deps():
actual = "@com_github_grpc_grpc//:grpc++_codegen_proto",
)
+ native.bind(
+ name = "opencensus-trace",
+ actual = "@io_opencensus_cpp//opencensus/trace:trace"
+ )
+
+ native.bind(
+ name = "opencensus-stats",
+ actual = "@io_opencensus_cpp//opencensus/stats:stats"
+ )
+
+ native.bind(
+ name = "opencensus-stats-test",
+ actual = "@io_opencensus_cpp//opencensus/stats:test_utils"
+ )
+
if "boringssl" not in native.existing_rules():
native.http_archive(
name = "boringssl",
@@ -122,8 +147,8 @@ def grpc_deps():
native.new_http_archive(
name = "com_github_google_benchmark",
build_file = "@com_github_grpc_grpc//third_party:benchmark.BUILD",
- strip_prefix = "benchmark-5b7683f49e1e9223cf9927b24f6fd3d6bd82e3f8",
- url = "https://github.com/google/benchmark/archive/5b7683f49e1e9223cf9927b24f6fd3d6bd82e3f8.tar.gz",
+ strip_prefix = "benchmark-9913418d323e64a0111ca0da81388260c2bbe1e9",
+ url = "https://github.com/google/benchmark/archive/9913418d323e64a0111ca0da81388260c2bbe1e9.tar.gz",
)
if "com_github_cares_cares" not in native.existing_rules():
@@ -137,8 +162,8 @@ def grpc_deps():
if "com_google_absl" not in native.existing_rules():
native.http_archive(
name = "com_google_absl",
- strip_prefix = "abseil-cpp-cc4bed2d74f7c8717e31f9579214ab52a9c9c610",
- url = "https://github.com/abseil/abseil-cpp/archive/cc4bed2d74f7c8717e31f9579214ab52a9c9c610.tar.gz",
+ strip_prefix = "abseil-cpp-cd95e71df6eaf8f2a282b1da556c2cf1c9b09207",
+ url = "https://github.com/abseil/abseil-cpp/archive/cd95e71df6eaf8f2a282b1da556c2cf1c9b09207.tar.gz",
)
if "com_github_bazelbuild_bazeltoolchains" not in native.existing_rules():
@@ -152,6 +177,14 @@ def grpc_deps():
sha256 = "1c4a532b396c698e6467a1548554571cb85fa091e472b05e398ebc836c315d77",
)
+ if "io_opencensus_cpp" not in native.existing_rules():
+ native.http_archive(
+ name = "io_opencensus_cpp",
+ strip_prefix = "opencensus-cpp-fdf0f308b1631bb4a942e32ba5d22536a6170274",
+ url = "https://github.com/census-instrumentation/opencensus-cpp/archive/fdf0f308b1631bb4a942e32ba5d22536a6170274.tar.gz",
+ )
+
+
# TODO: move some dependencies from "grpc_deps" here?
def grpc_test_only_deps():
"""Internal, not intended for use by packages that are consuming grpc.
diff --git a/build.yaml b/build.yaml
index 11060b6ddd..d70a31c2d2 100644
--- a/build.yaml
+++ b/build.yaml
@@ -100,10 +100,9 @@ filegroups:
public_headers:
- include/grpc/census.h
src:
- - src/core/ext/census/grpc_context.cc
+ - src/cpp/ext/filters/census/grpc_context.cc
uses:
- grpc_base
- - nanopb
- name: cmdline
headers:
- test/core/util/cmdline.h
@@ -235,6 +234,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 +405,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
@@ -1905,15 +1906,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++
@@ -2793,6 +2785,21 @@ targets:
platforms:
- linux
secure: true
+- name: handshake_verify_peer_options
+ build: test
+ language: c
+ src:
+ - test/core/handshake/verify_peer_options.cc
+ deps:
+ - grpc_test_util
+ - grpc
+ - gpr_test_util
+ - gpr
+ exclude_iomgrs:
+ - uv
+ platforms:
+ - linux
+ secure: true
- name: histogram_test
build: test
language: c
@@ -4238,6 +4245,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++
@@ -4831,20 +4855,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
@@ -5494,7 +5504,7 @@ configs:
compile_the_world: true
test_environ:
ASAN_OPTIONS: detect_leaks=1:color=always
- LSAN_OPTIONS: suppressions=tools/lsan_suppressions.txt:report_objects=1
+ LSAN_OPTIONS: suppressions=test/core/util/lsan_suppressions.txt:report_objects=1
asan-noleaks:
CC: clang
CPPFLAGS: -O0 -fsanitize-coverage=edge,trace-pc-guard -fsanitize=address -fno-omit-frame-pointer
@@ -5518,7 +5528,7 @@ configs:
compile_the_world: true
test_environ:
ASAN_OPTIONS: detect_leaks=1:color=always
- LSAN_OPTIONS: suppressions=tools/lsan_suppressions.txt:report_objects=1
+ LSAN_OPTIONS: suppressions=test/core/util/lsan_suppressions.txt:report_objects=1
basicprof:
CPPFLAGS: -O2 -DGRPC_BASIC_PROFILER -DGRPC_TIMERS_RDTSC
DEFINES: NDEBUG
@@ -5592,7 +5602,7 @@ configs:
LDXX: clang++
compile_the_world: true
test_environ:
- TSAN_OPTIONS: suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
+ TSAN_OPTIONS: suppressions=test/core/util/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
ubsan:
CC: clang
CPPFLAGS: -O0 -fsanitize-coverage=edge,trace-pc-guard -fsanitize=undefined -fno-omit-frame-pointer
@@ -5604,7 +5614,7 @@ configs:
LDXX: clang++
compile_the_world: true
test_environ:
- UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1:suppressions=tools/ubsan_suppressions.txt
+ UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1:suppressions=test/core/util/ubsan_suppressions.txt
defaults:
ares:
CFLAGS: -Wno-sign-conversion $(if $(subst Darwin,,$(SYSTEM)),,-Wno-shorten-64-to-32)
diff --git a/config.m4 b/config.m4
index a5b041f035..99c4a85206 100644
--- a/config.m4
+++ b/config.m4
@@ -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 \
@@ -378,7 +380,7 @@ if test "$PHP_GRPC" != "no"; then
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/core/ext/census/grpc_context.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 \
src/core/ext/filters/http/client_authority_filter.cc \
@@ -649,7 +651,6 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
PHP_ADD_BUILD_DIR($ext_builddir/src/boringssl)
- PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/census)
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)
@@ -712,6 +713,7 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/alts/handshaker)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/alts/zero_copy_frame_protector)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/ssl/session_cache)
+ PHP_ADD_BUILD_DIR($ext_builddir/src/cpp/ext/filters/census)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/address_sorting)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/asn1)
diff --git a/config.w32 b/config.w32
index cd51b4d97c..b8be2387d9 100644
--- a/config.w32
+++ b/config.w32
@@ -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 " +
@@ -354,7 +355,7 @@ if (PHP_GRPC != "no") {
"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\\core\\ext\\census\\grpc_context.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 " +
"src\\core\\ext\\filters\\http\\client_authority_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");
@@ -653,7 +655,6 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\boringssl");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext");
- FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\census");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy");
@@ -729,6 +730,10 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\alts\\zero_copy_frame_protector");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\ssl");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\ssl\\session_cache");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\cpp");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\cpp\\ext");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\cpp\\ext\\filters");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\cpp\\ext\\filters\\census");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php\\ext");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php\\ext\\grpc");
diff --git a/doc/command_line_tool.md b/doc/command_line_tool.md
index 082e6402eb..6337acaf60 100644
--- a/doc/command_line_tool.md
+++ b/doc/command_line_tool.md
@@ -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:
diff --git a/examples/cpp/README.md b/examples/cpp/README.md
index 8e2bb5d13b..0e358bf9a2 100644
--- a/examples/cpp/README.md
+++ b/examples/cpp/README.md
@@ -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!
diff --git a/examples/cpp/cpptutorial.md b/examples/cpp/cpptutorial.md
index 7d98367da4..c40676de13 100644
--- a/examples/cpp/cpptutorial.md
+++ b/examples/cpp/cpptutorial.md
@@ -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
diff --git a/examples/cpp/helloworld/README.md b/examples/cpp/helloworld/README.md
index 18d3d79dcc..c598658b1d 100644
--- a/examples/cpp/helloworld/README.md
+++ b/examples/cpp/helloworld/README.md
@@ -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
diff --git a/examples/cpp/route_guide/README.md b/examples/cpp/route_guide/README.md
new file mode 100644
index 0000000000..1cb5a409f8
--- /dev/null
+++ b/examples/cpp/route_guide/README.md
@@ -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
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index 2380da9476..d7afd5a99c 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -347,6 +347,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',
@@ -532,6 +533,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',
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index ca6df16a06..89ddf20efb 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -357,6 +357,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',
@@ -507,6 +508,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',
@@ -793,7 +795,7 @@ Pod::Spec.new do |s|
'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/core/ext/census/grpc_context.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',
'src/core/ext/filters/http/client_authority_filter.cc',
@@ -936,6 +938,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',
@@ -1194,6 +1197,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',
diff --git a/grpc.def b/grpc.def
index 6a91214e8c..e7f93396b2 100644
--- a/grpc.def
+++ b/grpc.def
@@ -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
diff --git a/grpc.gemspec b/grpc.gemspec
index 1a3b5bd889..3b48967cba 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -294,6 +294,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 )
@@ -444,6 +445,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 )
@@ -733,7 +735,7 @@ Gem::Specification.new do |s|
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/core/ext/census/grpc_context.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 )
s.files += %w( src/core/ext/filters/http/client_authority_filter.cc )
diff --git a/grpc.gyp b/grpc.gyp
index 8edfcadf95..e9eb0125ef 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -256,6 +256,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',
@@ -545,7 +546,7 @@
'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/core/ext/census/grpc_context.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',
'src/core/ext/filters/http/client_authority_filter.cc',
@@ -606,6 +607,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 +839,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 +1049,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',
@@ -1268,7 +1272,7 @@
'third_party/nanopb/pb_encode.c',
'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
- 'src/core/ext/census/grpc_context.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',
'src/core/ext/filters/http/client_authority_filter.cc',
@@ -1646,16 +1650,6 @@
],
},
{
- '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',
'dependencies': [
@@ -2616,6 +2610,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',
@@ -2707,6 +2702,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',
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index dd8a5d7d5f..c129a66949 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -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.
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index e1975a8e09..b34fb70898 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -163,6 +163,26 @@ typedef struct {
const char* cert_chain;
} grpc_ssl_pem_key_cert_pair;
+/** Object that holds additional peer-verification options on a secure
+ channel. */
+typedef struct {
+ /** If non-NULL this callback will be invoked with the expected
+ target_name, the peer's certificate (in PEM format), and whatever
+ userdata pointer is set below. If a non-zero value is returned by this
+ callback then it is treated as a verification failure. Invocation of
+ the callback is blocking, so any implementation should be light-weight.
+ */
+ int (*verify_peer_callback)(const char* target_name, const char* peer_pem,
+ void* userdata);
+ /** Arbitrary userdata that will be passed as the last argument to
+ verify_peer_callback. */
+ void* verify_peer_callback_userdata;
+ /** A destruct callback that will be invoked when the channel is being
+ cleaned up. The userdata argument will be passed to it. The intent is
+ to perform any cleanup associated with that userdata. */
+ void (*verify_peer_destruct)(void* userdata);
+} verify_peer_options;
+
/** Creates an SSL credentials object.
- pem_root_certs is the NULL-terminated string containing the PEM encoding
of the server root certificates. If this parameter is NULL, the
@@ -173,10 +193,17 @@ typedef struct {
disk (in the grpc install directory).
- pem_key_cert_pair is a pointer on the object containing client's private
key and certificate chain. This parameter can be NULL if the client does
- not have such a key/cert pair. */
+ not have such a key/cert pair.
+ - verify_options is an optional verify_peer_options object which holds
+ additional options controlling how peer certificates are verified. For
+ example, you can supply a callback which receives the peer's certificate
+ with which you can do additional verification. Can be NULL, in which
+ case verification will retain default behavior. Any settings in
+ verify_options are copied during this call, so the verify_options
+ object can be released afterwards. */
GRPCAPI grpc_channel_credentials* grpc_ssl_credentials_create(
const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
- void* reserved);
+ const verify_peer_options* verify_options, void* reserved);
/** --- grpc_call_credentials object.
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index a5961857c1..c32e99ed4c 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -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 \
diff --git a/include/grpcpp/impl/codegen/call.h b/include/grpcpp/impl/codegen/call.h
index e324f6b14d..a5e930aaa5 100644
--- a/include/grpcpp/impl/codegen/call.h
+++ b/include/grpcpp/impl/codegen/call.h
@@ -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;
diff --git a/include/grpcpp/opencensus.h b/include/grpcpp/opencensus.h
new file mode 100644
index 0000000000..7e5d1dfeb4
--- /dev/null
+++ b/include/grpcpp/opencensus.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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 GRPCPP_OPENCENSUS_H
+#define GRPCPP_OPENCENSUS_H
+
+namespace grpc {
+// These symbols in this file will not be included in the binary unless
+// grpc_opencensus_plugin build target was added as a dependency. At the moment
+// it is only setup to be built with Bazel.
+
+// Registers the OpenCensus plugin with gRPC, so that it will be used for future
+// RPCs. This must be called before any views are created.
+void RegisterOpenCensusPlugin();
+
+// RPC stats definitions, defined by
+// https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/gRPC.md
+
+// Registers the cumulative gRPC views so that they will be exported by any
+// registered stats exporter. For on-task stats, construct a View using the
+// ViewDescriptors below.
+void RegisterOpenCensusViewsForExport();
+
+} // namespace grpc
+
+#endif // GRPCPP_OPENCENSUS_H
diff --git a/package.xml b/package.xml
index 5be18bd4d0..29f6f0147a 100644
--- a/package.xml
+++ b/package.xml
@@ -299,6 +299,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" />
@@ -449,6 +450,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" />
@@ -738,7 +740,7 @@
<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/core/ext/census/grpc_context.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" />
<file baseinstalldir="/" name="src/core/ext/filters/http/client_authority_filter.cc" role="src" />
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index ea6775a8d8..520431e63b 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -794,6 +794,15 @@ typedef struct {
// The batch to use in the subchannel call.
// Its payload field points to subchannel_call_retry_state.batch_payload.
grpc_transport_stream_op_batch batch;
+ // For intercepting on_complete.
+ grpc_closure on_complete;
+} subchannel_batch_data;
+
+// Retry state associated with a subchannel call.
+// Stored in the parent_data of the subchannel call object.
+typedef struct {
+ // subchannel_batch_data.batch.payload points to this.
+ grpc_transport_stream_op_batch_payload batch_payload;
// For send_initial_metadata.
// Note that we need to make a copy of the initial metadata for each
// subchannel call instead of just referring to the copy in call_data,
@@ -817,15 +826,7 @@ typedef struct {
// For intercepting recv_trailing_metadata.
grpc_metadata_batch recv_trailing_metadata;
grpc_transport_stream_stats collect_stats;
- // For intercepting on_complete.
- grpc_closure on_complete;
-} subchannel_batch_data;
-
-// Retry state associated with a subchannel call.
-// Stored in the parent_data of the subchannel call object.
-typedef struct {
- // subchannel_batch_data.batch.payload points to this.
- grpc_transport_stream_op_batch_payload batch_payload;
+ grpc_closure recv_trailing_metadata_ready;
// These fields indicate which ops have been started and completed on
// this subchannel call.
size_t started_send_message_count;
@@ -1192,35 +1193,24 @@ static void pending_batches_fail(grpc_call_element* elem, grpc_error* error,
"chand=%p calld=%p: failing %" PRIuPTR " pending batches: %s",
elem->channel_data, calld, num_batches, grpc_error_string(error));
}
- grpc_transport_stream_op_batch*
- batches[GPR_ARRAY_SIZE(calld->pending_batches)];
- size_t num_batches = 0;
+ grpc_core::CallCombinerClosureList closures;
for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
pending_batch* pending = &calld->pending_batches[i];
grpc_transport_stream_op_batch* batch = pending->batch;
if (batch != nullptr) {
- batches[num_batches++] = batch;
+ batch->handler_private.extra_arg = calld;
+ GRPC_CLOSURE_INIT(&batch->handler_private.closure,
+ fail_pending_batch_in_call_combiner, batch,
+ grpc_schedule_on_exec_ctx);
+ closures.Add(&batch->handler_private.closure, GRPC_ERROR_REF(error),
+ "pending_batches_fail");
pending_batch_clear(calld, pending);
}
}
- for (size_t i = yield_call_combiner ? 1 : 0; i < num_batches; ++i) {
- grpc_transport_stream_op_batch* batch = batches[i];
- batch->handler_private.extra_arg = calld;
- GRPC_CLOSURE_INIT(&batch->handler_private.closure,
- fail_pending_batch_in_call_combiner, batch,
- grpc_schedule_on_exec_ctx);
- GRPC_CALL_COMBINER_START(calld->call_combiner,
- &batch->handler_private.closure,
- GRPC_ERROR_REF(error), "pending_batches_fail");
- }
if (yield_call_combiner) {
- if (num_batches > 0) {
- // Note: This will release the call combiner.
- grpc_transport_stream_op_batch_finish_with_failure(
- batches[0], GRPC_ERROR_REF(error), calld->call_combiner);
- } else {
- GRPC_CALL_COMBINER_STOP(calld->call_combiner, "pending_batches_fail");
- }
+ closures.RunClosures(calld->call_combiner);
+ } else {
+ closures.RunClosuresWithoutYielding(calld->call_combiner);
}
GRPC_ERROR_UNREF(error);
}
@@ -1255,30 +1245,22 @@ static void pending_batches_resume(grpc_call_element* elem) {
" pending batches on subchannel_call=%p",
chand, calld, num_batches, calld->subchannel_call);
}
- grpc_transport_stream_op_batch*
- batches[GPR_ARRAY_SIZE(calld->pending_batches)];
- size_t num_batches = 0;
+ grpc_core::CallCombinerClosureList closures;
for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
pending_batch* pending = &calld->pending_batches[i];
grpc_transport_stream_op_batch* batch = pending->batch;
if (batch != nullptr) {
- batches[num_batches++] = batch;
+ batch->handler_private.extra_arg = calld->subchannel_call;
+ GRPC_CLOSURE_INIT(&batch->handler_private.closure,
+ resume_pending_batch_in_call_combiner, batch,
+ grpc_schedule_on_exec_ctx);
+ closures.Add(&batch->handler_private.closure, GRPC_ERROR_NONE,
+ "pending_batches_resume");
pending_batch_clear(calld, pending);
}
}
- for (size_t i = 1; i < num_batches; ++i) {
- grpc_transport_stream_op_batch* batch = batches[i];
- batch->handler_private.extra_arg = calld->subchannel_call;
- GRPC_CLOSURE_INIT(&batch->handler_private.closure,
- resume_pending_batch_in_call_combiner, batch,
- grpc_schedule_on_exec_ctx);
- GRPC_CALL_COMBINER_START(calld->call_combiner,
- &batch->handler_private.closure, GRPC_ERROR_NONE,
- "pending_batches_resume");
- }
- GPR_ASSERT(num_batches > 0);
// Note: This will release the call combiner.
- grpc_subchannel_call_process_op(calld->subchannel_call, batches[0]);
+ closures.RunClosures(calld->call_combiner);
}
static void maybe_clear_pending_batch(grpc_call_element* elem,
@@ -1293,7 +1275,10 @@ static void maybe_clear_pending_batch(grpc_call_element* elem,
batch->payload->recv_initial_metadata.recv_initial_metadata_ready ==
nullptr) &&
(!batch->recv_message ||
- batch->payload->recv_message.recv_message_ready == nullptr)) {
+ batch->payload->recv_message.recv_message_ready == nullptr) &&
+ (!batch->recv_trailing_metadata ||
+ batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready ==
+ nullptr)) {
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO, "chand=%p calld=%p: clearing pending batch", chand,
calld);
@@ -1302,75 +1287,27 @@ static void maybe_clear_pending_batch(grpc_call_element* elem,
}
}
-// Returns true if all ops in the pending batch have been completed.
-static bool pending_batch_is_completed(
- pending_batch* pending, call_data* calld,
- subchannel_call_retry_state* retry_state) {
- if (pending->batch == nullptr || pending->batch->on_complete == nullptr) {
- return false;
- }
- if (pending->batch->send_initial_metadata &&
- !retry_state->completed_send_initial_metadata) {
- return false;
- }
- if (pending->batch->send_message &&
- retry_state->completed_send_message_count <
- calld->send_messages->size()) {
- return false;
- }
- if (pending->batch->send_trailing_metadata &&
- !retry_state->completed_send_trailing_metadata) {
- return false;
- }
- if (pending->batch->recv_initial_metadata &&
- !retry_state->completed_recv_initial_metadata) {
- return false;
- }
- if (pending->batch->recv_message &&
- retry_state->completed_recv_message_count <
- retry_state->started_recv_message_count) {
- return false;
- }
- if (pending->batch->recv_trailing_metadata &&
- !retry_state->completed_recv_trailing_metadata) {
- return false;
- }
- return true;
-}
-
-// Returns true if any op in the batch was not yet started.
-static bool pending_batch_is_unstarted(
- pending_batch* pending, call_data* calld,
- subchannel_call_retry_state* retry_state) {
- if (pending->batch == nullptr || pending->batch->on_complete == nullptr) {
- return false;
- }
- if (pending->batch->send_initial_metadata &&
- !retry_state->started_send_initial_metadata) {
- return true;
- }
- if (pending->batch->send_message &&
- retry_state->started_send_message_count < calld->send_messages->size()) {
- return true;
- }
- if (pending->batch->send_trailing_metadata &&
- !retry_state->started_send_trailing_metadata) {
- return true;
- }
- if (pending->batch->recv_initial_metadata &&
- !retry_state->started_recv_initial_metadata) {
- return true;
- }
- if (pending->batch->recv_message &&
- retry_state->completed_recv_message_count ==
- retry_state->started_recv_message_count) {
- return true;
- }
- if (pending->batch->recv_trailing_metadata &&
- !retry_state->started_recv_trailing_metadata) {
- return true;
+// Returns a pointer to the first pending batch for which predicate(batch)
+// returns true, or null if not found.
+template <typename Predicate>
+static pending_batch* pending_batch_find(grpc_call_element* elem,
+ const char* log_message,
+ Predicate predicate) {
+ channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+ call_data* calld = static_cast<call_data*>(elem->call_data);
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
+ pending_batch* pending = &calld->pending_batches[i];
+ grpc_transport_stream_op_batch* batch = pending->batch;
+ if (batch != nullptr && predicate(batch)) {
+ if (grpc_client_channel_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "chand=%p calld=%p: %s pending batch at index %" PRIuPTR, chand,
+ calld, log_message, i);
+ }
+ return pending;
+ }
}
- return false;
+ return nullptr;
}
//
@@ -1557,8 +1494,13 @@ static bool maybe_retry(grpc_call_element* elem,
// subchannel_batch_data
//
+// Creates a subchannel_batch_data object on the call's arena with the
+// specified refcount. If set_on_complete is true, the batch's
+// on_complete callback will be set to point to on_complete();
+// otherwise, the batch's on_complete callback will be null.
static subchannel_batch_data* batch_data_create(grpc_call_element* elem,
- int refcount) {
+ int refcount,
+ bool set_on_complete) {
call_data* calld = static_cast<call_data*>(elem->call_data);
subchannel_call_retry_state* retry_state =
static_cast<subchannel_call_retry_state*>(
@@ -1571,26 +1513,32 @@ static subchannel_batch_data* batch_data_create(grpc_call_element* elem,
GRPC_SUBCHANNEL_CALL_REF(calld->subchannel_call, "batch_data_create");
batch_data->batch.payload = &retry_state->batch_payload;
gpr_ref_init(&batch_data->refs, refcount);
- GRPC_CLOSURE_INIT(&batch_data->on_complete, on_complete, batch_data,
- grpc_schedule_on_exec_ctx);
- batch_data->batch.on_complete = &batch_data->on_complete;
+ if (set_on_complete) {
+ GRPC_CLOSURE_INIT(&batch_data->on_complete, on_complete, batch_data,
+ grpc_schedule_on_exec_ctx);
+ batch_data->batch.on_complete = &batch_data->on_complete;
+ }
GRPC_CALL_STACK_REF(calld->owning_call, "batch_data");
return batch_data;
}
static void batch_data_unref(subchannel_batch_data* batch_data) {
if (gpr_unref(&batch_data->refs)) {
- if (batch_data->send_initial_metadata_storage != nullptr) {
- grpc_metadata_batch_destroy(&batch_data->send_initial_metadata);
+ subchannel_call_retry_state* retry_state =
+ static_cast<subchannel_call_retry_state*>(
+ grpc_connected_subchannel_call_get_parent_data(
+ batch_data->subchannel_call));
+ if (batch_data->batch.send_initial_metadata) {
+ grpc_metadata_batch_destroy(&retry_state->send_initial_metadata);
}
- if (batch_data->send_trailing_metadata_storage != nullptr) {
- grpc_metadata_batch_destroy(&batch_data->send_trailing_metadata);
+ if (batch_data->batch.send_trailing_metadata) {
+ grpc_metadata_batch_destroy(&retry_state->send_trailing_metadata);
}
if (batch_data->batch.recv_initial_metadata) {
- grpc_metadata_batch_destroy(&batch_data->recv_initial_metadata);
+ grpc_metadata_batch_destroy(&retry_state->recv_initial_metadata);
}
if (batch_data->batch.recv_trailing_metadata) {
- grpc_metadata_batch_destroy(&batch_data->recv_trailing_metadata);
+ grpc_metadata_batch_destroy(&retry_state->recv_trailing_metadata);
}
GRPC_SUBCHANNEL_CALL_UNREF(batch_data->subchannel_call, "batch_data_unref");
call_data* calld = static_cast<call_data*>(batch_data->elem->call_data);
@@ -1606,30 +1554,22 @@ static void batch_data_unref(subchannel_batch_data* batch_data) {
static void invoke_recv_initial_metadata_callback(void* arg,
grpc_error* error) {
subchannel_batch_data* batch_data = static_cast<subchannel_batch_data*>(arg);
- channel_data* chand =
- static_cast<channel_data*>(batch_data->elem->channel_data);
- call_data* calld = static_cast<call_data*>(batch_data->elem->call_data);
// Find pending batch.
- pending_batch* pending = nullptr;
- for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
- grpc_transport_stream_op_batch* batch = calld->pending_batches[i].batch;
- if (batch != nullptr && batch->recv_initial_metadata &&
- batch->payload->recv_initial_metadata.recv_initial_metadata_ready !=
- nullptr) {
- if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_INFO,
- "chand=%p calld=%p: invoking recv_initial_metadata_ready for "
- "pending batch at index %" PRIuPTR,
- chand, calld, i);
- }
- pending = &calld->pending_batches[i];
- break;
- }
- }
+ pending_batch* pending = pending_batch_find(
+ batch_data->elem, "invoking recv_initial_metadata_ready for",
+ [](grpc_transport_stream_op_batch* batch) {
+ return batch->recv_initial_metadata &&
+ batch->payload->recv_initial_metadata
+ .recv_initial_metadata_ready != nullptr;
+ });
GPR_ASSERT(pending != nullptr);
// Return metadata.
+ subchannel_call_retry_state* retry_state =
+ static_cast<subchannel_call_retry_state*>(
+ grpc_connected_subchannel_call_get_parent_data(
+ batch_data->subchannel_call));
grpc_metadata_batch_move(
- &batch_data->recv_initial_metadata,
+ &retry_state->recv_initial_metadata,
pending->batch->payload->recv_initial_metadata.recv_initial_metadata);
// Update bookkeeping.
// Note: Need to do this before invoking the callback, since invoking
@@ -1661,11 +1601,20 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) {
static_cast<subchannel_call_retry_state*>(
grpc_connected_subchannel_call_get_parent_data(
batch_data->subchannel_call));
+ retry_state->completed_recv_initial_metadata = true;
+ // If a retry was already dispatched, then we're not going to use the
+ // result of this recv_initial_metadata op, so do nothing.
+ if (retry_state->retry_dispatched) {
+ GRPC_CALL_COMBINER_STOP(
+ calld->call_combiner,
+ "recv_initial_metadata_ready after retry dispatched");
+ return;
+ }
// If we got an error or a Trailers-Only response and have not yet gotten
- // the recv_trailing_metadata on_complete callback, then defer
- // propagating this callback back to the surface. We can evaluate whether
- // to retry when recv_trailing_metadata comes back.
- if (GPR_UNLIKELY((batch_data->trailing_metadata_available ||
+ // the recv_trailing_metadata_ready callback, then defer propagating this
+ // callback back to the surface. We can evaluate whether to retry when
+ // recv_trailing_metadata comes back.
+ if (GPR_UNLIKELY((retry_state->trailing_metadata_available ||
error != GRPC_ERROR_NONE) &&
!retry_state->completed_recv_trailing_metadata)) {
if (grpc_client_channel_trace.enabled()) {
@@ -1689,9 +1638,9 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) {
}
// Received valid initial metadata, so commit the call.
retry_commit(elem, retry_state);
+ // Invoke the callback to return the result to the surface.
// Manually invoking a callback function; it does not take ownership of error.
invoke_recv_initial_metadata_callback(batch_data, error);
- GRPC_ERROR_UNREF(error);
}
//
@@ -1701,29 +1650,21 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) {
// Invokes recv_message_ready for a subchannel batch.
static void invoke_recv_message_callback(void* arg, grpc_error* error) {
subchannel_batch_data* batch_data = static_cast<subchannel_batch_data*>(arg);
- channel_data* chand =
- static_cast<channel_data*>(batch_data->elem->channel_data);
- call_data* calld = static_cast<call_data*>(batch_data->elem->call_data);
// Find pending op.
- pending_batch* pending = nullptr;
- for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
- grpc_transport_stream_op_batch* batch = calld->pending_batches[i].batch;
- if (batch != nullptr && batch->recv_message &&
- batch->payload->recv_message.recv_message_ready != nullptr) {
- if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_INFO,
- "chand=%p calld=%p: invoking recv_message_ready for "
- "pending batch at index %" PRIuPTR,
- chand, calld, i);
- }
- pending = &calld->pending_batches[i];
- break;
- }
- }
+ pending_batch* pending = pending_batch_find(
+ batch_data->elem, "invoking recv_message_ready for",
+ [](grpc_transport_stream_op_batch* batch) {
+ return batch->recv_message &&
+ batch->payload->recv_message.recv_message_ready != nullptr;
+ });
GPR_ASSERT(pending != nullptr);
// Return payload.
+ subchannel_call_retry_state* retry_state =
+ static_cast<subchannel_call_retry_state*>(
+ grpc_connected_subchannel_call_get_parent_data(
+ batch_data->subchannel_call));
*pending->batch->payload->recv_message.recv_message =
- std::move(batch_data->recv_message);
+ std::move(retry_state->recv_message);
// Update bookkeeping.
// Note: Need to do this before invoking the callback, since invoking
// the callback will result in yielding the call combiner.
@@ -1751,12 +1692,20 @@ static void recv_message_ready(void* arg, grpc_error* error) {
static_cast<subchannel_call_retry_state*>(
grpc_connected_subchannel_call_get_parent_data(
batch_data->subchannel_call));
+ ++retry_state->completed_recv_message_count;
+ // If a retry was already dispatched, then we're not going to use the
+ // result of this recv_message op, so do nothing.
+ if (retry_state->retry_dispatched) {
+ GRPC_CALL_COMBINER_STOP(calld->call_combiner,
+ "recv_message_ready after retry dispatched");
+ return;
+ }
// If we got an error or the payload was nullptr and we have not yet gotten
- // the recv_trailing_metadata on_complete callback, then defer
- // propagating this callback back to the surface. We can evaluate whether
- // to retry when recv_trailing_metadata comes back.
+ // the recv_trailing_metadata_ready callback, then defer propagating this
+ // callback back to the surface. We can evaluate whether to retry when
+ // recv_trailing_metadata comes back.
if (GPR_UNLIKELY(
- (batch_data->recv_message == nullptr || error != GRPC_ERROR_NONE) &&
+ (retry_state->recv_message == nullptr || error != GRPC_ERROR_NONE) &&
!retry_state->completed_recv_trailing_metadata)) {
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO,
@@ -1777,133 +1726,272 @@ static void recv_message_ready(void* arg, grpc_error* error) {
}
// Received a valid message, so commit the call.
retry_commit(elem, retry_state);
+ // Invoke the callback to return the result to the surface.
// Manually invoking a callback function; it does not take ownership of error.
invoke_recv_message_callback(batch_data, error);
- GRPC_ERROR_UNREF(error);
}
//
-// list of closures to execute in call combiner
+// recv_trailing_metadata handling
//
-// Represents a closure that needs to run in the call combiner as part of
-// starting or completing a batch.
-typedef struct {
- grpc_closure* closure;
- grpc_error* error;
- const char* reason;
- bool free_reason = false;
-} closure_to_execute;
-
-static void execute_closures_in_call_combiner(grpc_call_element* elem,
- const char* caller,
- closure_to_execute* closures,
- size_t num_closures) {
- channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+// Sets *status and *server_pushback_md based on batch_data and error.
+static void get_call_status(subchannel_batch_data* batch_data,
+ grpc_error* error, grpc_status_code* status,
+ grpc_mdelem** server_pushback_md) {
+ grpc_call_element* elem = batch_data->elem;
call_data* calld = static_cast<call_data*>(elem->call_data);
- // Note that the call combiner will be yielded for each closure that
- // we schedule. We're already running in the call combiner, so one of
- // the closures can be scheduled directly, but the others will
- // have to re-enter the call combiner.
- if (num_closures > 0) {
- if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_INFO, "chand=%p calld=%p: %s starting closure: %s", chand,
- calld, caller, closures[0].reason);
- }
- GRPC_CLOSURE_SCHED(closures[0].closure, closures[0].error);
- if (closures[0].free_reason) {
- gpr_free(const_cast<char*>(closures[0].reason));
- }
- for (size_t i = 1; i < num_closures; ++i) {
- if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_INFO,
- "chand=%p calld=%p: %s starting closure in call combiner: %s",
- chand, calld, caller, closures[i].reason);
- }
- GRPC_CALL_COMBINER_START(calld->call_combiner, closures[i].closure,
- closures[i].error, closures[i].reason);
- if (closures[i].free_reason) {
- gpr_free(const_cast<char*>(closures[i].reason));
- }
- }
+ if (error != GRPC_ERROR_NONE) {
+ grpc_error_get_status(error, calld->deadline, status, nullptr, nullptr,
+ nullptr);
} else {
- if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_INFO, "chand=%p calld=%p: no closures to run for %s", chand,
- calld, caller);
+ grpc_metadata_batch* md_batch =
+ batch_data->batch.payload->recv_trailing_metadata
+ .recv_trailing_metadata;
+ GPR_ASSERT(md_batch->idx.named.grpc_status != nullptr);
+ *status =
+ grpc_get_status_code_from_metadata(md_batch->idx.named.grpc_status->md);
+ if (md_batch->idx.named.grpc_retry_pushback_ms != nullptr) {
+ *server_pushback_md = &md_batch->idx.named.grpc_retry_pushback_ms->md;
}
- GRPC_CALL_COMBINER_STOP(calld->call_combiner, "no closures to run");
}
+ GRPC_ERROR_UNREF(error);
}
-//
-// on_complete callback handling
-//
-
-// Updates retry_state to reflect the ops completed in batch_data.
-static void update_retry_state_for_completed_batch(
- subchannel_batch_data* batch_data,
- subchannel_call_retry_state* retry_state) {
- if (batch_data->batch.send_initial_metadata) {
- retry_state->completed_send_initial_metadata = true;
- }
- if (batch_data->batch.send_message) {
- ++retry_state->completed_send_message_count;
- }
- if (batch_data->batch.send_trailing_metadata) {
- retry_state->completed_send_trailing_metadata = true;
- }
- if (batch_data->batch.recv_initial_metadata) {
- retry_state->completed_recv_initial_metadata = true;
- }
- if (batch_data->batch.recv_message) {
- ++retry_state->completed_recv_message_count;
- }
- if (batch_data->batch.recv_trailing_metadata) {
- retry_state->completed_recv_trailing_metadata = true;
+// Adds recv_trailing_metadata_ready closure to closures.
+static void add_closure_for_recv_trailing_metadata_ready(
+ grpc_call_element* elem, subchannel_batch_data* batch_data,
+ grpc_error* error, grpc_core::CallCombinerClosureList* closures) {
+ // Find pending batch.
+ pending_batch* pending = pending_batch_find(
+ elem, "invoking recv_trailing_metadata for",
+ [](grpc_transport_stream_op_batch* batch) {
+ return batch->recv_trailing_metadata &&
+ batch->payload->recv_trailing_metadata
+ .recv_trailing_metadata_ready != nullptr;
+ });
+ // If we generated the recv_trailing_metadata op internally via
+ // start_internal_recv_trailing_metadata(), then there will be no
+ // pending batch.
+ if (pending == nullptr) {
+ GRPC_ERROR_UNREF(error);
+ return;
}
+ // Return metadata.
+ subchannel_call_retry_state* retry_state =
+ static_cast<subchannel_call_retry_state*>(
+ grpc_connected_subchannel_call_get_parent_data(
+ batch_data->subchannel_call));
+ grpc_metadata_batch_move(
+ &retry_state->recv_trailing_metadata,
+ pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata);
+ // Add closure.
+ closures->Add(pending->batch->payload->recv_trailing_metadata
+ .recv_trailing_metadata_ready,
+ error, "recv_trailing_metadata_ready for pending batch");
+ // Update bookkeeping.
+ pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
+ nullptr;
+ maybe_clear_pending_batch(elem, pending);
}
// Adds any necessary closures for deferred recv_initial_metadata and
-// recv_message callbacks to closures, updating *num_closures as needed.
+// recv_message callbacks to closures.
static void add_closures_for_deferred_recv_callbacks(
subchannel_batch_data* batch_data, subchannel_call_retry_state* retry_state,
- closure_to_execute* closures, size_t* num_closures) {
+ grpc_core::CallCombinerClosureList* closures) {
if (batch_data->batch.recv_trailing_metadata) {
// Add closure for deferred recv_initial_metadata_ready.
if (GPR_UNLIKELY(retry_state->recv_initial_metadata_ready_deferred_batch !=
nullptr)) {
- closure_to_execute* closure = &closures[(*num_closures)++];
- closure->closure = GRPC_CLOSURE_INIT(
- &batch_data->recv_initial_metadata_ready,
- invoke_recv_initial_metadata_callback,
- retry_state->recv_initial_metadata_ready_deferred_batch,
- grpc_schedule_on_exec_ctx);
- closure->error = retry_state->recv_initial_metadata_error;
- closure->reason = "resuming recv_initial_metadata_ready";
+ GRPC_CLOSURE_INIT(&retry_state->recv_initial_metadata_ready,
+ invoke_recv_initial_metadata_callback,
+ retry_state->recv_initial_metadata_ready_deferred_batch,
+ grpc_schedule_on_exec_ctx);
+ closures->Add(&retry_state->recv_initial_metadata_ready,
+ retry_state->recv_initial_metadata_error,
+ "resuming recv_initial_metadata_ready");
retry_state->recv_initial_metadata_ready_deferred_batch = nullptr;
}
// Add closure for deferred recv_message_ready.
if (GPR_UNLIKELY(retry_state->recv_message_ready_deferred_batch !=
nullptr)) {
- closure_to_execute* closure = &closures[(*num_closures)++];
- closure->closure = GRPC_CLOSURE_INIT(
- &batch_data->recv_message_ready, invoke_recv_message_callback,
- retry_state->recv_message_ready_deferred_batch,
- grpc_schedule_on_exec_ctx);
- closure->error = retry_state->recv_message_error;
- closure->reason = "resuming recv_message_ready";
+ GRPC_CLOSURE_INIT(&retry_state->recv_message_ready,
+ invoke_recv_message_callback,
+ retry_state->recv_message_ready_deferred_batch,
+ grpc_schedule_on_exec_ctx);
+ closures->Add(&retry_state->recv_message_ready,
+ retry_state->recv_message_error,
+ "resuming recv_message_ready");
retry_state->recv_message_ready_deferred_batch = nullptr;
}
}
}
+// Returns true if any op in the batch was not yet started.
+// Only looks at send ops, since recv ops are always started immediately.
+static bool pending_batch_is_unstarted(
+ pending_batch* pending, call_data* calld,
+ subchannel_call_retry_state* retry_state) {
+ if (pending->batch == nullptr || pending->batch->on_complete == nullptr) {
+ return false;
+ }
+ if (pending->batch->send_initial_metadata &&
+ !retry_state->started_send_initial_metadata) {
+ return true;
+ }
+ if (pending->batch->send_message &&
+ retry_state->started_send_message_count < calld->send_messages->size()) {
+ return true;
+ }
+ if (pending->batch->send_trailing_metadata &&
+ !retry_state->started_send_trailing_metadata) {
+ return true;
+ }
+ return false;
+}
+
+// For any pending batch containing an op that has not yet been started,
+// adds the pending batch's completion closures to closures.
+static void add_closures_to_fail_unstarted_pending_batches(
+ grpc_call_element* elem, subchannel_call_retry_state* retry_state,
+ grpc_error* error, grpc_core::CallCombinerClosureList* closures) {
+ channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+ call_data* calld = static_cast<call_data*>(elem->call_data);
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
+ pending_batch* pending = &calld->pending_batches[i];
+ if (pending_batch_is_unstarted(pending, calld, retry_state)) {
+ if (grpc_client_channel_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "chand=%p calld=%p: failing unstarted pending batch at index "
+ "%" PRIuPTR,
+ chand, calld, i);
+ }
+ closures->Add(pending->batch->on_complete, GRPC_ERROR_REF(error),
+ "failing on_complete for pending batch");
+ pending->batch->on_complete = nullptr;
+ maybe_clear_pending_batch(elem, pending);
+ }
+ }
+ GRPC_ERROR_UNREF(error);
+}
+
+// Runs necessary closures upon completion of a call attempt.
+static void run_closures_for_completed_call(subchannel_batch_data* batch_data,
+ grpc_error* error) {
+ grpc_call_element* elem = batch_data->elem;
+ call_data* calld = static_cast<call_data*>(elem->call_data);
+ subchannel_call_retry_state* retry_state =
+ static_cast<subchannel_call_retry_state*>(
+ grpc_connected_subchannel_call_get_parent_data(
+ batch_data->subchannel_call));
+ // Construct list of closures to execute.
+ grpc_core::CallCombinerClosureList closures;
+ // First, add closure for recv_trailing_metadata_ready.
+ add_closure_for_recv_trailing_metadata_ready(
+ elem, batch_data, GRPC_ERROR_REF(error), &closures);
+ // If there are deferred recv_initial_metadata_ready or recv_message_ready
+ // callbacks, add them to closures.
+ add_closures_for_deferred_recv_callbacks(batch_data, retry_state, &closures);
+ // Add closures to fail any pending batches that have not yet been started.
+ add_closures_to_fail_unstarted_pending_batches(
+ elem, retry_state, GRPC_ERROR_REF(error), &closures);
+ // Don't need batch_data anymore.
+ batch_data_unref(batch_data);
+ // Schedule all of the closures identified above.
+ // Note: This will release the call combiner.
+ closures.RunClosures(calld->call_combiner);
+ GRPC_ERROR_UNREF(error);
+}
+
+// Intercepts recv_trailing_metadata_ready callback for retries.
+// Commits the call and returns the trailing metadata up the stack.
+static void recv_trailing_metadata_ready(void* arg, grpc_error* error) {
+ subchannel_batch_data* batch_data = static_cast<subchannel_batch_data*>(arg);
+ grpc_call_element* elem = batch_data->elem;
+ channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+ call_data* calld = static_cast<call_data*>(elem->call_data);
+ if (grpc_client_channel_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "chand=%p calld=%p: got recv_trailing_metadata_ready, error=%s",
+ chand, calld, grpc_error_string(error));
+ }
+ subchannel_call_retry_state* retry_state =
+ static_cast<subchannel_call_retry_state*>(
+ grpc_connected_subchannel_call_get_parent_data(
+ batch_data->subchannel_call));
+ retry_state->completed_recv_trailing_metadata = true;
+ // Get the call's status and check for server pushback metadata.
+ grpc_status_code status = GRPC_STATUS_OK;
+ grpc_mdelem* server_pushback_md = nullptr;
+ get_call_status(batch_data, GRPC_ERROR_REF(error), &status,
+ &server_pushback_md);
+ if (grpc_client_channel_trace.enabled()) {
+ gpr_log(GPR_INFO, "chand=%p calld=%p: call finished, status=%s", chand,
+ calld, grpc_status_code_to_string(status));
+ }
+ // Check if we should retry.
+ if (maybe_retry(elem, batch_data, status, server_pushback_md)) {
+ // Unref batch_data for deferred recv_initial_metadata_ready or
+ // recv_message_ready callbacks, if any.
+ if (retry_state->recv_initial_metadata_ready_deferred_batch != nullptr) {
+ batch_data_unref(batch_data);
+ GRPC_ERROR_UNREF(retry_state->recv_initial_metadata_error);
+ }
+ if (retry_state->recv_message_ready_deferred_batch != nullptr) {
+ batch_data_unref(batch_data);
+ GRPC_ERROR_UNREF(retry_state->recv_message_error);
+ }
+ batch_data_unref(batch_data);
+ return;
+ }
+ // Not retrying, so commit the call.
+ retry_commit(elem, retry_state);
+ // Run any necessary closures.
+ run_closures_for_completed_call(batch_data, GRPC_ERROR_REF(error));
+}
+
+//
+// on_complete callback handling
+//
+
+// Adds the on_complete closure for the pending batch completed in
+// batch_data to closures.
+static void add_closure_for_completed_pending_batch(
+ grpc_call_element* elem, subchannel_batch_data* batch_data,
+ subchannel_call_retry_state* retry_state, grpc_error* error,
+ grpc_core::CallCombinerClosureList* closures) {
+ pending_batch* pending = pending_batch_find(
+ elem, "completed", [batch_data](grpc_transport_stream_op_batch* batch) {
+ // Match the pending batch with the same set of send ops as the
+ // subchannel batch we've just completed.
+ return batch->on_complete != nullptr &&
+ batch_data->batch.send_initial_metadata ==
+ batch->send_initial_metadata &&
+ batch_data->batch.send_message == batch->send_message &&
+ batch_data->batch.send_trailing_metadata ==
+ batch->send_trailing_metadata;
+ });
+ // If batch_data is a replay batch, then there will be no pending
+ // batch to complete.
+ if (pending == nullptr) {
+ GRPC_ERROR_UNREF(error);
+ return;
+ }
+ // Add closure.
+ closures->Add(pending->batch->on_complete, error,
+ "on_complete for pending batch");
+ pending->batch->on_complete = nullptr;
+ maybe_clear_pending_batch(elem, pending);
+}
+
// If there are any cached ops to replay or pending ops to start on the
// subchannel call, adds a closure to closures to invoke
-// start_retriable_subchannel_batches(), updating *num_closures as needed.
+// start_retriable_subchannel_batches().
static void add_closures_for_replay_or_pending_send_ops(
grpc_call_element* elem, subchannel_batch_data* batch_data,
- subchannel_call_retry_state* retry_state, closure_to_execute* closures,
- size_t* num_closures) {
+ subchannel_call_retry_state* retry_state,
+ grpc_core::CallCombinerClosureList* closures) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
bool have_pending_send_message_ops =
@@ -1929,93 +2017,12 @@ static void add_closures_for_replay_or_pending_send_ops(
"chand=%p calld=%p: starting next batch for pending send op(s)",
chand, calld);
}
- closure_to_execute* closure = &closures[(*num_closures)++];
- closure->closure = GRPC_CLOSURE_INIT(
- &batch_data->batch.handler_private.closure,
- start_retriable_subchannel_batches, elem, grpc_schedule_on_exec_ctx);
- closure->error = GRPC_ERROR_NONE;
- closure->reason = "starting next batch for send_* op(s)";
- }
-}
-
-// For any pending batch completed in batch_data, adds the necessary
-// completion closures to closures, updating *num_closures as needed.
-static void add_closures_for_completed_pending_batches(
- grpc_call_element* elem, subchannel_batch_data* batch_data,
- subchannel_call_retry_state* retry_state, grpc_error* error,
- closure_to_execute* closures, size_t* num_closures) {
- channel_data* chand = static_cast<channel_data*>(elem->channel_data);
- call_data* calld = static_cast<call_data*>(elem->call_data);
- for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
- pending_batch* pending = &calld->pending_batches[i];
- if (pending_batch_is_completed(pending, calld, retry_state)) {
- if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_INFO,
- "chand=%p calld=%p: pending batch completed at index %" PRIuPTR,
- chand, calld, i);
- }
- // Copy the trailing metadata to return it to the surface.
- if (batch_data->batch.recv_trailing_metadata) {
- grpc_metadata_batch_move(&batch_data->recv_trailing_metadata,
- pending->batch->payload->recv_trailing_metadata
- .recv_trailing_metadata);
- }
- closure_to_execute* closure = &closures[(*num_closures)++];
- closure->closure = pending->batch->on_complete;
- closure->error = GRPC_ERROR_REF(error);
- closure->reason = "on_complete for pending batch";
- pending->batch->on_complete = nullptr;
- maybe_clear_pending_batch(elem, pending);
- }
- }
- GRPC_ERROR_UNREF(error);
-}
-
-// For any pending batch containing an op that has not yet been started,
-// adds the pending batch's completion closures to closures, updating
-// *num_closures as needed.
-static void add_closures_to_fail_unstarted_pending_batches(
- grpc_call_element* elem, subchannel_call_retry_state* retry_state,
- grpc_error* error, closure_to_execute* closures, size_t* num_closures) {
- channel_data* chand = static_cast<channel_data*>(elem->channel_data);
- call_data* calld = static_cast<call_data*>(elem->call_data);
- for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
- pending_batch* pending = &calld->pending_batches[i];
- if (pending_batch_is_unstarted(pending, calld, retry_state)) {
- if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_INFO,
- "chand=%p calld=%p: failing unstarted pending batch at index "
- "%" PRIuPTR,
- chand, calld, i);
- }
- if (pending->batch->recv_initial_metadata) {
- closure_to_execute* closure = &closures[(*num_closures)++];
- closure->closure = pending->batch->payload->recv_initial_metadata
- .recv_initial_metadata_ready;
- closure->error = GRPC_ERROR_REF(error);
- closure->reason =
- "failing recv_initial_metadata_ready for pending batch";
- pending->batch->payload->recv_initial_metadata
- .recv_initial_metadata_ready = nullptr;
- }
- if (pending->batch->recv_message) {
- *pending->batch->payload->recv_message.recv_message = nullptr;
- closure_to_execute* closure = &closures[(*num_closures)++];
- closure->closure =
- pending->batch->payload->recv_message.recv_message_ready;
- closure->error = GRPC_ERROR_REF(error);
- closure->reason = "failing recv_message_ready for pending batch";
- pending->batch->payload->recv_message.recv_message_ready = nullptr;
- }
- closure_to_execute* closure = &closures[(*num_closures)++];
- closure->closure = pending->batch->on_complete;
- closure->error = GRPC_ERROR_REF(error);
- closure->reason = "failing on_complete for pending batch";
- pending->batch->on_complete = nullptr;
- maybe_clear_pending_batch(elem, pending);
- }
+ GRPC_CLOSURE_INIT(&batch_data->batch.handler_private.closure,
+ start_retriable_subchannel_batches, elem,
+ grpc_schedule_on_exec_ctx);
+ closures->Add(&batch_data->batch.handler_private.closure, GRPC_ERROR_NONE,
+ "starting next batch for send_* op(s)");
}
- GRPC_ERROR_UNREF(error);
}
// Callback used to intercept on_complete from subchannel calls.
@@ -2035,136 +2042,49 @@ static void on_complete(void* arg, grpc_error* error) {
static_cast<subchannel_call_retry_state*>(
grpc_connected_subchannel_call_get_parent_data(
batch_data->subchannel_call));
- // If we have previously completed recv_trailing_metadata, then the
- // call is finished.
- bool call_finished = retry_state->completed_recv_trailing_metadata;
- // Record whether we were already committed before receiving this callback.
- const bool previously_committed = calld->retry_committed;
// Update bookkeeping in retry_state.
- update_retry_state_for_completed_batch(batch_data, retry_state);
- if (call_finished) {
- if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_INFO, "chand=%p calld=%p: call already finished", chand,
- calld);
- }
- } else {
- // Check if this batch finished the call, and if so, get its status.
- // The call is finished if either (a) this callback was invoked with
- // an error or (b) we receive status.
- grpc_status_code status = GRPC_STATUS_OK;
- grpc_mdelem* server_pushback_md = nullptr;
- if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { // Case (a).
- call_finished = true;
- grpc_error_get_status(error, calld->deadline, &status, nullptr, nullptr,
- nullptr);
- } else if (batch_data->batch.recv_trailing_metadata) { // Case (b).
- call_finished = true;
- grpc_metadata_batch* md_batch =
- batch_data->batch.payload->recv_trailing_metadata
- .recv_trailing_metadata;
- GPR_ASSERT(md_batch->idx.named.grpc_status != nullptr);
- status = grpc_get_status_code_from_metadata(
- md_batch->idx.named.grpc_status->md);
- if (md_batch->idx.named.grpc_retry_pushback_ms != nullptr) {
- server_pushback_md = &md_batch->idx.named.grpc_retry_pushback_ms->md;
- }
- }
- // If the call just finished, check if we should retry.
- if (call_finished) {
- if (grpc_client_channel_trace.enabled()) {
- gpr_log(GPR_INFO, "chand=%p calld=%p: call finished, status=%s", chand,
- calld, grpc_status_code_to_string(status));
- }
- if (maybe_retry(elem, batch_data, status, server_pushback_md)) {
- // Unref batch_data for deferred recv_initial_metadata_ready or
- // recv_message_ready callbacks, if any.
- if (batch_data->batch.recv_trailing_metadata &&
- retry_state->recv_initial_metadata_ready_deferred_batch !=
- nullptr) {
- batch_data_unref(batch_data);
- GRPC_ERROR_UNREF(retry_state->recv_initial_metadata_error);
- }
- if (batch_data->batch.recv_trailing_metadata &&
- retry_state->recv_message_ready_deferred_batch != nullptr) {
- batch_data_unref(batch_data);
- GRPC_ERROR_UNREF(retry_state->recv_message_error);
- }
- // Track number of pending subchannel send batches and determine if
- // this was the last one.
- bool last_callback_complete = false;
- if (batch_data->batch.send_initial_metadata ||
- batch_data->batch.send_message ||
- batch_data->batch.send_trailing_metadata) {
- --calld->num_pending_retriable_subchannel_send_batches;
- last_callback_complete =
- calld->num_pending_retriable_subchannel_send_batches == 0;
- }
- batch_data_unref(batch_data);
- // If we just completed the last subchannel send batch, unref the
- // call stack.
- if (last_callback_complete) {
- GRPC_CALL_STACK_UNREF(calld->owning_call, "subchannel_send_batches");
- }
- return;
- }
- // Not retrying, so commit the call.
- retry_commit(elem, retry_state);
- }
+ if (batch_data->batch.send_initial_metadata) {
+ retry_state->completed_send_initial_metadata = true;
+ }
+ if (batch_data->batch.send_message) {
+ ++retry_state->completed_send_message_count;
+ }
+ if (batch_data->batch.send_trailing_metadata) {
+ retry_state->completed_send_trailing_metadata = true;
}
- // If we were already committed before receiving this callback, free
- // cached data for send ops that we've just completed. (If the call has
- // just now finished, the call to retry_commit() above will have freed all
- // cached send ops, so we don't need to do it here.)
- if (previously_committed) {
+ // If the call is committed, free cached data for send ops that we've just
+ // completed.
+ if (calld->retry_committed) {
free_cached_send_op_data_for_completed_batch(elem, batch_data, retry_state);
}
- // Call not being retried.
// Construct list of closures to execute.
- // Max number of closures is number of pending batches plus one for
- // each of:
- // - recv_initial_metadata_ready (either deferred or unstarted)
- // - recv_message_ready (either deferred or unstarted)
- // - starting a new batch for pending send ops
- closure_to_execute closures[GPR_ARRAY_SIZE(calld->pending_batches) + 3];
- size_t num_closures = 0;
- // If there are deferred recv_initial_metadata_ready or recv_message_ready
- // callbacks, add them to closures.
- add_closures_for_deferred_recv_callbacks(batch_data, retry_state, closures,
- &num_closures);
- // Find pending batches whose ops are now complete and add their
- // on_complete callbacks to closures.
- add_closures_for_completed_pending_batches(elem, batch_data, retry_state,
- GRPC_ERROR_REF(error), closures,
- &num_closures);
- // Add closures to handle any pending batches that have not yet been started.
- // If the call is finished, we fail these batches; otherwise, we add a
- // callback to start_retriable_subchannel_batches() to start them on
- // the subchannel call.
- if (call_finished) {
- add_closures_to_fail_unstarted_pending_batches(
- elem, retry_state, GRPC_ERROR_REF(error), closures, &num_closures);
- } else {
- add_closures_for_replay_or_pending_send_ops(elem, batch_data, retry_state,
- closures, &num_closures);
+ grpc_core::CallCombinerClosureList closures;
+ // If a retry was already dispatched, that means we saw
+ // recv_trailing_metadata before this, so we do nothing here.
+ // Otherwise, invoke the callback to return the result to the surface.
+ if (!retry_state->retry_dispatched) {
+ // Add closure for the completed pending batch, if any.
+ add_closure_for_completed_pending_batch(elem, batch_data, retry_state,
+ GRPC_ERROR_REF(error), &closures);
+ // If needed, add a callback to start any replay or pending send ops on
+ // the subchannel call.
+ if (!retry_state->completed_recv_trailing_metadata) {
+ add_closures_for_replay_or_pending_send_ops(elem, batch_data, retry_state,
+ &closures);
+ }
}
// Track number of pending subchannel send batches and determine if this
// was the last one.
- bool last_callback_complete = false;
- if (batch_data->batch.send_initial_metadata ||
- batch_data->batch.send_message ||
- batch_data->batch.send_trailing_metadata) {
- --calld->num_pending_retriable_subchannel_send_batches;
- last_callback_complete =
- calld->num_pending_retriable_subchannel_send_batches == 0;
- }
+ --calld->num_pending_retriable_subchannel_send_batches;
+ const bool last_send_batch_complete =
+ calld->num_pending_retriable_subchannel_send_batches == 0;
// Don't need batch_data anymore.
batch_data_unref(batch_data);
// Schedule all of the closures identified above.
// Note: This yeilds the call combiner.
- execute_closures_in_call_combiner(elem, "on_complete", closures,
- num_closures);
- // If we just completed the last subchannel send batch, unref the call stack.
- if (last_callback_complete) {
+ closures.RunClosures(calld->call_combiner);
+ // If this was the last subchannel send batch, unref the call stack.
+ if (last_send_batch_complete) {
GRPC_CALL_STACK_UNREF(calld->owning_call, "subchannel_send_batches");
}
}
@@ -2185,27 +2105,22 @@ static void start_batch_in_call_combiner(void* arg, grpc_error* ignored) {
// Adds a closure to closures that will execute batch in the call combiner.
static void add_closure_for_subchannel_batch(
- call_data* calld, grpc_transport_stream_op_batch* batch,
- closure_to_execute* closures, size_t* num_closures) {
+ grpc_call_element* elem, grpc_transport_stream_op_batch* batch,
+ grpc_core::CallCombinerClosureList* closures) {
+ channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+ call_data* calld = static_cast<call_data*>(elem->call_data);
batch->handler_private.extra_arg = calld->subchannel_call;
GRPC_CLOSURE_INIT(&batch->handler_private.closure,
start_batch_in_call_combiner, batch,
grpc_schedule_on_exec_ctx);
- closure_to_execute* closure = &closures[(*num_closures)++];
- closure->closure = &batch->handler_private.closure;
- closure->error = GRPC_ERROR_NONE;
- // If the tracer is enabled, we log a more detailed message, which
- // requires dynamic allocation. This will be freed in
- // start_retriable_subchannel_batches().
if (grpc_client_channel_trace.enabled()) {
char* batch_str = grpc_transport_stream_op_batch_string(batch);
- gpr_asprintf(const_cast<char**>(&closure->reason),
- "starting batch in call combiner: %s", batch_str);
+ gpr_log(GPR_INFO, "chand=%p calld=%p: starting subchannel batch: %s", chand,
+ calld, batch_str);
gpr_free(batch_str);
- closure->free_reason = true;
- } else {
- closure->reason = "start_subchannel_batch";
}
+ closures->Add(&batch->handler_private.closure, GRPC_ERROR_NONE,
+ "start_subchannel_batch");
}
// Adds retriable send_initial_metadata op to batch_data.
@@ -2221,28 +2136,28 @@ static void add_retriable_send_initial_metadata_op(
//
// If we've already completed one or more attempts, add the
// grpc-retry-attempts header.
- batch_data->send_initial_metadata_storage =
+ retry_state->send_initial_metadata_storage =
static_cast<grpc_linked_mdelem*>(gpr_arena_alloc(
calld->arena, sizeof(grpc_linked_mdelem) *
(calld->send_initial_metadata.list.count +
(calld->num_attempts_completed > 0))));
grpc_metadata_batch_copy(&calld->send_initial_metadata,
- &batch_data->send_initial_metadata,
- batch_data->send_initial_metadata_storage);
- if (GPR_UNLIKELY(batch_data->send_initial_metadata.idx.named
+ &retry_state->send_initial_metadata,
+ retry_state->send_initial_metadata_storage);
+ if (GPR_UNLIKELY(retry_state->send_initial_metadata.idx.named
.grpc_previous_rpc_attempts != nullptr)) {
- grpc_metadata_batch_remove(
- &batch_data->send_initial_metadata,
- batch_data->send_initial_metadata.idx.named.grpc_previous_rpc_attempts);
+ grpc_metadata_batch_remove(&retry_state->send_initial_metadata,
+ retry_state->send_initial_metadata.idx.named
+ .grpc_previous_rpc_attempts);
}
if (GPR_UNLIKELY(calld->num_attempts_completed > 0)) {
grpc_mdelem retry_md = grpc_mdelem_from_slices(
GRPC_MDSTR_GRPC_PREVIOUS_RPC_ATTEMPTS,
*retry_count_strings[calld->num_attempts_completed - 1]);
grpc_error* error = grpc_metadata_batch_add_tail(
- &batch_data->send_initial_metadata,
- &batch_data->send_initial_metadata_storage[calld->send_initial_metadata
- .list.count],
+ &retry_state->send_initial_metadata,
+ &retry_state->send_initial_metadata_storage[calld->send_initial_metadata
+ .list.count],
retry_md);
if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) {
gpr_log(GPR_ERROR, "error adding retry metadata: %s",
@@ -2253,7 +2168,7 @@ static void add_retriable_send_initial_metadata_op(
retry_state->started_send_initial_metadata = true;
batch_data->batch.send_initial_metadata = true;
batch_data->batch.payload->send_initial_metadata.send_initial_metadata =
- &batch_data->send_initial_metadata;
+ &retry_state->send_initial_metadata;
batch_data->batch.payload->send_initial_metadata.send_initial_metadata_flags =
calld->send_initial_metadata_flags;
batch_data->batch.payload->send_initial_metadata.peer_string =
@@ -2274,10 +2189,10 @@ static void add_retriable_send_message_op(
grpc_core::ByteStreamCache* cache =
(*calld->send_messages)[retry_state->started_send_message_count];
++retry_state->started_send_message_count;
- batch_data->send_message.Init(cache);
+ retry_state->send_message.Init(cache);
batch_data->batch.send_message = true;
batch_data->batch.payload->send_message.send_message.reset(
- batch_data->send_message.get());
+ retry_state->send_message.get());
}
// Adds retriable send_trailing_metadata op to batch_data.
@@ -2287,17 +2202,17 @@ static void add_retriable_send_trailing_metadata_op(
// We need to make a copy of the metadata batch for each attempt, since
// the filters in the subchannel stack may modify this batch, and we don't
// want those modifications to be passed forward to subsequent attempts.
- batch_data->send_trailing_metadata_storage =
+ retry_state->send_trailing_metadata_storage =
static_cast<grpc_linked_mdelem*>(gpr_arena_alloc(
calld->arena, sizeof(grpc_linked_mdelem) *
calld->send_trailing_metadata.list.count));
grpc_metadata_batch_copy(&calld->send_trailing_metadata,
- &batch_data->send_trailing_metadata,
- batch_data->send_trailing_metadata_storage);
+ &retry_state->send_trailing_metadata,
+ retry_state->send_trailing_metadata_storage);
retry_state->started_send_trailing_metadata = true;
batch_data->batch.send_trailing_metadata = true;
batch_data->batch.payload->send_trailing_metadata.send_trailing_metadata =
- &batch_data->send_trailing_metadata;
+ &retry_state->send_trailing_metadata;
}
// Adds retriable recv_initial_metadata op to batch_data.
@@ -2306,16 +2221,16 @@ static void add_retriable_recv_initial_metadata_op(
subchannel_batch_data* batch_data) {
retry_state->started_recv_initial_metadata = true;
batch_data->batch.recv_initial_metadata = true;
- grpc_metadata_batch_init(&batch_data->recv_initial_metadata);
+ grpc_metadata_batch_init(&retry_state->recv_initial_metadata);
batch_data->batch.payload->recv_initial_metadata.recv_initial_metadata =
- &batch_data->recv_initial_metadata;
+ &retry_state->recv_initial_metadata;
batch_data->batch.payload->recv_initial_metadata.trailing_metadata_available =
- &batch_data->trailing_metadata_available;
- GRPC_CLOSURE_INIT(&batch_data->recv_initial_metadata_ready,
+ &retry_state->trailing_metadata_available;
+ GRPC_CLOSURE_INIT(&retry_state->recv_initial_metadata_ready,
recv_initial_metadata_ready, batch_data,
grpc_schedule_on_exec_ctx);
batch_data->batch.payload->recv_initial_metadata.recv_initial_metadata_ready =
- &batch_data->recv_initial_metadata_ready;
+ &retry_state->recv_initial_metadata_ready;
}
// Adds retriable recv_message op to batch_data.
@@ -2325,11 +2240,11 @@ static void add_retriable_recv_message_op(
++retry_state->started_recv_message_count;
batch_data->batch.recv_message = true;
batch_data->batch.payload->recv_message.recv_message =
- &batch_data->recv_message;
- GRPC_CLOSURE_INIT(&batch_data->recv_message_ready, recv_message_ready,
+ &retry_state->recv_message;
+ GRPC_CLOSURE_INIT(&retry_state->recv_message_ready, recv_message_ready,
batch_data, grpc_schedule_on_exec_ctx);
batch_data->batch.payload->recv_message.recv_message_ready =
- &batch_data->recv_message_ready;
+ &retry_state->recv_message_ready;
}
// Adds retriable recv_trailing_metadata op to batch_data.
@@ -2338,12 +2253,17 @@ static void add_retriable_recv_trailing_metadata_op(
subchannel_batch_data* batch_data) {
retry_state->started_recv_trailing_metadata = true;
batch_data->batch.recv_trailing_metadata = true;
- grpc_metadata_batch_init(&batch_data->recv_trailing_metadata);
+ grpc_metadata_batch_init(&retry_state->recv_trailing_metadata);
batch_data->batch.payload->recv_trailing_metadata.recv_trailing_metadata =
- &batch_data->recv_trailing_metadata;
- batch_data->batch.collect_stats = true;
- batch_data->batch.payload->collect_stats.collect_stats =
- &batch_data->collect_stats;
+ &retry_state->recv_trailing_metadata;
+ batch_data->batch.payload->recv_trailing_metadata.collect_stats =
+ &retry_state->collect_stats;
+ GRPC_CLOSURE_INIT(&retry_state->recv_trailing_metadata_ready,
+ recv_trailing_metadata_ready, batch_data,
+ grpc_schedule_on_exec_ctx);
+ batch_data->batch.payload->recv_trailing_metadata
+ .recv_trailing_metadata_ready =
+ &retry_state->recv_trailing_metadata_ready;
}
// Helper function used to start a recv_trailing_metadata batch. This
@@ -2364,9 +2284,11 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem) {
grpc_connected_subchannel_call_get_parent_data(
calld->subchannel_call));
// Create batch_data with 2 refs, since this batch will be unreffed twice:
- // once when the subchannel batch returns, and again when we actually get
- // a recv_trailing_metadata op from the surface.
- subchannel_batch_data* batch_data = batch_data_create(elem, 2);
+ // once for the recv_trailing_metadata_ready callback when the subchannel
+ // batch returns, and again when we actually get a recv_trailing_metadata
+ // op from the surface.
+ subchannel_batch_data* batch_data =
+ batch_data_create(elem, 2, false /* set_on_complete */);
add_retriable_recv_trailing_metadata_op(calld, retry_state, batch_data);
retry_state->recv_trailing_metadata_internal_batch = batch_data;
// Note: This will release the call combiner.
@@ -2391,7 +2313,7 @@ static subchannel_batch_data* maybe_create_subchannel_batch_for_replay(
"send_initial_metadata op",
chand, calld);
}
- replay_batch_data = batch_data_create(elem, 1);
+ replay_batch_data = batch_data_create(elem, 1, true /* set_on_complete */);
add_retriable_send_initial_metadata_op(calld, retry_state,
replay_batch_data);
}
@@ -2408,7 +2330,8 @@ static subchannel_batch_data* maybe_create_subchannel_batch_for_replay(
chand, calld);
}
if (replay_batch_data == nullptr) {
- replay_batch_data = batch_data_create(elem, 1);
+ replay_batch_data =
+ batch_data_create(elem, 1, true /* set_on_complete */);
}
add_retriable_send_message_op(elem, retry_state, replay_batch_data);
}
@@ -2427,7 +2350,8 @@ static subchannel_batch_data* maybe_create_subchannel_batch_for_replay(
chand, calld);
}
if (replay_batch_data == nullptr) {
- replay_batch_data = batch_data_create(elem, 1);
+ replay_batch_data =
+ batch_data_create(elem, 1, true /* set_on_complete */);
}
add_retriable_send_trailing_metadata_op(calld, retry_state,
replay_batch_data);
@@ -2439,7 +2363,7 @@ static subchannel_batch_data* maybe_create_subchannel_batch_for_replay(
// *num_batches as needed.
static void add_subchannel_batches_for_pending_batches(
grpc_call_element* elem, subchannel_call_retry_state* retry_state,
- closure_to_execute* closures, size_t* num_closures) {
+ grpc_core::CallCombinerClosureList* closures) {
call_data* calld = static_cast<call_data*>(elem->call_data);
for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
pending_batch* pending = &calld->pending_batches[i];
@@ -2493,15 +2417,11 @@ static void add_subchannel_batches_for_pending_batches(
// started subchannel batch, since we'll propagate the
// completion when it completes.
if (retry_state->completed_recv_trailing_metadata) {
- subchannel_batch_data* batch_data =
- retry_state->recv_trailing_metadata_internal_batch;
- closure_to_execute* closure = &closures[(*num_closures)++];
- closure->closure = &batch_data->on_complete;
// Batches containing recv_trailing_metadata always succeed.
- closure->error = GRPC_ERROR_NONE;
- closure->reason =
- "re-executing on_complete for recv_trailing_metadata "
- "to propagate internally triggered result";
+ closures->Add(
+ &retry_state->recv_trailing_metadata_ready, GRPC_ERROR_NONE,
+ "re-executing recv_trailing_metadata_ready to propagate "
+ "internally triggered result");
} else {
batch_data_unref(retry_state->recv_trailing_metadata_internal_batch);
}
@@ -2513,14 +2433,19 @@ static void add_subchannel_batches_for_pending_batches(
if (calld->method_params == nullptr ||
calld->method_params->retry_policy() == nullptr ||
calld->retry_committed) {
- add_closure_for_subchannel_batch(calld, batch, closures, num_closures);
+ add_closure_for_subchannel_batch(elem, batch, closures);
pending_batch_clear(calld, pending);
continue;
}
// Create batch with the right number of callbacks.
- const int num_callbacks =
- 1 + batch->recv_initial_metadata + batch->recv_message;
- subchannel_batch_data* batch_data = batch_data_create(elem, num_callbacks);
+ const bool has_send_ops = batch->send_initial_metadata ||
+ batch->send_message ||
+ batch->send_trailing_metadata;
+ const int num_callbacks = has_send_ops + batch->recv_initial_metadata +
+ batch->recv_message +
+ batch->recv_trailing_metadata;
+ subchannel_batch_data* batch_data = batch_data_create(
+ elem, num_callbacks, has_send_ops /* set_on_complete */);
// Cache send ops if needed.
maybe_cache_send_ops_for_batch(calld, pending);
// send_initial_metadata.
@@ -2547,11 +2472,9 @@ static void add_subchannel_batches_for_pending_batches(
}
// recv_trailing_metadata.
if (batch->recv_trailing_metadata) {
- GPR_ASSERT(batch->collect_stats);
add_retriable_recv_trailing_metadata_op(calld, retry_state, batch_data);
}
- add_closure_for_subchannel_batch(calld, &batch_data->batch, closures,
- num_closures);
+ add_closure_for_subchannel_batch(elem, &batch_data->batch, closures);
// Track number of pending subchannel send batches.
// If this is the first one, take a ref to the call stack.
if (batch->send_initial_metadata || batch->send_message ||
@@ -2579,15 +2502,13 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) {
grpc_connected_subchannel_call_get_parent_data(
calld->subchannel_call));
// Construct list of closures to execute, one for each pending batch.
- // We can start up to 6 batches.
- closure_to_execute closures[GPR_ARRAY_SIZE(calld->pending_batches)];
- size_t num_closures = 0;
+ grpc_core::CallCombinerClosureList closures;
// Replay previously-returned send_* ops if needed.
subchannel_batch_data* replay_batch_data =
maybe_create_subchannel_batch_for_replay(elem, retry_state);
if (replay_batch_data != nullptr) {
- add_closure_for_subchannel_batch(calld, &replay_batch_data->batch, closures,
- &num_closures);
+ add_closure_for_subchannel_batch(elem, &replay_batch_data->batch,
+ &closures);
// Track number of pending subchannel send batches.
// If this is the first one, take a ref to the call stack.
if (calld->num_pending_retriable_subchannel_send_batches == 0) {
@@ -2596,17 +2517,16 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) {
++calld->num_pending_retriable_subchannel_send_batches;
}
// Now add pending batches.
- add_subchannel_batches_for_pending_batches(elem, retry_state, closures,
- &num_closures);
+ add_subchannel_batches_for_pending_batches(elem, retry_state, &closures);
// Start batches on subchannel call.
if (grpc_client_channel_trace.enabled()) {
gpr_log(GPR_INFO,
"chand=%p calld=%p: starting %" PRIuPTR
" retriable batches on subchannel_call=%p",
- chand, calld, num_closures, calld->subchannel_call);
+ chand, calld, closures.size(), calld->subchannel_call);
}
- execute_closures_in_call_combiner(elem, "start_retriable_subchannel_batches",
- closures, num_closures);
+ // Note: This will yield the call combiner.
+ closures.RunClosures(calld->call_combiner);
}
//
diff --git a/src/core/ext/filters/deadline/deadline_filter.cc b/src/core/ext/filters/deadline/deadline_filter.cc
index e0a41a3637..d23ad67ad5 100644
--- a/src/core/ext/filters/deadline/deadline_filter.cc
+++ b/src/core/ext/filters/deadline/deadline_filter.cc
@@ -128,21 +128,25 @@ static void cancel_timer_if_needed(grpc_deadline_state* deadline_state) {
}
}
-// Callback run when the call is complete.
-static void on_complete(void* arg, grpc_error* error) {
+// Callback run when we receive trailing metadata.
+static void recv_trailing_metadata_ready(void* arg, grpc_error* error) {
grpc_deadline_state* deadline_state = static_cast<grpc_deadline_state*>(arg);
cancel_timer_if_needed(deadline_state);
- // Invoke the next callback.
- GRPC_CLOSURE_RUN(deadline_state->next_on_complete, GRPC_ERROR_REF(error));
+ // Invoke the original callback.
+ GRPC_CLOSURE_RUN(deadline_state->original_recv_trailing_metadata_ready,
+ GRPC_ERROR_REF(error));
}
-// Inject our own on_complete callback into op.
-static void inject_on_complete_cb(grpc_deadline_state* deadline_state,
- grpc_transport_stream_op_batch* op) {
- deadline_state->next_on_complete = op->on_complete;
- GRPC_CLOSURE_INIT(&deadline_state->on_complete, on_complete, deadline_state,
+// Inject our own recv_trailing_metadata_ready callback into op.
+static void inject_recv_trailing_metadata_ready(
+ grpc_deadline_state* deadline_state, grpc_transport_stream_op_batch* op) {
+ deadline_state->original_recv_trailing_metadata_ready =
+ op->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
+ GRPC_CLOSURE_INIT(&deadline_state->recv_trailing_metadata_ready,
+ recv_trailing_metadata_ready, deadline_state,
grpc_schedule_on_exec_ctx);
- op->on_complete = &deadline_state->on_complete;
+ op->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
+ &deadline_state->recv_trailing_metadata_ready;
}
// Callback and associated state for starting the timer after call stack
@@ -226,7 +230,7 @@ void grpc_deadline_state_client_start_transport_stream_op_batch(
// Make sure we know when the call is complete, so that we can cancel
// the timer.
if (op->recv_trailing_metadata) {
- inject_on_complete_cb(deadline_state, op);
+ inject_recv_trailing_metadata_ready(deadline_state, op);
}
}
}
@@ -322,7 +326,7 @@ static void server_start_transport_stream_op_batch(
// the client never sends trailing metadata, because this is the
// hook that tells us when the call is complete on the server side.
if (op->recv_trailing_metadata) {
- inject_on_complete_cb(&calld->base.deadline_state, op);
+ inject_recv_trailing_metadata_ready(&calld->base.deadline_state, op);
}
}
// Chain to next filter.
diff --git a/src/core/ext/filters/deadline/deadline_filter.h b/src/core/ext/filters/deadline/deadline_filter.h
index 13207cbd6f..1d797f445a 100644
--- a/src/core/ext/filters/deadline/deadline_filter.h
+++ b/src/core/ext/filters/deadline/deadline_filter.h
@@ -37,12 +37,12 @@ typedef struct grpc_deadline_state {
grpc_deadline_timer_state timer_state;
grpc_timer timer;
grpc_closure timer_callback;
- // Closure to invoke when the call is complete.
+ // Closure to invoke when we receive trailing metadata.
// We use this to cancel the timer.
- grpc_closure on_complete;
- // The original on_complete closure, which we chain to after our own
- // closure is invoked.
- grpc_closure* next_on_complete;
+ grpc_closure recv_trailing_metadata_ready;
+ // The original recv_trailing_metadata_ready closure, which we chain to
+ // after our own closure is invoked.
+ grpc_closure* original_recv_trailing_metadata_ready;
} grpc_deadline_state;
//
diff --git a/src/core/ext/filters/http/client/http_client_filter.cc b/src/core/ext/filters/http/client/http_client_filter.cc
index ae94ce47b9..1678051beb 100644
--- a/src/core/ext/filters/http/client/http_client_filter.cc
+++ b/src/core/ext/filters/http/client/http_client_filter.cc
@@ -55,8 +55,8 @@ struct call_data {
grpc_closure recv_initial_metadata_ready;
// State for handling recv_trailing_metadata ops.
grpc_metadata_batch* recv_trailing_metadata;
- grpc_closure* original_recv_trailing_metadata_on_complete;
- grpc_closure recv_trailing_metadata_on_complete;
+ grpc_closure* original_recv_trailing_metadata_ready;
+ grpc_closure recv_trailing_metadata_ready;
// State for handling send_message ops.
grpc_transport_stream_op_batch* send_message_batch;
size_t send_message_bytes_read;
@@ -153,8 +153,7 @@ static void recv_initial_metadata_ready(void* user_data, grpc_error* error) {
GRPC_CLOSURE_RUN(calld->original_recv_initial_metadata_ready, error);
}
-static void recv_trailing_metadata_on_complete(void* user_data,
- grpc_error* error) {
+static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) {
grpc_call_element* elem = static_cast<grpc_call_element*>(user_data);
call_data* calld = static_cast<call_data*>(elem->call_data);
if (error == GRPC_ERROR_NONE) {
@@ -163,7 +162,7 @@ static void recv_trailing_metadata_on_complete(void* user_data,
} else {
GRPC_ERROR_REF(error);
}
- GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_on_complete, error);
+ GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata_ready, error);
}
static void send_message_on_complete(void* arg, grpc_error* error) {
@@ -312,8 +311,10 @@ static void hc_start_transport_stream_op_batch(
/* substitute our callback for the higher callback */
calld->recv_trailing_metadata =
batch->payload->recv_trailing_metadata.recv_trailing_metadata;
- calld->original_recv_trailing_metadata_on_complete = batch->on_complete;
- batch->on_complete = &calld->recv_trailing_metadata_on_complete;
+ calld->original_recv_trailing_metadata_ready =
+ batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
+ batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
+ &calld->recv_trailing_metadata_ready;
}
grpc_error* error = GRPC_ERROR_NONE;
@@ -420,8 +421,8 @@ static grpc_error* init_call_elem(grpc_call_element* elem,
GRPC_CLOSURE_INIT(&calld->recv_initial_metadata_ready,
recv_initial_metadata_ready, elem,
grpc_schedule_on_exec_ctx);
- GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_on_complete,
- recv_trailing_metadata_on_complete, elem,
+ GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready,
+ recv_trailing_metadata_ready, elem,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&calld->send_message_on_complete, send_message_on_complete,
elem, grpc_schedule_on_exec_ctx);
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
index a8090d18a6..0d6b72c66e 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
@@ -1149,12 +1149,10 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t) {
}
}
-/* Flag that this closure barrier wants stats to be updated before finishing */
-#define CLOSURE_BARRIER_STATS_BIT (1 << 0)
/* Flag that this closure barrier may be covering a write in a pollset, and so
we should not complete this closure until we can prove that the write got
scheduled */
-#define CLOSURE_BARRIER_MAY_COVER_WRITE (1 << 1)
+#define CLOSURE_BARRIER_MAY_COVER_WRITE (1 << 0)
/* First bit of the reference count, stored in the high order bits (with the low
bits being used for flags defined above) */
#define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16)
@@ -1206,10 +1204,6 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
grpc_error_add_child(closure->error_data.error, error);
}
if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) {
- if (closure->next_data.scratch & CLOSURE_BARRIER_STATS_BIT) {
- grpc_transport_move_stats(&s->stats, s->collecting_stats);
- s->collecting_stats = nullptr;
- }
if ((t->write_state == GRPC_CHTTP2_WRITE_STATE_IDLE) ||
!(closure->next_data.scratch & CLOSURE_BARRIER_MAY_COVER_WRITE)) {
GRPC_CLOSURE_RUN(closure, closure->error_data.error);
@@ -1351,9 +1345,14 @@ static void perform_stream_op_locked(void* stream_op,
}
grpc_closure* on_complete = op->on_complete;
+ // TODO(roth): This is a hack needed because we use data inside of the
+ // closure itself to do the barrier calculation (i.e., to ensure that
+ // we don't schedule the closure until all ops in the batch have been
+ // completed). This can go away once we move to a new C++ closure API
+ // that provides the ability to create a barrier closure.
if (on_complete == nullptr) {
- on_complete =
- GRPC_CLOSURE_CREATE(do_nothing, nullptr, grpc_schedule_on_exec_ctx);
+ on_complete = GRPC_CLOSURE_INIT(&op->handler_private.closure, do_nothing,
+ nullptr, grpc_schedule_on_exec_ctx);
}
/* use final_data as a barrier until enqueue time; the inital counter is
@@ -1361,12 +1360,6 @@ static void perform_stream_op_locked(void* stream_op,
on_complete->next_data.scratch = CLOSURE_BARRIER_FIRST_REF_BIT;
on_complete->error_data.error = GRPC_ERROR_NONE;
- if (op->collect_stats) {
- GPR_ASSERT(s->collecting_stats == nullptr);
- s->collecting_stats = op_payload->collect_stats.collect_stats;
- on_complete->next_data.scratch |= CLOSURE_BARRIER_STATS_BIT;
- }
-
if (op->cancel_stream) {
GRPC_STATS_INC_HTTP2_OP_CANCEL();
grpc_chttp2_cancel_stream(t, s, op_payload->cancel_stream.cancel_error);
@@ -1600,8 +1593,11 @@ static void perform_stream_op_locked(void* stream_op,
if (op->recv_trailing_metadata) {
GRPC_STATS_INC_HTTP2_OP_RECV_TRAILING_METADATA();
+ GPR_ASSERT(s->collecting_stats == nullptr);
+ s->collecting_stats = op_payload->recv_trailing_metadata.collect_stats;
GPR_ASSERT(s->recv_trailing_metadata_finished == nullptr);
- s->recv_trailing_metadata_finished = add_closure_barrier(on_complete);
+ s->recv_trailing_metadata_finished =
+ op_payload->recv_trailing_metadata.recv_trailing_metadata_ready;
s->recv_trailing_metadata =
op_payload->recv_trailing_metadata.recv_trailing_metadata;
s->final_metadata_requested = true;
@@ -1960,11 +1956,12 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_chttp2_transport* t,
}
if (s->read_closed && s->frame_storage.length == 0 && !pending_data &&
s->recv_trailing_metadata_finished != nullptr) {
+ grpc_transport_move_stats(&s->stats, s->collecting_stats);
+ s->collecting_stats = nullptr;
grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[1],
s->recv_trailing_metadata);
- grpc_chttp2_complete_closure_step(
- t, s, &s->recv_trailing_metadata_finished, GRPC_ERROR_NONE,
- "recv_trailing_metadata_finished");
+ null_then_run_closure(&s->recv_trailing_metadata_finished,
+ GRPC_ERROR_NONE);
}
}
}
diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc
index 34d5e6e218..8b73b01dea 100644
--- a/src/core/ext/transport/chttp2/transport/writing.cc
+++ b/src/core/ext/transport/chttp2/transport/writing.cc
@@ -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) {
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc
index 420c2d13e1..4a252d972d 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.cc
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc
@@ -925,6 +925,10 @@ static bool op_can_be_run(grpc_transport_stream_op_batch* curr_op,
result = false;
}
/* Check if every op that was asked for is done. */
+ /* TODO(muxi): We should not consider the recv ops here, since they
+ * have their own callbacks. We should invoke a batch's on_complete
+ * as soon as all of the batch's send ops are complete, even if
+ * there are still recv ops pending. */
else if (curr_op->send_initial_metadata &&
!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA]) {
CRONET_LOG(GPR_DEBUG, "Because");
@@ -1280,12 +1284,20 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) {
op_can_be_run(stream_op, s, &oas->state,
OP_RECV_TRAILING_METADATA)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_TRAILING_METADATA", oas);
- if (oas->s->state.rs.trailing_metadata_valid) {
+ grpc_error* error = GRPC_ERROR_NONE;
+ if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
+ error = GRPC_ERROR_REF(stream_state->cancel_error);
+ } else if (stream_state->state_op_done[OP_FAILED]) {
+ error = make_error_with_desc(GRPC_STATUS_UNAVAILABLE, "Unavailable.");
+ } else if (oas->s->state.rs.trailing_metadata_valid) {
grpc_chttp2_incoming_metadata_buffer_publish(
&oas->s->state.rs.trailing_metadata,
stream_op->payload->recv_trailing_metadata.recv_trailing_metadata);
stream_state->rs.trailing_metadata_valid = false;
}
+ GRPC_CLOSURE_SCHED(
+ stream_op->payload->recv_trailing_metadata.recv_trailing_metadata_ready,
+ error);
stream_state->state_op_done[OP_RECV_TRAILING_METADATA] = true;
result = ACTION_TAKEN_NO_CALLBACK;
} else if (stream_op->cancel_stream &&
@@ -1398,6 +1410,11 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
GRPC_CLOSURE_SCHED(op->payload->recv_message.recv_message_ready,
GRPC_ERROR_CANCELLED);
}
+ if (op->recv_trailing_metadata) {
+ GRPC_CLOSURE_SCHED(
+ op->payload->recv_trailing_metadata.recv_trailing_metadata_ready,
+ GRPC_ERROR_CANCELLED);
+ }
GRPC_CLOSURE_SCHED(op->on_complete, GRPC_ERROR_CANCELLED);
return;
}
diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc
index 2c3bff5c1e..b0ca7f8207 100644
--- a/src/core/ext/transport/inproc/inproc_transport.cc
+++ b/src/core/ext/transport/inproc/inproc_transport.cc
@@ -120,7 +120,6 @@ typedef struct inproc_stream {
struct inproc_stream* stream_list_next;
} inproc_stream;
-static grpc_closure do_nothing_closure;
static bool cancel_stream_locked(inproc_stream* s, grpc_error* error);
static void op_state_machine(void* arg, grpc_error* error);
@@ -373,6 +372,10 @@ static void complete_if_batch_end_locked(inproc_stream* s, grpc_error* error,
const char* msg) {
int is_sm = static_cast<int>(op == s->send_message_op);
int is_stm = static_cast<int>(op == s->send_trailing_md_op);
+ // TODO(vjpai): We should not consider the recv ops here, since they
+ // have their own callbacks. We should invoke a batch's on_complete
+ // as soon as all of the batch's send ops are complete, even if there
+ // are still recv ops pending.
int is_rim = static_cast<int>(op == s->recv_initial_md_op);
int is_rm = static_cast<int>(op == s->recv_message_op);
int is_rtm = static_cast<int>(op == s->recv_trailing_md_op);
@@ -496,6 +499,11 @@ static void fail_helper_locked(inproc_stream* s, grpc_error* error) {
s->send_trailing_md_op = nullptr;
}
if (s->recv_trailing_md_op) {
+ INPROC_LOG(GPR_INFO, "fail_helper %p scheduling trailing-metadata-ready %p",
+ s, error);
+ GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->payload->recv_trailing_metadata
+ .recv_trailing_metadata_ready,
+ GRPC_ERROR_REF(error));
INPROC_LOG(GPR_INFO, "fail_helper %p scheduling trailing-md-on-complete %p",
s, error);
complete_if_batch_end_locked(
@@ -639,6 +647,12 @@ static void op_state_machine(void* arg, grpc_error* error) {
s->trailing_md_sent = true;
if (!s->t->is_client && s->trailing_md_recvd && s->recv_trailing_md_op) {
INPROC_LOG(GPR_INFO,
+ "op_state_machine %p scheduling trailing-metadata-ready", s);
+ GRPC_CLOSURE_SCHED(
+ s->recv_trailing_md_op->payload->recv_trailing_metadata
+ .recv_trailing_metadata_ready,
+ GRPC_ERROR_NONE);
+ INPROC_LOG(GPR_INFO,
"op_state_machine %p scheduling trailing-md-on-complete", s);
GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->on_complete,
GRPC_ERROR_NONE);
@@ -711,6 +725,12 @@ static void op_state_machine(void* arg, grpc_error* error) {
}
if (s->recv_trailing_md_op && s->t->is_client && other &&
other->send_message_op) {
+ INPROC_LOG(GPR_INFO,
+ "op_state_machine %p scheduling trailing-metadata-ready %p", s,
+ GRPC_ERROR_NONE);
+ GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->payload->recv_trailing_metadata
+ .recv_trailing_metadata_ready,
+ GRPC_ERROR_NONE);
maybe_schedule_op_closure_locked(other, GRPC_ERROR_NONE);
}
if (s->to_read_trailing_md_filled) {
@@ -766,6 +786,10 @@ static void op_state_machine(void* arg, grpc_error* error) {
INPROC_LOG(GPR_INFO,
"op_state_machine %p scheduling trailing-md-on-complete %p",
s, new_err);
+ GRPC_CLOSURE_SCHED(
+ s->recv_trailing_md_op->payload->recv_trailing_metadata
+ .recv_trailing_metadata_ready,
+ GRPC_ERROR_REF(new_err));
GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->on_complete,
GRPC_ERROR_REF(new_err));
s->recv_trailing_md_op = nullptr;
@@ -859,6 +883,9 @@ static bool cancel_stream_locked(inproc_stream* s, grpc_error* error) {
// couldn't complete that because we hadn't yet sent out trailing
// md, now's the chance
if (!s->t->is_client && s->trailing_md_recvd && s->recv_trailing_md_op) {
+ GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->payload->recv_trailing_metadata
+ .recv_trailing_metadata_ready,
+ GRPC_ERROR_REF(s->cancel_self_error));
complete_if_batch_end_locked(
s, s->cancel_self_error, s->recv_trailing_md_op,
"cancel_stream scheduling trailing-md-on-complete");
@@ -873,6 +900,8 @@ static bool cancel_stream_locked(inproc_stream* s, grpc_error* error) {
return ret;
}
+static void do_nothing(void* arg, grpc_error* error) {}
+
static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
grpc_transport_stream_op_batch* op) {
INPROC_LOG(GPR_INFO, "perform_stream_op %p %p %p", gt, gs, op);
@@ -892,8 +921,14 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
}
grpc_error* error = GRPC_ERROR_NONE;
grpc_closure* on_complete = op->on_complete;
+ // TODO(roth): This is a hack needed because we use data inside of the
+ // closure itself to do the barrier calculation (i.e., to ensure that
+ // we don't schedule the closure until all ops in the batch have been
+ // completed). This can go away once we move to a new C++ closure API
+ // that provides the ability to create a barrier closure.
if (on_complete == nullptr) {
- on_complete = &do_nothing_closure;
+ on_complete = GRPC_CLOSURE_INIT(&op->handler_private.closure, do_nothing,
+ nullptr, grpc_schedule_on_exec_ctx);
}
if (op->cancel_stream) {
@@ -1026,6 +1061,15 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
GRPC_CLOSURE_SCHED(op->payload->recv_message.recv_message_ready,
GRPC_ERROR_REF(error));
}
+ if (op->recv_trailing_metadata) {
+ INPROC_LOG(
+ GPR_INFO,
+ "perform_stream_op error %p scheduling trailing-metadata-ready %p",
+ s, error);
+ GRPC_CLOSURE_SCHED(
+ op->payload->recv_trailing_metadata.recv_trailing_metadata_ready,
+ GRPC_ERROR_REF(error));
+ }
}
INPROC_LOG(GPR_INFO, "perform_stream_op %p scheduling on_complete %p", s,
error);
@@ -1129,12 +1173,8 @@ static grpc_endpoint* get_endpoint(grpc_transport* t) { return nullptr; }
/*******************************************************************************
* GLOBAL INIT AND DESTROY
*/
-static void do_nothing(void* arg, grpc_error* error) {}
-
void grpc_inproc_transport_init(void) {
grpc_core::ExecCtx exec_ctx;
- GRPC_CLOSURE_INIT(&do_nothing_closure, do_nothing, nullptr,
- grpc_schedule_on_exec_ctx);
g_empty_slice = grpc_slice_from_static_buffer(nullptr, 0);
grpc_slice key_tmp = grpc_slice_from_static_string(":path");
diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc
index eb7214b355..0f655d8716 100644
--- a/src/core/lib/channel/channel_trace.cc
+++ b/src/core/lib/channel/channel_trace.cc
@@ -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
diff --git a/src/core/lib/channel/channel_trace.h b/src/core/lib/channel/channel_trace.h
index 1df1e585f2..0dd162a777 100644
--- a/src/core/lib/channel/channel_trace.h
+++ b/src/core/lib/channel/channel_trace.h
@@ -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 */
diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc
new file mode 100644
index 0000000000..3550fc0551
--- /dev/null
+++ b/src/core/lib/channel/channelz.cc
@@ -0,0 +1,185 @@
+/*
+ *
+ * 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 {
+ return grpc_channel_check_connectivity_state(channel_, false);
+ }
+}
+
+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
diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h
new file mode 100644
index 0000000000..2aad1e82f4
--- /dev/null
+++ b/src/core/lib/channel/channelz.h
@@ -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 */
diff --git a/src/core/lib/channel/connected_channel.cc b/src/core/lib/channel/connected_channel.cc
index ddd3029402..e2ea334ded 100644
--- a/src/core/lib/channel/connected_channel.cc
+++ b/src/core/lib/channel/connected_channel.cc
@@ -51,6 +51,7 @@ typedef struct connected_channel_call_data {
callback_state on_complete[6]; // Max number of pending batches.
callback_state recv_initial_metadata_ready;
callback_state recv_message_ready;
+ callback_state recv_trailing_metadata_ready;
} call_data;
static void run_in_call_combiner(void* arg, grpc_error* error) {
@@ -111,6 +112,12 @@ static void con_start_transport_stream_op_batch(
intercept_callback(calld, state, false, "recv_message_ready",
&batch->payload->recv_message.recv_message_ready);
}
+ if (batch->recv_trailing_metadata) {
+ callback_state* state = &calld->recv_trailing_metadata_ready;
+ intercept_callback(
+ calld, state, false, "recv_trailing_metadata_ready",
+ &batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready);
+ }
if (batch->cancel_stream) {
// There can be more than one cancellation batch in flight at any
// given time, so we can't just pick out a fixed index into
@@ -121,7 +128,7 @@ static void con_start_transport_stream_op_batch(
static_cast<callback_state*>(gpr_malloc(sizeof(*state)));
intercept_callback(calld, state, true, "on_complete (cancel_stream)",
&batch->on_complete);
- } else {
+ } else if (batch->on_complete != nullptr) {
callback_state* state = get_state_for_batch(calld, batch);
intercept_callback(calld, state, false, "on_complete", &batch->on_complete);
}
diff --git a/src/core/lib/gprpp/inlined_vector.h b/src/core/lib/gprpp/inlined_vector.h
index f36f6cb706..0d2586e507 100644
--- a/src/core/lib/gprpp/inlined_vector.h
+++ b/src/core/lib/gprpp/inlined_vector.h
@@ -99,6 +99,8 @@ class InlinedVector {
void push_back(T&& value) { emplace_back(std::move(value)); }
size_t size() const { return size_; }
+ bool empty() const { return size_ == 0; }
+
size_t capacity() const { return capacity_; }
void clear() {
diff --git a/src/core/lib/iomgr/call_combiner.h b/src/core/lib/iomgr/call_combiner.h
index 0ccd08ea57..641fa18082 100644
--- a/src/core/lib/iomgr/call_combiner.h
+++ b/src/core/lib/iomgr/call_combiner.h
@@ -26,6 +26,7 @@
#include <grpc/support/atm.h>
#include "src/core/lib/gpr/mpscq.h"
+#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/iomgr/closure.h"
// A simple, lock-free mechanism for serializing activity related to a
@@ -109,4 +110,83 @@ void grpc_call_combiner_set_notify_on_cancel(grpc_call_combiner* call_combiner,
void grpc_call_combiner_cancel(grpc_call_combiner* call_combiner,
grpc_error* error);
+namespace grpc_core {
+
+// Helper for running a list of closures in a call combiner.
+//
+// Each callback running in the call combiner will eventually be
+// returned to the surface, at which point the surface will yield the
+// call combiner. So when we are running in the call combiner and have
+// more than one callback to return to the surface, we need to re-enter
+// the call combiner for all but one of those callbacks.
+class CallCombinerClosureList {
+ public:
+ CallCombinerClosureList() {}
+
+ // Adds a closure to the list. The closure must eventually result in
+ // the call combiner being yielded.
+ void Add(grpc_closure* closure, grpc_error* error, const char* reason) {
+ closures_.emplace_back(closure, error, reason);
+ }
+
+ // Runs all closures in the call combiner and yields the call combiner.
+ //
+ // All but one of the closures in the list will be scheduled via
+ // GRPC_CALL_COMBINER_START(), and the remaining closure will be
+ // scheduled via GRPC_CLOSURE_SCHED(), which will eventually result in
+ // yielding the call combiner. If the list is empty, then the call
+ // combiner will be yielded immediately.
+ void RunClosures(grpc_call_combiner* call_combiner) {
+ if (closures_.empty()) {
+ GRPC_CALL_COMBINER_STOP(call_combiner, "no closures to schedule");
+ return;
+ }
+ for (size_t i = 1; i < closures_.size(); ++i) {
+ auto& closure = closures_[i];
+ GRPC_CALL_COMBINER_START(call_combiner, closure.closure, closure.error,
+ closure.reason);
+ }
+ if (grpc_call_combiner_trace.enabled()) {
+ gpr_log(GPR_INFO,
+ "CallCombinerClosureList executing closure while already "
+ "holding call_combiner %p: closure=%p error=%s reason=%s",
+ call_combiner, closures_[0].closure,
+ grpc_error_string(closures_[0].error), closures_[0].reason);
+ }
+ // This will release the call combiner.
+ GRPC_CLOSURE_SCHED(closures_[0].closure, closures_[0].error);
+ closures_.clear();
+ }
+
+ // Runs all closures in the call combiner, but does NOT yield the call
+ // combiner. All closures will be scheduled via GRPC_CALL_COMBINER_START().
+ void RunClosuresWithoutYielding(grpc_call_combiner* call_combiner) {
+ for (size_t i = 0; i < closures_.size(); ++i) {
+ auto& closure = closures_[i];
+ GRPC_CALL_COMBINER_START(call_combiner, closure.closure, closure.error,
+ closure.reason);
+ }
+ closures_.clear();
+ }
+
+ size_t size() const { return closures_.size(); }
+
+ private:
+ struct CallCombinerClosure {
+ grpc_closure* closure;
+ grpc_error* error;
+ const char* reason;
+
+ CallCombinerClosure(grpc_closure* closure, grpc_error* error,
+ const char* reason)
+ : closure(closure), error(error), reason(reason) {}
+ };
+
+ // There are generally a maximum of 6 closures to run in the call
+ // combiner, one for each pending op.
+ InlinedVector<CallCombinerClosure, 6> closures_;
+};
+
+} // namespace grpc_core
+
#endif /* GRPC_CORE_LIB_IOMGR_CALL_COMBINER_H */
diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h
index 34a494485d..f14c723844 100644
--- a/src/core/lib/iomgr/closure.h
+++ b/src/core/lib/iomgr/closure.h
@@ -283,9 +283,10 @@ inline void grpc_closure_sched(grpc_closure* c, grpc_error* error) {
if (c->scheduled) {
gpr_log(GPR_ERROR,
"Closure already scheduled. (closure: %p, created: [%s:%d], "
- "previously scheduled at: [%s: %d] run?: %s",
+ "previously scheduled at: [%s: %d], newly scheduled at [%s: %d], "
+ "run?: %s",
c, c->file_created, c->line_created, c->file_initiated,
- c->line_initiated, c->run ? "true" : "false");
+ c->line_initiated, file, line, c->run ? "true" : "false");
abort();
}
c->scheduled = true;
diff --git a/src/core/lib/iomgr/socket_utils.h b/src/core/lib/iomgr/socket_utils.h
index cf1a7be648..14bb081e93 100644
--- a/src/core/lib/iomgr/socket_utils.h
+++ b/src/core/lib/iomgr/socket_utils.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);
diff --git a/src/core/lib/iomgr/socket_utils_common_posix.cc b/src/core/lib/iomgr/socket_utils_common_posix.cc
index caee652307..c4b991c94d 100644
--- a/src/core/lib/iomgr/socket_utils_common_posix.cc
+++ b/src/core/lib/iomgr/socket_utils_common_posix.cc
@@ -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);
}
diff --git a/src/core/lib/iomgr/socket_utils_uv.cc b/src/core/lib/iomgr/socket_utils_uv.cc
index 7eba40c46b..b5f96b52df 100644
--- a/src/core/lib/iomgr/socket_utils_uv.cc
+++ b/src/core/lib/iomgr/socket_utils_uv.cc
@@ -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);
}
diff --git a/src/core/lib/iomgr/socket_utils_windows.cc b/src/core/lib/iomgr/socket_utils_windows.cc
index 3e7b5b812d..9137ab98e6 100644
--- a/src/core/lib/iomgr/socket_utils_windows.cc
+++ b/src/core/lib/iomgr/socket_utils_windows.cc
@@ -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);
}
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc
index 38c9175717..c456ffaf5d 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc
@@ -231,7 +231,8 @@ end:
creds->base.vtable = &google_default_credentials_vtable;
creds->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_GOOGLE_DEFAULT;
gpr_ref_init(&creds->base.refcount, 1);
- creds->ssl_creds = grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
+ creds->ssl_creds =
+ grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
GPR_ASSERT(creds->ssl_creds != nullptr);
grpc_alts_credentials_options* options =
grpc_alts_credentials_client_options_create();
diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.cc b/src/core/lib/security/credentials/ssl/ssl_credentials.cc
index 2b6377d3ec..3d6f2f200a 100644
--- a/src/core/lib/security/credentials/ssl/ssl_credentials.cc
+++ b/src/core/lib/security/credentials/ssl/ssl_credentials.cc
@@ -48,6 +48,10 @@ static void ssl_destruct(grpc_channel_credentials* creds) {
grpc_ssl_credentials* c = reinterpret_cast<grpc_ssl_credentials*>(creds);
gpr_free(c->config.pem_root_certs);
grpc_tsi_ssl_pem_key_cert_pairs_destroy(c->config.pem_key_cert_pair, 1);
+ if (c->config.verify_options.verify_peer_destruct != nullptr) {
+ c->config.verify_options.verify_peer_destruct(
+ c->config.verify_options.verify_peer_callback_userdata);
+ }
}
static grpc_security_status ssl_create_security_connector(
@@ -87,6 +91,7 @@ static grpc_channel_credentials_vtable ssl_vtable = {
static void ssl_build_config(const char* pem_root_certs,
grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
+ const verify_peer_options* verify_options,
grpc_ssl_config* config) {
if (pem_root_certs != nullptr) {
config->pem_root_certs = gpr_strdup(pem_root_certs);
@@ -101,23 +106,32 @@ static void ssl_build_config(const char* pem_root_certs,
config->pem_key_cert_pair->private_key =
gpr_strdup(pem_key_cert_pair->private_key);
}
+ if (verify_options != nullptr) {
+ memcpy(&config->verify_options, verify_options,
+ sizeof(verify_peer_options));
+ } else {
+ // Otherwise set all options to default values
+ memset(&config->verify_options, 0, sizeof(verify_peer_options));
+ }
}
grpc_channel_credentials* grpc_ssl_credentials_create(
const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair,
- void* reserved) {
+ const verify_peer_options* verify_options, void* reserved) {
grpc_ssl_credentials* c = static_cast<grpc_ssl_credentials*>(
gpr_zalloc(sizeof(grpc_ssl_credentials)));
GRPC_API_TRACE(
"grpc_ssl_credentials_create(pem_root_certs=%s, "
"pem_key_cert_pair=%p, "
+ "verify_options=%p, "
"reserved=%p)",
- 3, (pem_root_certs, pem_key_cert_pair, reserved));
+ 4, (pem_root_certs, pem_key_cert_pair, verify_options, reserved));
GPR_ASSERT(reserved == nullptr);
c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
c->base.vtable = &ssl_vtable;
gpr_ref_init(&c->base.refcount, 1);
- ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config);
+ ssl_build_config(pem_root_certs, pem_key_cert_pair, verify_options,
+ &c->config);
return &c->base;
}
diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc
index b54a7643e4..cc72bb6164 100644
--- a/src/core/lib/security/security_connector/security_connector.cc
+++ b/src/core/lib/security/security_connector/security_connector.cc
@@ -620,6 +620,7 @@ typedef struct {
tsi_ssl_client_handshaker_factory* client_handshaker_factory;
char* target_name;
char* overridden_target_name;
+ const verify_peer_options* verify_options;
} grpc_ssl_channel_security_connector;
typedef struct {
@@ -878,11 +879,34 @@ static void ssl_channel_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_closure* on_peer_checked) {
grpc_ssl_channel_security_connector* c =
reinterpret_cast<grpc_ssl_channel_security_connector*>(sc);
- grpc_error* error = ssl_check_peer(sc,
- c->overridden_target_name != nullptr
- ? c->overridden_target_name
- : c->target_name,
- &peer, auth_context);
+ const char* target_name = c->overridden_target_name != nullptr
+ ? c->overridden_target_name
+ : c->target_name;
+ grpc_error* error = ssl_check_peer(sc, target_name, &peer, auth_context);
+ if (error == GRPC_ERROR_NONE &&
+ c->verify_options->verify_peer_callback != nullptr) {
+ const tsi_peer_property* p =
+ tsi_peer_get_property_by_name(&peer, TSI_X509_PEM_CERT_PROPERTY);
+ if (p == nullptr) {
+ error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "Cannot check peer: missing pem cert property.");
+ } else {
+ char* peer_pem = static_cast<char*>(gpr_malloc(p->value.length + 1));
+ memcpy(peer_pem, p->value.data, p->value.length);
+ peer_pem[p->value.length] = '\0';
+ int callback_status = c->verify_options->verify_peer_callback(
+ target_name, peer_pem,
+ c->verify_options->verify_peer_callback_userdata);
+ gpr_free(peer_pem);
+ if (callback_status) {
+ char* msg;
+ gpr_asprintf(&msg, "Verify peer callback returned a failure (%d)",
+ callback_status);
+ error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
+ gpr_free(msg);
+ }
+ }
+ }
GRPC_CLOSURE_SCHED(on_peer_checked, error);
tsi_peer_destruct(&peer);
}
@@ -1047,6 +1071,7 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
if (overridden_target_name != nullptr) {
c->overridden_target_name = gpr_strdup(overridden_target_name);
}
+ c->verify_options = &config->verify_options;
has_key_cert_pair = config->pem_key_cert_pair != nullptr &&
config->pem_key_cert_pair->private_key != nullptr &&
diff --git a/src/core/lib/security/security_connector/security_connector.h b/src/core/lib/security/security_connector/security_connector.h
index f9723166d0..67a506b576 100644
--- a/src/core/lib/security/security_connector/security_connector.h
+++ b/src/core/lib/security/security_connector/security_connector.h
@@ -193,6 +193,7 @@ grpc_server_security_connector* grpc_fake_server_security_connector_create(
typedef struct {
tsi_ssl_pem_key_cert_pair* pem_key_cert_pair;
char* pem_root_certs;
+ verify_peer_options verify_options;
} grpc_ssl_config;
/* Creates an SSL channel_security_connector.
diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc
index 1cf8ea94e7..556eb234b4 100644
--- a/src/core/lib/surface/call.cc
+++ b/src/core/lib/surface/call.cc
@@ -233,6 +233,7 @@ struct grpc_call {
grpc_closure receiving_slice_ready;
grpc_closure receiving_stream_ready;
grpc_closure receiving_initial_metadata_ready;
+ grpc_closure receiving_trailing_metadata_ready;
uint32_t test_only_last_message_flags;
grpc_closure release_call;
@@ -270,8 +271,17 @@ struct grpc_call {
grpc_core::TraceFlag grpc_call_error_trace(false, "call_error");
grpc_core::TraceFlag grpc_compression_trace(false, "compression");
-#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack*)((call) + 1))
-#define CALL_FROM_CALL_STACK(call_stack) (((grpc_call*)(call_stack)) - 1)
+/* Given a size, round up to the next multiple of sizeof(void*) */
+#define ROUND_UP_TO_ALIGNMENT_SIZE(x) \
+ (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u))
+
+#define CALL_STACK_FROM_CALL(call) \
+ (grpc_call_stack*)((char*)(call) + \
+ ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)))
+#define CALL_FROM_CALL_STACK(call_stack) \
+ (grpc_call*)(((char*)(call_stack)) - \
+ ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)))
+
#define CALL_ELEM_FROM_CALL(call, idx) \
grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx)
#define CALL_FROM_TOP_ELEM(top_elem) \
@@ -342,8 +352,9 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args,
size_t initial_size = grpc_channel_get_call_size_estimate(args->channel);
GRPC_STATS_INC_CALL_INITIAL_SIZE(initial_size);
gpr_arena* arena = gpr_arena_create(initial_size);
- call = static_cast<grpc_call*>(gpr_arena_alloc(
- arena, sizeof(grpc_call) + channel_stack->call_stack_size));
+ call = static_cast<grpc_call*>(
+ gpr_arena_alloc(arena, ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call)) +
+ channel_stack->call_stack_size));
gpr_ref_init(&call->ext_ref, 1);
call->arena = arena;
grpc_call_combiner_init(&call->call_combiner);
@@ -478,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;
@@ -520,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;
@@ -1076,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,
@@ -1209,7 +1224,6 @@ static void post_batch_completion(batch_control* bctl) {
if (bctl->op.send_initial_metadata) {
grpc_metadata_batch_destroy(
-
&call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
}
if (bctl->op.send_message) {
@@ -1217,14 +1231,9 @@ static void post_batch_completion(batch_control* bctl) {
}
if (bctl->op.send_trailing_metadata) {
grpc_metadata_batch_destroy(
-
&call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
}
if (bctl->op.recv_trailing_metadata) {
- grpc_metadata_batch* md =
- &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
- recv_trailing_filter(call, md);
-
/* propagate cancellation to any interested children */
gpr_atm_rel_store(&call->received_final_op_atm, 1);
parent_call* pc = get_parent_call(call);
@@ -1246,7 +1255,6 @@ static void post_batch_completion(batch_control* bctl) {
}
gpr_mu_unlock(&pc->child_list_mu);
}
-
if (call->is_client) {
get_final_status(call, set_status_value_directly,
call->final_op.client.status,
@@ -1256,7 +1264,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;
}
@@ -1538,6 +1554,17 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) {
finish_batch_step(bctl);
}
+static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) {
+ batch_control* bctl = static_cast<batch_control*>(bctlp);
+ grpc_call* call = bctl->call;
+ GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready");
+ add_batch_error(bctl, GRPC_ERROR_REF(error), false);
+ grpc_metadata_batch* md =
+ &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
+ recv_trailing_filter(call, md);
+ finish_batch_step(bctl);
+}
+
static void finish_batch(void* bctlp, grpc_error* error) {
batch_control* bctl = static_cast<batch_control*>(bctlp);
grpc_call* call = bctl->call;
@@ -1558,7 +1585,8 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
size_t i;
const grpc_op* op;
batch_control* bctl;
- int num_completion_callbacks_needed = 1;
+ bool has_send_ops = false;
+ int num_recv_ops = 0;
grpc_call_error error = GRPC_CALL_OK;
grpc_transport_stream_op_batch* stream_op;
grpc_transport_stream_op_batch_payload* stream_op_payload;
@@ -1664,6 +1692,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
stream_op_payload->send_initial_metadata.peer_string =
&call->peer_string;
}
+ has_send_ops = true;
break;
}
case GRPC_OP_SEND_MESSAGE: {
@@ -1693,6 +1722,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
&op->data.send_message.send_message->data.raw.slice_buffer, flags);
stream_op_payload->send_message.send_message.reset(
call->sending_stream.get());
+ has_send_ops = true;
break;
}
case GRPC_OP_SEND_CLOSE_FROM_CLIENT: {
@@ -1713,6 +1743,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
call->sent_final_op = true;
stream_op_payload->send_trailing_metadata.send_trailing_metadata =
&call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
+ has_send_ops = true;
break;
}
case GRPC_OP_SEND_STATUS_FROM_SERVER: {
@@ -1777,6 +1808,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
}
stream_op_payload->send_trailing_metadata.send_trailing_metadata =
&call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
+ has_send_ops = true;
break;
}
case GRPC_OP_RECV_INITIAL_METADATA: {
@@ -1804,7 +1836,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
stream_op_payload->recv_initial_metadata.peer_string =
&call->peer_string;
}
- num_completion_callbacks_needed++;
+ ++num_recv_ops;
break;
}
case GRPC_OP_RECV_MESSAGE: {
@@ -1826,7 +1858,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
grpc_schedule_on_exec_ctx);
stream_op_payload->recv_message.recv_message_ready =
&call->receiving_stream_ready;
- num_completion_callbacks_needed++;
+ ++num_recv_ops;
break;
}
case GRPC_OP_RECV_STATUS_ON_CLIENT: {
@@ -1852,11 +1884,16 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
call->final_op.client.error_string =
op->data.recv_status_on_client.error_string;
stream_op->recv_trailing_metadata = true;
- stream_op->collect_stats = true;
stream_op_payload->recv_trailing_metadata.recv_trailing_metadata =
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
- stream_op_payload->collect_stats.collect_stats =
+ stream_op_payload->recv_trailing_metadata.collect_stats =
&call->final_info.stats.transport_stream_stats;
+ GRPC_CLOSURE_INIT(&call->receiving_trailing_metadata_ready,
+ receiving_trailing_metadata_ready, bctl,
+ grpc_schedule_on_exec_ctx);
+ stream_op_payload->recv_trailing_metadata.recv_trailing_metadata_ready =
+ &call->receiving_trailing_metadata_ready;
+ ++num_recv_ops;
break;
}
case GRPC_OP_RECV_CLOSE_ON_SERVER: {
@@ -1877,11 +1914,16 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
call->final_op.server.cancelled =
op->data.recv_close_on_server.cancelled;
stream_op->recv_trailing_metadata = true;
- stream_op->collect_stats = true;
stream_op_payload->recv_trailing_metadata.recv_trailing_metadata =
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
- stream_op_payload->collect_stats.collect_stats =
+ stream_op_payload->recv_trailing_metadata.collect_stats =
&call->final_info.stats.transport_stream_stats;
+ GRPC_CLOSURE_INIT(&call->receiving_trailing_metadata_ready,
+ receiving_trailing_metadata_ready, bctl,
+ grpc_schedule_on_exec_ctx);
+ stream_op_payload->recv_trailing_metadata.recv_trailing_metadata_ready =
+ &call->receiving_trailing_metadata_ready;
+ ++num_recv_ops;
break;
}
}
@@ -1891,13 +1933,15 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
if (!is_notify_tag_closure) {
GPR_ASSERT(grpc_cq_begin_op(call->cq, notify_tag));
}
- gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed);
+ gpr_ref_init(&bctl->steps_to_complete, (has_send_ops ? 1 : 0) + num_recv_ops);
- GRPC_CLOSURE_INIT(&bctl->finish_batch, finish_batch, bctl,
- grpc_schedule_on_exec_ctx);
- stream_op->on_complete = &bctl->finish_batch;
- gpr_atm_rel_store(&call->any_ops_sent_atm, 1);
+ if (has_send_ops) {
+ GRPC_CLOSURE_INIT(&bctl->finish_batch, finish_batch, bctl,
+ grpc_schedule_on_exec_ctx);
+ stream_op->on_complete = &bctl->finish_batch;
+ }
+ gpr_atm_rel_store(&call->any_ops_sent_atm, 1);
execute_batch(call, stream_op, &bctl->start_batch);
done:
diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc
index a466b325be..d5d75fcb2a 100644
--- a/src/core/lib/surface/channel.cc
+++ b/src/core/lib/surface/channel.cc
@@ -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);
diff --git a/src/core/lib/surface/channel.h b/src/core/lib/surface/channel.h
index 288313951e..e5ff2c3596 100644
--- a/src/core/lib/surface/channel.h
+++ b/src/core/lib/surface/channel.h
@@ -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.
diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc
index 039d603394..cbdb77c844 100644
--- a/src/core/lib/transport/transport.cc
+++ b/src/core/lib/transport/transport.cc
@@ -212,21 +212,32 @@ void grpc_transport_stream_op_batch_finish_with_failure(
if (batch->send_message) {
batch->payload->send_message.send_message.reset();
}
- if (batch->recv_message) {
- GRPC_CALL_COMBINER_START(
- call_combiner, batch->payload->recv_message.recv_message_ready,
- GRPC_ERROR_REF(error), "failing recv_message_ready");
+ if (batch->cancel_stream) {
+ GRPC_ERROR_UNREF(batch->payload->cancel_stream.cancel_error);
}
+ // Construct a list of closures to execute.
+ grpc_core::CallCombinerClosureList closures;
if (batch->recv_initial_metadata) {
- GRPC_CALL_COMBINER_START(
- call_combiner,
+ closures.Add(
batch->payload->recv_initial_metadata.recv_initial_metadata_ready,
GRPC_ERROR_REF(error), "failing recv_initial_metadata_ready");
}
- GRPC_CLOSURE_SCHED(batch->on_complete, error);
- if (batch->cancel_stream) {
- GRPC_ERROR_UNREF(batch->payload->cancel_stream.cancel_error);
+ if (batch->recv_message) {
+ closures.Add(batch->payload->recv_message.recv_message_ready,
+ GRPC_ERROR_REF(error), "failing recv_message_ready");
+ }
+ if (batch->recv_trailing_metadata) {
+ closures.Add(
+ batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready,
+ GRPC_ERROR_REF(error), "failing recv_trailing_metadata_ready");
+ }
+ if (batch->on_complete != nullptr) {
+ closures.Add(batch->on_complete, GRPC_ERROR_REF(error),
+ "failing on_complete");
}
+ // Execute closures.
+ closures.RunClosures(call_combiner);
+ GRPC_ERROR_UNREF(error);
}
typedef struct {
diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h
index b2e252d939..585b9dfae9 100644
--- a/src/core/lib/transport/transport.h
+++ b/src/core/lib/transport/transport.h
@@ -122,9 +122,15 @@ typedef struct grpc_transport_stream_op_batch_payload
/* Transport stream op: a set of operations to perform on a transport
against a single stream */
typedef struct grpc_transport_stream_op_batch {
- /** Should be enqueued when all requested operations (excluding recv_message
- and recv_initial_metadata which have their own closures) in a given batch
- have been completed. */
+ /** Should be scheduled when all of the non-recv operations in the batch
+ are complete.
+
+ The recv ops (recv_initial_metadata, recv_message, and
+ recv_trailing_metadata) each have their own callbacks. If a batch
+ contains both recv ops and non-recv ops, on_complete should be
+ scheduled as soon as the non-recv ops are complete, regardless of
+ whether or not the recv ops are complete. If a batch contains
+ only recv ops, on_complete can be null. */
grpc_closure* on_complete;
/** Values for the stream op (fields set are determined by flags above) */
@@ -149,9 +155,6 @@ typedef struct grpc_transport_stream_op_batch {
*/
bool recv_trailing_metadata : 1;
- /** Collect any stats into provided buffer, zero internal stat counters */
- bool collect_stats : 1;
-
/** Cancel this stream with the provided error */
bool cancel_stream : 1;
@@ -219,11 +222,10 @@ struct grpc_transport_stream_op_batch_payload {
struct {
grpc_metadata_batch* recv_trailing_metadata;
- } recv_trailing_metadata;
-
- struct {
grpc_transport_stream_stats* collect_stats;
- } collect_stats;
+ /** Should be enqueued when initial metadata is ready to be processed. */
+ grpc_closure* recv_trailing_metadata_ready;
+ } recv_trailing_metadata;
/** Forcefully close this stream.
The HTTP2 semantics should be:
diff --git a/src/core/lib/transport/transport_op_string.cc b/src/core/lib/transport/transport_op_string.cc
index 25ab492f3a..8c7db642a5 100644
--- a/src/core/lib/transport/transport_op_string.cc
+++ b/src/core/lib/transport/transport_op_string.cc
@@ -120,13 +120,6 @@ char* grpc_transport_stream_op_batch_string(
gpr_strvec_add(&b, tmp);
}
- if (op->collect_stats) {
- gpr_strvec_add(&b, gpr_strdup(" "));
- gpr_asprintf(&tmp, "COLLECT_STATS:%p",
- op->payload->collect_stats.collect_stats);
- gpr_strvec_add(&b, tmp);
- }
-
out = gpr_strvec_flatten(&b, nullptr);
gpr_strvec_destroy(&b);
diff --git a/src/cpp/README.md b/src/cpp/README.md
index ac76bf74ed..f16cab1f44 100644
--- a/src/cpp/README.md
+++ b/src/cpp/README.md
@@ -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.
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index 00245b397d..bdb6359632 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -83,7 +83,8 @@ std::shared_ptr<ChannelCredentials> SslCredentials(
grpc_channel_credentials* c_creds = grpc_ssl_credentials_create(
options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
- options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr);
+ options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr,
+ nullptr);
return WrapChannelCredentials(c_creds);
}
diff --git a/test/core/statistics/performance_test.cc b/src/cpp/ext/filters/census/channel_filter.cc
index 9d4fd6ef90..4ac684d277 100644
--- a/test/core/statistics/performance_test.cc
+++ b/src/cpp/ext/filters/census/channel_filter.cc
@@ -1,6 +1,6 @@
/*
*
- * Copyright 2015 gRPC authors.
+ * Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,16 +16,15 @@
*
*/
-#include "test/core/statistics/census_log_tests.h"
+#include <grpc/support/port_platform.h>
-#include <stdlib.h>
+#include "src/cpp/ext/filters/census/channel_filter.h"
-#include <grpc/support/time.h>
-#include "test/core/util/test_config.h"
+namespace grpc {
-int main(int argc, char** argv) {
- grpc_test_init(argc, argv);
- srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
- test_performance();
- return 0;
+grpc_error* CensusChannelData::Init(grpc_channel_element* elem,
+ grpc_channel_element_args* args) {
+ return GRPC_ERROR_NONE;
}
+
+} // namespace grpc
diff --git a/test/core/statistics/multiple_writers_test.cc b/src/cpp/ext/filters/census/channel_filter.h
index 47410ab105..0b7c682681 100644
--- a/test/core/statistics/multiple_writers_test.cc
+++ b/src/cpp/ext/filters/census/channel_filter.h
@@ -1,6 +1,6 @@
/*
*
- * Copyright 2015 gRPC authors.
+ * Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,16 +16,21 @@
*
*/
-#include "test/core/statistics/census_log_tests.h"
+#ifndef GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CHANNEL_FILTER_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CHANNEL_FILTER_H
-#include <stdlib.h>
+#include <grpc/support/port_platform.h>
-#include <grpc/support/time.h>
-#include "test/core/util/test_config.h"
+#include "src/cpp/ext/filters/census/context.h"
-int main(int argc, char** argv) {
- grpc_test_init(argc, argv);
- srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
- test_multiple_writers();
- return 0;
-}
+namespace grpc {
+
+class CensusChannelData : public ChannelData {
+ public:
+ grpc_error* Init(grpc_channel_element* elem,
+ grpc_channel_element_args* args) override;
+};
+
+} // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CHANNEL_FILTER_H */
diff --git a/src/cpp/ext/filters/census/client_filter.cc b/src/cpp/ext/filters/census/client_filter.cc
new file mode 100644
index 0000000000..940d42d100
--- /dev/null
+++ b/src/cpp/ext/filters/census/client_filter.cc
@@ -0,0 +1,165 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/client_filter.h"
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "opencensus/stats/stats.h"
+#include "src/core/lib/surface/call.h"
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+#include "src/cpp/ext/filters/census/measures.h"
+
+namespace grpc {
+
+constexpr uint32_t CensusClientCallData::kMaxTraceContextLen;
+constexpr uint32_t CensusClientCallData::kMaxTagsLen;
+
+namespace {
+
+void FilterTrailingMetadata(grpc_metadata_batch* b, uint64_t* elapsed_time) {
+ if (b->idx.named.grpc_server_stats_bin != nullptr) {
+ ServerStatsDeserialize(
+ reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(
+ GRPC_MDVALUE(b->idx.named.grpc_server_stats_bin->md))),
+ GRPC_SLICE_LENGTH(GRPC_MDVALUE(b->idx.named.grpc_server_stats_bin->md)),
+ elapsed_time);
+ grpc_metadata_batch_remove(b, b->idx.named.grpc_server_stats_bin);
+ }
+}
+
+} // namespace
+
+void CensusClientCallData::OnDoneRecvTrailingMetadataCb(void* user_data,
+ grpc_error* error) {
+ grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
+ CensusClientCallData* calld =
+ reinterpret_cast<CensusClientCallData*>(elem->call_data);
+ GPR_ASSERT(calld != nullptr);
+ if (error == GRPC_ERROR_NONE) {
+ GPR_ASSERT(calld->recv_trailing_metadata_ != nullptr);
+ FilterTrailingMetadata(calld->recv_trailing_metadata_,
+ &calld->elapsed_time_);
+ }
+ GRPC_CLOSURE_RUN(calld->initial_on_done_recv_trailing_metadata_,
+ GRPC_ERROR_REF(error));
+}
+
+void CensusClientCallData::OnDoneRecvMessageCb(void* user_data,
+ grpc_error* error) {
+ grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
+ CensusClientCallData* calld =
+ reinterpret_cast<CensusClientCallData*>(elem->call_data);
+ CensusChannelData* channeld =
+ reinterpret_cast<CensusChannelData*>(elem->channel_data);
+ GPR_ASSERT(calld != nullptr);
+ GPR_ASSERT(channeld != nullptr);
+ // Stream messages are no longer valid after receiving trailing metadata.
+ if ((*calld->recv_message_) != nullptr) {
+ calld->recv_message_count_++;
+ }
+ GRPC_CLOSURE_RUN(calld->initial_on_done_recv_message_, GRPC_ERROR_REF(error));
+}
+
+void CensusClientCallData::StartTransportStreamOpBatch(
+ grpc_call_element* elem, TransportStreamOpBatch* op) {
+ if (op->send_initial_metadata() != nullptr) {
+ census_context* ctxt = op->get_census_context();
+ GenerateClientContext(
+ qualified_method_, &context_,
+ (ctxt == nullptr) ? nullptr : reinterpret_cast<CensusContext*>(ctxt));
+ size_t tracing_len = TraceContextSerialize(context_.Context(), tracing_buf_,
+ kMaxTraceContextLen);
+ if (tracing_len > 0) {
+ GRPC_LOG_IF_ERROR(
+ "census grpc_filter",
+ grpc_metadata_batch_add_tail(
+ op->send_initial_metadata()->batch(), &tracing_bin_,
+ grpc_mdelem_from_slices(
+ GRPC_MDSTR_GRPC_TRACE_BIN,
+ grpc_slice_from_copied_buffer(tracing_buf_, tracing_len))));
+ }
+ grpc_slice tags = grpc_empty_slice();
+ // TODO: Add in tagging serialization.
+ size_t encoded_tags_len = StatsContextSerialize(kMaxTagsLen, &tags);
+ if (encoded_tags_len > 0) {
+ GRPC_LOG_IF_ERROR(
+ "census grpc_filter",
+ grpc_metadata_batch_add_tail(
+ op->send_initial_metadata()->batch(), &stats_bin_,
+ grpc_mdelem_from_slices(GRPC_MDSTR_GRPC_TAGS_BIN, tags)));
+ }
+ }
+
+ if (op->send_message() != nullptr) {
+ ++sent_message_count_;
+ }
+ if (op->recv_message() != nullptr) {
+ recv_message_ = op->op()->payload->recv_message.recv_message;
+ initial_on_done_recv_message_ =
+ op->op()->payload->recv_message.recv_message_ready;
+ op->op()->payload->recv_message.recv_message_ready = &on_done_recv_message_;
+ }
+ if (op->recv_trailing_metadata() != nullptr) {
+ recv_trailing_metadata_ = op->recv_trailing_metadata()->batch();
+ initial_on_done_recv_trailing_metadata_ =
+ op->op()->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
+ op->op()->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
+ &on_done_recv_trailing_metadata_;
+ }
+ // Call next op.
+ grpc_call_next_op(elem, op->op());
+}
+
+grpc_error* CensusClientCallData::Init(grpc_call_element* elem,
+ const grpc_call_element_args* args) {
+ path_ = grpc_slice_ref_internal(args->path);
+ start_time_ = absl::Now();
+ method_ = GetMethod(&path_);
+ qualified_method_ = absl::StrCat("Sent.", method_);
+ GRPC_CLOSURE_INIT(&on_done_recv_message_, OnDoneRecvMessageCb, elem,
+ grpc_schedule_on_exec_ctx);
+ GRPC_CLOSURE_INIT(&on_done_recv_trailing_metadata_,
+ OnDoneRecvTrailingMetadataCb, elem,
+ grpc_schedule_on_exec_ctx);
+ return GRPC_ERROR_NONE;
+}
+
+void CensusClientCallData::Destroy(grpc_call_element* elem,
+ const grpc_call_final_info* final_info,
+ grpc_closure* then_call_closure) {
+ const uint64_t request_size = GetOutgoingDataSize(final_info);
+ const uint64_t response_size = GetIncomingDataSize(final_info);
+ double latency_ms = absl::ToDoubleMilliseconds(absl::Now() - start_time_);
+ ::opencensus::stats::Record(
+ {{RpcClientSentBytesPerRpc(), static_cast<double>(request_size)},
+ {RpcClientReceivedBytesPerRpc(), static_cast<double>(response_size)},
+ {RpcClientRoundtripLatency(), latency_ms},
+ {RpcClientServerLatency(),
+ ToDoubleMilliseconds(absl::Nanoseconds(elapsed_time_))},
+ {RpcClientSentMessagesPerRpc(), sent_message_count_},
+ {RpcClientReceivedMessagesPerRpc(), recv_message_count_}},
+ {{ClientMethodTagKey(), method_},
+ {ClientStatusTagKey(), StatusCodeToString(final_info->final_status)}});
+ grpc_slice_unref_internal(path_);
+ context_.EndSpan();
+}
+
+} // namespace grpc
diff --git a/src/cpp/ext/filters/census/client_filter.h b/src/cpp/ext/filters/census/client_filter.h
new file mode 100644
index 0000000000..851022873f
--- /dev/null
+++ b/src/cpp/ext/filters/census/client_filter.h
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_CLIENT_FILTER_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CLIENT_FILTER_H
+
+#include <grpc/support/port_platform.h>
+
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+#include "src/cpp/ext/filters/census/channel_filter.h"
+#include "src/cpp/ext/filters/census/context.h"
+
+namespace grpc {
+
+// A CallData class will be created for every grpc call within a channel. It is
+// used to store data and methods specific to that call. CensusClientCallData is
+// thread-compatible, however typically only 1 thread should be interacting with
+// a call at a time.
+class CensusClientCallData : public CallData {
+ public:
+ // Maximum size of trace context is sent on the wire.
+ static constexpr uint32_t kMaxTraceContextLen = 64;
+ // Maximum size of tags that are sent on the wire.
+ static constexpr uint32_t kMaxTagsLen = 2048;
+
+ CensusClientCallData()
+ : recv_trailing_metadata_(nullptr),
+ initial_on_done_recv_trailing_metadata_(nullptr),
+ initial_on_done_recv_message_(nullptr),
+ elapsed_time_(0),
+ recv_message_(nullptr),
+ recv_message_count_(0),
+ sent_message_count_(0) {
+ memset(&stats_bin_, 0, sizeof(grpc_linked_mdelem));
+ memset(&tracing_bin_, 0, sizeof(grpc_linked_mdelem));
+ memset(&path_, 0, sizeof(grpc_slice));
+ memset(&on_done_recv_trailing_metadata_, 0, sizeof(grpc_closure));
+ memset(&on_done_recv_message_, 0, sizeof(grpc_closure));
+ }
+
+ 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;
+
+ static void OnDoneRecvTrailingMetadataCb(void* user_data, grpc_error* error);
+
+ static void OnDoneSendInitialMetadataCb(void* user_data, grpc_error* error);
+
+ static void OnDoneRecvMessageCb(void* user_data, grpc_error* error);
+
+ private:
+ CensusContext context_;
+ // Metadata elements for tracing and census stats data.
+ grpc_linked_mdelem stats_bin_;
+ grpc_linked_mdelem tracing_bin_;
+ // Client method.
+ absl::string_view method_;
+ std::string qualified_method_;
+ grpc_slice path_;
+ // The recv trailing metadata callbacks.
+ grpc_metadata_batch* recv_trailing_metadata_;
+ grpc_closure* initial_on_done_recv_trailing_metadata_;
+ grpc_closure on_done_recv_trailing_metadata_;
+ // recv message
+ grpc_closure* initial_on_done_recv_message_;
+ grpc_closure on_done_recv_message_;
+ // Start time (for measuring latency).
+ absl::Time start_time_;
+ // Server elapsed time in nanoseconds.
+ uint64_t elapsed_time_;
+ // The received message--may be null.
+ grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message_;
+ // Number of messages in this RPC.
+ uint64_t recv_message_count_;
+ uint64_t sent_message_count_;
+ // Buffer needed for grpc_slice to reference when adding trace context
+ // metatdata to outgoing message.
+ char tracing_buf_[kMaxTraceContextLen];
+};
+
+} // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CLIENT_FILTER_H */
diff --git a/src/cpp/ext/filters/census/context.cc b/src/cpp/ext/filters/census/context.cc
new file mode 100644
index 0000000000..4b3250236d
--- /dev/null
+++ b/src/cpp/ext/filters/census/context.cc
@@ -0,0 +1,132 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/context.h"
+
+namespace grpc {
+
+using ::opencensus::trace::Span;
+using ::opencensus::trace::SpanContext;
+
+void GenerateServerContext(absl::string_view tracing, absl::string_view stats,
+ absl::string_view primary_role,
+ absl::string_view method, CensusContext* context) {
+ GrpcTraceContext trace_ctxt;
+ TraceContextEncoding::Decode(tracing, &trace_ctxt);
+ SpanContext parent_ctx = trace_ctxt.ToSpanContext();
+ new (context) CensusContext(method, parent_ctx);
+}
+
+void GenerateClientContext(absl::string_view method, CensusContext* ctxt,
+ CensusContext* parent_ctxt) {
+ if (parent_ctxt != nullptr) {
+ SpanContext span_ctxt = parent_ctxt->Context();
+ Span span = parent_ctxt->Span();
+ if (span_ctxt.IsValid()) {
+ new (ctxt) CensusContext(method, &span);
+ return;
+ }
+ }
+ new (ctxt) CensusContext(method);
+}
+
+size_t TraceContextSerialize(const ::opencensus::trace::SpanContext& context,
+ char* tracing_buf, size_t tracing_buf_size) {
+ GrpcTraceContext trace_ctxt(context);
+ return TraceContextEncoding::Encode(trace_ctxt, tracing_buf,
+ tracing_buf_size);
+}
+
+size_t StatsContextSerialize(size_t max_tags_len, grpc_slice* tags) {
+ // TODO: Add implementation. Waiting on stats tagging to be added.
+ return 0;
+}
+
+size_t ServerStatsSerialize(uint64_t server_elapsed_time, char* buf,
+ size_t buf_size) {
+ return RpcServerStatsEncoding::Encode(server_elapsed_time, buf, buf_size);
+}
+
+size_t ServerStatsDeserialize(const char* buf, size_t buf_size,
+ uint64_t* server_elapsed_time) {
+ return RpcServerStatsEncoding::Decode(absl::string_view(buf, buf_size),
+ server_elapsed_time);
+}
+
+uint64_t GetIncomingDataSize(const grpc_call_final_info* final_info) {
+ return final_info->stats.transport_stream_stats.incoming.data_bytes;
+}
+
+uint64_t GetOutgoingDataSize(const grpc_call_final_info* final_info) {
+ return final_info->stats.transport_stream_stats.outgoing.data_bytes;
+}
+
+SpanContext SpanContextFromCensusContext(const census_context* ctxt) {
+ return reinterpret_cast<const CensusContext*>(ctxt)->Context();
+}
+
+Span SpanFromCensusContext(const census_context* ctxt) {
+ return reinterpret_cast<const CensusContext*>(ctxt)->Span();
+}
+
+absl::string_view StatusCodeToString(grpc_status_code code) {
+ switch (code) {
+ case GRPC_STATUS_OK:
+ return "OK";
+ case GRPC_STATUS_CANCELLED:
+ return "CANCELLED";
+ case GRPC_STATUS_UNKNOWN:
+ return "UNKNOWN";
+ case GRPC_STATUS_INVALID_ARGUMENT:
+ return "INVALID_ARGUMENT";
+ case GRPC_STATUS_DEADLINE_EXCEEDED:
+ return "DEADLINE_EXCEEDED";
+ case GRPC_STATUS_NOT_FOUND:
+ return "NOT_FOUND";
+ case GRPC_STATUS_ALREADY_EXISTS:
+ return "ALREADY_EXISTS";
+ case GRPC_STATUS_PERMISSION_DENIED:
+ return "PERMISSION_DENIED";
+ case GRPC_STATUS_UNAUTHENTICATED:
+ return "UNAUTHENTICATED";
+ case GRPC_STATUS_RESOURCE_EXHAUSTED:
+ return "RESOURCE_EXHAUSTED";
+ case GRPC_STATUS_FAILED_PRECONDITION:
+ return "FAILED_PRECONDITION";
+ case GRPC_STATUS_ABORTED:
+ return "ABORTED";
+ case GRPC_STATUS_OUT_OF_RANGE:
+ return "OUT_OF_RANGE";
+ case GRPC_STATUS_UNIMPLEMENTED:
+ return "UNIMPLEMENTED";
+ case GRPC_STATUS_INTERNAL:
+ return "INTERNAL";
+ case GRPC_STATUS_UNAVAILABLE:
+ return "UNAVAILABLE";
+ case GRPC_STATUS_DATA_LOSS:
+ return "DATA_LOSS";
+ default:
+ // gRPC wants users of this enum to include a default branch so that
+ // adding values is not a breaking change.
+ return "UNKNOWN_STATUS";
+ }
+}
+
+} // namespace grpc
diff --git a/src/cpp/ext/filters/census/context.h b/src/cpp/ext/filters/census/context.h
new file mode 100644
index 0000000000..1643fdd11b
--- /dev/null
+++ b/src/cpp/ext/filters/census/context.h
@@ -0,0 +1,126 @@
+/*
+ *
+ * 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_CONTEXT_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CONTEXT_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/status.h>
+#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "opencensus/trace/span.h"
+#include "opencensus/trace/span_context.h"
+#include "opencensus/trace/trace_params.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/cpp/common/channel_filter.h"
+#include "src/cpp/ext/filters/census/rpc_encoding.h"
+
+// This is needed because grpc has hardcoded CensusContext with a
+// forward declaration of 'struct census_context;'
+struct census_context;
+
+namespace grpc {
+
+// Thread compatible.
+class CensusContext {
+ public:
+ CensusContext() : span_(::opencensus::trace::Span::BlankSpan()) {}
+
+ explicit CensusContext(absl::string_view name)
+ : span_(::opencensus::trace::Span::StartSpan(name)) {}
+
+ CensusContext(absl::string_view name, const ::opencensus::trace::Span* parent)
+ : span_(::opencensus::trace::Span::StartSpan(name, parent)) {}
+
+ CensusContext(absl::string_view name,
+ const ::opencensus::trace::SpanContext& parent_ctxt)
+ : span_(::opencensus::trace::Span::StartSpanWithRemoteParent(
+ name, parent_ctxt)) {}
+
+ ::opencensus::trace::SpanContext Context() const { return span_.context(); }
+ ::opencensus::trace::Span Span() const { return span_; }
+ void EndSpan() { span_.End(); }
+
+ private:
+ ::opencensus::trace::Span span_;
+};
+
+// Serializes the outgoing trace context. Field IDs are 1 byte followed by
+// field data. A 1 byte version ID is always encoded first.
+size_t TraceContextSerialize(const ::opencensus::trace::SpanContext& context,
+ char* tracing_buf, size_t tracing_buf_size);
+
+// Serializes the outgoing stats context. Field IDs are 1 byte followed by
+// field data. A 1 byte version ID is always encoded first. Tags are directly
+// serialized into the given grpc_slice.
+size_t StatsContextSerialize(size_t max_tags_len, grpc_slice* tags);
+
+// Serialize outgoing server stats. Returns the number of bytes serialized.
+size_t ServerStatsSerialize(uint64_t server_elapsed_time, char* buf,
+ size_t buf_size);
+
+// Deserialize incoming server stats. Returns the number of bytes deserialized.
+size_t ServerStatsDeserialize(const char* buf, size_t buf_size,
+ uint64_t* server_elapsed_time);
+
+// Deserialize the incoming SpanContext and generate a new server context based
+// on that. This new span will never be a root span. This should only be called
+// with a blank CensusContext as it overwrites it.
+void GenerateServerContext(absl::string_view tracing, absl::string_view stats,
+ absl::string_view primary_role,
+ absl::string_view method, CensusContext* context);
+
+// Creates a new client context that is by default a new root context.
+// If the current context is the default context then the newly created
+// span automatically becomes a root span. This should only be called with a
+// blank CensusContext as it overwrites it.
+void GenerateClientContext(absl::string_view method, CensusContext* ctxt,
+ CensusContext* parent_ctx);
+
+// Returns the incoming data size from the grpc call final info.
+uint64_t GetIncomingDataSize(const grpc_call_final_info* final_info);
+
+// Returns the outgoing data size from the grpc call final info.
+uint64_t GetOutgoingDataSize(const grpc_call_final_info* final_info);
+
+// These helper functions return the SpanContext and Span, respectively
+// associated with the census_context* stored by grpc. The user will need to
+// call this for manual propagation of tracing data.
+::opencensus::trace::SpanContext SpanContextFromCensusContext(
+ const census_context* ctxt);
+::opencensus::trace::Span SpanFromCensusContext(const census_context* ctxt);
+
+// Returns a string representation of the StatusCode enum.
+absl::string_view StatusCodeToString(grpc_status_code code);
+
+inline absl::string_view GetMethod(const grpc_slice* path) {
+ if (GRPC_SLICE_IS_EMPTY(*path)) {
+ return "";
+ }
+ // Check for leading '/' and trim it if present.
+ return absl::StripPrefix(absl::string_view(reinterpret_cast<const char*>(
+ GRPC_SLICE_START_PTR(*path)),
+ GRPC_SLICE_LENGTH(*path)),
+ "/");
+}
+
+} // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CONTEXT_H */
diff --git a/src/core/ext/census/grpc_context.cc b/src/cpp/ext/filters/census/grpc_context.cc
index 599a798dda..599a798dda 100644
--- a/src/core/ext/census/grpc_context.cc
+++ b/src/cpp/ext/filters/census/grpc_context.cc
diff --git a/src/cpp/ext/filters/census/grpc_plugin.cc b/src/cpp/ext/filters/census/grpc_plugin.cc
new file mode 100644
index 0000000000..f978ed3bf5
--- /dev/null
+++ b/src/cpp/ext/filters/census/grpc_plugin.cc
@@ -0,0 +1,130 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+
+#include <grpcpp/server_context.h>
+
+#include "opencensus/trace/span.h"
+#include "src/cpp/ext/filters/census/channel_filter.h"
+#include "src/cpp/ext/filters/census/client_filter.h"
+#include "src/cpp/ext/filters/census/measures.h"
+#include "src/cpp/ext/filters/census/server_filter.h"
+
+namespace grpc {
+
+void RegisterOpenCensusPlugin() {
+ RegisterChannelFilter<CensusChannelData, CensusClientCallData>(
+ "opencensus_client", GRPC_CLIENT_CHANNEL, INT_MAX /* priority */,
+ nullptr /* condition function */);
+ RegisterChannelFilter<CensusChannelData, CensusServerCallData>(
+ "opencensus_server", GRPC_SERVER_CHANNEL, INT_MAX /* priority */,
+ nullptr /* condition function */);
+
+ // Access measures to ensure they are initialized. Otherwise, creating a view
+ // before the first RPC would cause an error.
+ RpcClientSentBytesPerRpc();
+ RpcClientReceivedBytesPerRpc();
+ RpcClientRoundtripLatency();
+ RpcClientServerLatency();
+ RpcClientSentMessagesPerRpc();
+ RpcClientReceivedMessagesPerRpc();
+
+ RpcServerSentBytesPerRpc();
+ RpcServerReceivedBytesPerRpc();
+ RpcServerServerLatency();
+ RpcServerSentMessagesPerRpc();
+ RpcServerReceivedMessagesPerRpc();
+}
+
+::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context) {
+ return reinterpret_cast<const CensusContext*>(context->census_context())
+ ->Span();
+}
+
+// These measure definitions should be kept in sync across opencensus
+// implementations--see
+// https://github.com/census-instrumentation/opencensus-java/blob/master/contrib/grpc_metrics/src/main/java/io/opencensus/contrib/grpc/metrics/RpcMeasureConstants.java.
+::opencensus::stats::TagKey ClientMethodTagKey() {
+ static const auto method_tag_key =
+ ::opencensus::stats::TagKey::Register("grpc_client_method");
+ return method_tag_key;
+}
+
+::opencensus::stats::TagKey ClientStatusTagKey() {
+ static const auto status_tag_key =
+ ::opencensus::stats::TagKey::Register("grpc_client_status");
+ return status_tag_key;
+}
+
+::opencensus::stats::TagKey ServerMethodTagKey() {
+ static const auto method_tag_key =
+ ::opencensus::stats::TagKey::Register("grpc_server_method");
+ return method_tag_key;
+}
+
+::opencensus::stats::TagKey ServerStatusTagKey() {
+ static const auto status_tag_key =
+ ::opencensus::stats::TagKey::Register("grpc_server_status");
+ return status_tag_key;
+}
+
+// Client
+ABSL_CONST_INIT const absl::string_view
+ kRpcClientSentMessagesPerRpcMeasureName =
+ "grpc.io/client/sent_messages_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view kRpcClientSentBytesPerRpcMeasureName =
+ "grpc.io/client/sent_bytes_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view
+ kRpcClientReceivedMessagesPerRpcMeasureName =
+ "grpc.io/client/received_messages_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view
+ kRpcClientReceivedBytesPerRpcMeasureName =
+ "grpc.io/client/received_bytes_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view kRpcClientRoundtripLatencyMeasureName =
+ "grpc.io/client/roundtrip_latency";
+
+ABSL_CONST_INIT const absl::string_view kRpcClientServerLatencyMeasureName =
+ "grpc.io/client/server_latency";
+
+// Server
+ABSL_CONST_INIT const absl::string_view
+ kRpcServerSentMessagesPerRpcMeasureName =
+ "grpc.io/server/sent_messages_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view kRpcServerSentBytesPerRpcMeasureName =
+ "grpc.io/server/sent_bytes_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view
+ kRpcServerReceivedMessagesPerRpcMeasureName =
+ "grpc.io/server/received_messages_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view
+ kRpcServerReceivedBytesPerRpcMeasureName =
+ "grpc.io/server/received_bytes_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view kRpcServerServerLatencyMeasureName =
+ "grpc.io/server/server_latency";
+
+} // namespace grpc
diff --git a/src/cpp/ext/filters/census/grpc_plugin.h b/src/cpp/ext/filters/census/grpc_plugin.h
new file mode 100644
index 0000000000..7ff2e7a8b8
--- /dev/null
+++ b/src/cpp/ext/filters/census/grpc_plugin.h
@@ -0,0 +1,111 @@
+/*
+ *
+ * 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_GRPC_PLUGIN_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_GRPC_PLUGIN_H
+
+#include <grpc/support/port_platform.h>
+
+#include "absl/strings/string_view.h"
+#include "include/grpcpp/opencensus.h"
+#include "opencensus/stats/stats.h"
+#include "opencensus/trace/span.h"
+
+namespace grpc {
+
+class ServerContext;
+
+// Returns the tracing Span for the current RPC.
+::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context);
+
+// The tag keys set when recording RPC stats.
+::opencensus::stats::TagKey ClientMethodTagKey();
+::opencensus::stats::TagKey ClientStatusTagKey();
+::opencensus::stats::TagKey ServerMethodTagKey();
+::opencensus::stats::TagKey ServerStatusTagKey();
+
+// Names of measures used by the plugin--users can create views on these
+// measures but should not record data for them.
+extern const absl::string_view kRpcClientSentMessagesPerRpcMeasureName;
+extern const absl::string_view kRpcClientSentBytesPerRpcMeasureName;
+extern const absl::string_view kRpcClientReceivedMessagesPerRpcMeasureName;
+extern const absl::string_view kRpcClientReceivedBytesPerRpcMeasureName;
+extern const absl::string_view kRpcClientRoundtripLatencyMeasureName;
+extern const absl::string_view kRpcClientServerLatencyMeasureName;
+
+extern const absl::string_view kRpcServerSentMessagesPerRpcMeasureName;
+extern const absl::string_view kRpcServerSentBytesPerRpcMeasureName;
+extern const absl::string_view kRpcServerReceivedMessagesPerRpcMeasureName;
+extern const absl::string_view kRpcServerReceivedBytesPerRpcMeasureName;
+extern const absl::string_view kRpcServerServerLatencyMeasureName;
+
+// Canonical gRPC view definitions.
+const ::opencensus::stats::ViewDescriptor& ClientSentMessagesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor& ClientSentBytesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor&
+ClientReceivedMessagesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor&
+ClientReceivedBytesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor& ClientRoundtripLatencyCumulative();
+const ::opencensus::stats::ViewDescriptor& ClientServerLatencyCumulative();
+const ::opencensus::stats::ViewDescriptor& ClientCompletedRpcsCumulative();
+
+const ::opencensus::stats::ViewDescriptor& ServerSentBytesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor&
+ServerReceivedBytesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor& ServerServerLatencyCumulative();
+const ::opencensus::stats::ViewDescriptor& ServerStartedCountCumulative();
+const ::opencensus::stats::ViewDescriptor& ServerCompletedRpcsCumulative();
+const ::opencensus::stats::ViewDescriptor& ServerSentMessagesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor&
+ServerReceivedMessagesPerRpcCumulative();
+
+const ::opencensus::stats::ViewDescriptor& ClientSentMessagesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ClientSentBytesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ClientReceivedMessagesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ClientReceivedBytesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ClientRoundtripLatencyMinute();
+const ::opencensus::stats::ViewDescriptor& ClientServerLatencyMinute();
+const ::opencensus::stats::ViewDescriptor& ClientCompletedRpcsMinute();
+
+const ::opencensus::stats::ViewDescriptor& ServerSentMessagesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ServerSentBytesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ServerReceivedMessagesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ServerReceivedBytesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ServerServerLatencyMinute();
+const ::opencensus::stats::ViewDescriptor& ServerCompletedRpcsMinute();
+
+const ::opencensus::stats::ViewDescriptor& ClientSentMessagesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ClientSentBytesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ClientReceivedMessagesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ClientReceivedBytesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ClientRoundtripLatencyHour();
+const ::opencensus::stats::ViewDescriptor& ClientServerLatencyHour();
+const ::opencensus::stats::ViewDescriptor& ClientCompletedRpcsHour();
+
+const ::opencensus::stats::ViewDescriptor& ServerSentMessagesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ServerSentBytesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ServerReceivedMessagesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ServerReceivedBytesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ServerServerLatencyHour();
+const ::opencensus::stats::ViewDescriptor& ServerStartedCountHour();
+const ::opencensus::stats::ViewDescriptor& ServerCompletedRpcsHour();
+
+} // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_GRPC_PLUGIN_H */
diff --git a/src/cpp/ext/filters/census/measures.cc b/src/cpp/ext/filters/census/measures.cc
new file mode 100644
index 0000000000..b522fae09a
--- /dev/null
+++ b/src/cpp/ext/filters/census/measures.cc
@@ -0,0 +1,129 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/measures.h"
+
+#include "opencensus/stats/stats.h"
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+
+namespace grpc {
+
+using ::opencensus::stats::MeasureDouble;
+using ::opencensus::stats::MeasureInt64;
+
+// These measure definitions should be kept in sync across opencensus
+// implementations--see
+// https://github.com/census-instrumentation/opencensus-java/blob/master/contrib/grpc_metrics/src/main/java/io/opencensus/contrib/grpc/metrics/RpcMeasureConstants.java.
+
+namespace {
+
+// Unit constants
+constexpr char kUnitBytes[] = "By";
+constexpr char kUnitMilliseconds[] = "ms";
+constexpr char kCount[] = "1";
+
+} // namespace
+
+// Client
+MeasureDouble RpcClientSentBytesPerRpc() {
+ static const auto measure = MeasureDouble::Register(
+ kRpcClientSentBytesPerRpcMeasureName,
+ "Total bytes sent across all request messages per RPC", kUnitBytes);
+ return measure;
+}
+
+MeasureDouble RpcClientReceivedBytesPerRpc() {
+ static const auto measure = MeasureDouble::Register(
+ kRpcClientReceivedBytesPerRpcMeasureName,
+ "Total bytes received across all response messages per RPC", kUnitBytes);
+ return measure;
+}
+
+MeasureDouble RpcClientRoundtripLatency() {
+ static const auto measure = MeasureDouble::Register(
+ kRpcClientRoundtripLatencyMeasureName,
+ "Time between first byte of request sent to last byte of response "
+ "received, or terminal error",
+ kUnitMilliseconds);
+ return measure;
+}
+
+MeasureDouble RpcClientServerLatency() {
+ static const auto measure = MeasureDouble::Register(
+ kRpcClientServerLatencyMeasureName,
+ "Time between first byte of request received to last byte of response "
+ "sent, or terminal error (propagated from the server)",
+ kUnitMilliseconds);
+ return measure;
+}
+
+MeasureInt64 RpcClientSentMessagesPerRpc() {
+ static const auto measure =
+ MeasureInt64::Register(kRpcClientSentMessagesPerRpcMeasureName,
+ "Number of messages sent per RPC", kCount);
+ return measure;
+}
+
+MeasureInt64 RpcClientReceivedMessagesPerRpc() {
+ static const auto measure =
+ MeasureInt64::Register(kRpcClientReceivedMessagesPerRpcMeasureName,
+ "Number of messages received per RPC", kCount);
+ return measure;
+}
+
+// Server
+MeasureDouble RpcServerSentBytesPerRpc() {
+ static const auto measure = MeasureDouble::Register(
+ kRpcServerSentBytesPerRpcMeasureName,
+ "Total bytes sent across all messages per RPC", kUnitBytes);
+ return measure;
+}
+
+MeasureDouble RpcServerReceivedBytesPerRpc() {
+ static const auto measure = MeasureDouble::Register(
+ kRpcServerReceivedBytesPerRpcMeasureName,
+ "Total bytes received across all messages per RPC", kUnitBytes);
+ return measure;
+}
+
+MeasureDouble RpcServerServerLatency() {
+ static const auto measure = MeasureDouble::Register(
+ kRpcServerServerLatencyMeasureName,
+ "Time between first byte of request received to last byte of response "
+ "sent, or terminal error",
+ kUnitMilliseconds);
+ return measure;
+}
+
+MeasureInt64 RpcServerSentMessagesPerRpc() {
+ static const auto measure =
+ MeasureInt64::Register(kRpcServerSentMessagesPerRpcMeasureName,
+ "Number of messages sent per RPC", kCount);
+ return measure;
+}
+
+MeasureInt64 RpcServerReceivedMessagesPerRpc() {
+ static const auto measure =
+ MeasureInt64::Register(kRpcServerReceivedMessagesPerRpcMeasureName,
+ "Number of messages received per RPC", kCount);
+ return measure;
+}
+
+} // namespace grpc
diff --git a/src/cpp/ext/filters/census/measures.h b/src/cpp/ext/filters/census/measures.h
new file mode 100644
index 0000000000..8f8e72ace2
--- /dev/null
+++ b/src/cpp/ext/filters/census/measures.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_MEASURES_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_MEASURES_H
+
+#include <grpc/support/port_platform.h>
+
+#include "opencensus/stats/stats.h"
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+
+namespace grpc {
+
+::opencensus::stats::MeasureInt64 RpcClientSentMessagesPerRpc();
+::opencensus::stats::MeasureDouble RpcClientSentBytesPerRpc();
+::opencensus::stats::MeasureInt64 RpcClientReceivedMessagesPerRpc();
+::opencensus::stats::MeasureDouble RpcClientReceivedBytesPerRpc();
+::opencensus::stats::MeasureDouble RpcClientRoundtripLatency();
+::opencensus::stats::MeasureDouble RpcClientServerLatency();
+::opencensus::stats::MeasureInt64 RpcClientCompletedRpcs();
+
+::opencensus::stats::MeasureInt64 RpcServerSentMessagesPerRpc();
+::opencensus::stats::MeasureDouble RpcServerSentBytesPerRpc();
+::opencensus::stats::MeasureInt64 RpcServerReceivedMessagesPerRpc();
+::opencensus::stats::MeasureDouble RpcServerReceivedBytesPerRpc();
+::opencensus::stats::MeasureDouble RpcServerServerLatency();
+::opencensus::stats::MeasureInt64 RpcServerCompletedRpcs();
+
+} // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_MEASURES_H */
diff --git a/src/cpp/ext/filters/census/rpc_encoding.cc b/src/cpp/ext/filters/census/rpc_encoding.cc
new file mode 100644
index 0000000000..45a66d9dc8
--- /dev/null
+++ b/src/cpp/ext/filters/census/rpc_encoding.cc
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/rpc_encoding.h"
+
+namespace grpc {
+
+constexpr size_t TraceContextEncoding::kGrpcTraceContextSize;
+constexpr size_t TraceContextEncoding::kEncodeDecodeFailure;
+constexpr size_t TraceContextEncoding::kVersionIdSize;
+constexpr size_t TraceContextEncoding::kFieldIdSize;
+constexpr size_t TraceContextEncoding::kVersionIdOffset;
+constexpr size_t TraceContextEncoding::kVersionId;
+
+constexpr size_t RpcServerStatsEncoding::kRpcServerStatsSize;
+constexpr size_t RpcServerStatsEncoding::kEncodeDecodeFailure;
+constexpr size_t RpcServerStatsEncoding::kVersionIdSize;
+constexpr size_t RpcServerStatsEncoding::kFieldIdSize;
+constexpr size_t RpcServerStatsEncoding::kVersionIdOffset;
+constexpr size_t RpcServerStatsEncoding::kVersionId;
+
+} // namespace grpc
diff --git a/src/cpp/ext/filters/census/rpc_encoding.h b/src/cpp/ext/filters/census/rpc_encoding.h
new file mode 100644
index 0000000000..ffffa60c46
--- /dev/null
+++ b/src/cpp/ext/filters/census/rpc_encoding.h
@@ -0,0 +1,284 @@
+/*
+ *
+ * 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H
+
+#include <grpc/support/port_platform.h>
+
+#include <string.h>
+
+#include "absl/base/internal/endian.h"
+#include "absl/strings/string_view.h"
+#include "opencensus/trace/span_context.h"
+#include "opencensus/trace/span_id.h"
+#include "opencensus/trace/trace_id.h"
+
+namespace grpc {
+
+// TODO: Rename to GrpcTraceContextV0.
+struct GrpcTraceContext {
+ GrpcTraceContext() {}
+
+ explicit GrpcTraceContext(const ::opencensus::trace::SpanContext& ctx) {
+ ctx.trace_id().CopyTo(trace_id);
+ ctx.span_id().CopyTo(span_id);
+ ctx.trace_options().CopyTo(trace_options);
+ }
+
+ ::opencensus::trace::SpanContext ToSpanContext() const {
+ return ::opencensus::trace::SpanContext(
+ ::opencensus::trace::TraceId(trace_id),
+ ::opencensus::trace::SpanId(span_id),
+ ::opencensus::trace::TraceOptions(trace_options));
+ }
+
+ // TODO: For performance:
+ // uint8_t version;
+ // uint8_t trace_id_field_id;
+ uint8_t trace_id[::opencensus::trace::TraceId::kSize];
+ // uint8_t span_id_field_id;
+ uint8_t span_id[::opencensus::trace::SpanId::kSize];
+ // uint8_t trace_options_field_id;
+ uint8_t trace_options[::opencensus::trace::TraceOptions::kSize];
+};
+
+// TraceContextEncoding encapsulates the logic for encoding and decoding of
+// trace contexts.
+class TraceContextEncoding {
+ public:
+ // Size of encoded GrpcTraceContext. (16 + 8 + 1 + 4)
+ static constexpr size_t kGrpcTraceContextSize = 29;
+ // Error value.
+ static constexpr size_t kEncodeDecodeFailure = 0;
+
+ // Deserializes a GrpcTraceContext from the incoming buffer. Returns the
+ // number of bytes deserialized from the buffer. If the incoming buffer is
+ // empty or the encoding version is not supported it will return 0 bytes,
+ // currently only version 0 is supported. If an unknown field ID is
+ // encountered it will return immediately without parsing the rest of the
+ // buffer. Inlined for performance reasons.
+ static size_t Decode(absl::string_view buf, GrpcTraceContext* tc) {
+ if (buf.empty()) {
+ return kEncodeDecodeFailure;
+ }
+ uint8_t version = buf[kVersionIdOffset];
+ // TODO: Support other versions later. Only support version 0 for
+ // now.
+ if (version != kVersionId) {
+ return kEncodeDecodeFailure;
+ }
+
+ size_t pos = kVersionIdSize;
+ while (pos < buf.size()) {
+ size_t bytes_read =
+ ParseField(absl::string_view(&buf[pos], buf.size() - pos), tc);
+ if (bytes_read == 0) {
+ break;
+ } else {
+ pos += bytes_read;
+ }
+ }
+ return pos;
+ }
+
+ // Serializes a GrpcTraceContext into the provided buffer. Returns the number
+ // of bytes serialized into the buffer. If the buffer is not of sufficient
+ // size (it must be at least kGrpcTraceContextSize bytes) it will drop
+ // everything and return 0 bytes serialized. Inlined for performance reasons.
+ static size_t Encode(const GrpcTraceContext& tc, char* buf, size_t buf_size) {
+ if (buf_size < kGrpcTraceContextSize) {
+ return kEncodeDecodeFailure;
+ }
+ buf[kVersionIdOffset] = kVersionId;
+ buf[kTraceIdOffset] = kTraceIdField;
+ memcpy(&buf[kTraceIdOffset + 1], tc.trace_id,
+ opencensus::trace::TraceId::kSize);
+ buf[kSpanIdOffset] = kSpanIdField;
+ memcpy(&buf[kSpanIdOffset + 1], tc.span_id,
+ opencensus::trace::SpanId::kSize);
+ buf[kTraceOptionsOffset] = kTraceOptionsField;
+ memcpy(&buf[kTraceOptionsOffset + 1], tc.trace_options,
+ opencensus::trace::TraceOptions::kSize);
+ return kGrpcTraceContextSize;
+ }
+
+ private:
+ // Parses the next field from the incoming buffer and stores the parsed value
+ // in a GrpcTraceContext struct. If it does not recognize the field ID it
+ // will return 0, otherwise it returns the number of bytes read.
+ static size_t ParseField(absl::string_view buf, GrpcTraceContext* tc) {
+ // TODO: Add support for multi-byte field IDs.
+ if (buf.empty()) {
+ return 0;
+ }
+ // Field ID is always the first byte in a field.
+ uint32_t field_id = buf[0];
+ size_t bytes_read = kFieldIdSize;
+ switch (field_id) {
+ case kTraceIdField:
+ bytes_read += kTraceIdSize;
+ if (bytes_read > buf.size()) {
+ return 0;
+ }
+ memcpy(tc->trace_id, &buf[kFieldIdSize],
+ opencensus::trace::TraceId::kSize);
+ break;
+ case kSpanIdField:
+ bytes_read += kSpanIdSize;
+ if (bytes_read > buf.size()) {
+ return 0;
+ }
+ memcpy(tc->span_id, &buf[kFieldIdSize],
+ opencensus::trace::SpanId::kSize);
+ break;
+ case kTraceOptionsField:
+ bytes_read += kTraceOptionsSize;
+ if (bytes_read > buf.size()) {
+ return 0;
+ }
+ memcpy(tc->trace_options, &buf[kFieldIdSize],
+ opencensus::trace::TraceOptions::kSize);
+ break;
+ default: // Invalid field ID
+ return 0;
+ }
+
+ return bytes_read;
+ }
+
+ // Size of Version ID.
+ static constexpr size_t kVersionIdSize = 1;
+ // Size of Field ID.
+ static constexpr size_t kFieldIdSize = 1;
+
+ // Offset and value for currently supported version ID.
+ static constexpr size_t kVersionIdOffset = 0;
+ static constexpr size_t kVersionId = 0;
+
+ // Fixed Field ID values:
+ enum FieldIdValue {
+ kTraceIdField = 0,
+ kSpanIdField = 1,
+ kTraceOptionsField = 2,
+ };
+
+ // Field data sizes in bytes
+ enum FieldSize {
+ kTraceIdSize = 16,
+ kSpanIdSize = 8,
+ kTraceOptionsSize = 1,
+ };
+
+ // Fixed size offsets for field ID start positions during encoding. Field
+ // data immediately follows.
+ enum FieldIdOffset {
+ kTraceIdOffset = kVersionIdSize,
+ kSpanIdOffset = kTraceIdOffset + kFieldIdSize + kTraceIdSize,
+ kTraceOptionsOffset = kSpanIdOffset + kFieldIdSize + kSpanIdSize,
+ };
+
+ TraceContextEncoding() = delete;
+ TraceContextEncoding(const TraceContextEncoding&) = delete;
+ TraceContextEncoding(TraceContextEncoding&&) = delete;
+ TraceContextEncoding operator=(const TraceContextEncoding&) = delete;
+ TraceContextEncoding operator=(TraceContextEncoding&&) = delete;
+};
+
+// TODO: This may not be needed. Check to see if opencensus requires
+// a trailing server response.
+// RpcServerStatsEncoding encapsulates the logic for encoding and decoding of
+// rpc server stats messages. Rpc server stats consists of a uint64_t time
+// value (server latency in nanoseconds).
+class RpcServerStatsEncoding {
+ public:
+ // Size of encoded RPC server stats.
+ static constexpr size_t kRpcServerStatsSize = 10;
+ // Error value.
+ static constexpr size_t kEncodeDecodeFailure = 0;
+
+ // Deserializes rpc server stats from the incoming 'buf' into *time. Returns
+ // number of bytes decoded. If the buffer is of insufficient size (it must be
+ // at least kRpcServerStatsSize bytes) or the encoding version or field ID are
+ // unrecognized, *time will be set to 0 and it will return
+ // kEncodeDecodeFailure. Inlined for performance reasons.
+ static size_t Decode(absl::string_view buf, uint64_t* time) {
+ if (buf.size() < kRpcServerStatsSize) {
+ *time = 0;
+ return kEncodeDecodeFailure;
+ }
+
+ uint8_t version = buf[kVersionIdOffset];
+ uint32_t fieldID = buf[kServerElapsedTimeOffset];
+ if (version != kVersionId || fieldID != kServerElapsedTimeField) {
+ *time = 0;
+ return kEncodeDecodeFailure;
+ }
+ *time = absl::little_endian::Load64(
+ &buf[kServerElapsedTimeOffset + kFieldIdSize]);
+ return kRpcServerStatsSize;
+ }
+
+ // Serializes rpc server stats into the provided buffer. It returns the
+ // number of bytes written to the buffer. If the buffer is smaller than
+ // kRpcServerStatsSize bytes it will return kEncodeDecodeFailure. Inlined for
+ // performance reasons.
+ static size_t Encode(uint64_t time, char* buf, size_t buf_size) {
+ if (buf_size < kRpcServerStatsSize) {
+ return kEncodeDecodeFailure;
+ }
+
+ buf[kVersionIdOffset] = kVersionId;
+ buf[kServerElapsedTimeOffset] = kServerElapsedTimeField;
+ absl::little_endian::Store64(&buf[kServerElapsedTimeOffset + kFieldIdSize],
+ time);
+ return kRpcServerStatsSize;
+ }
+
+ private:
+ // Size of Version ID.
+ static constexpr size_t kVersionIdSize = 1;
+ // Size of Field ID.
+ static constexpr size_t kFieldIdSize = 1;
+
+ // Offset and value for currently supported version ID.
+ static constexpr size_t kVersionIdOffset = 0;
+ static constexpr size_t kVersionId = 0;
+
+ enum FieldIdValue {
+ kServerElapsedTimeField = 0,
+ };
+
+ enum FieldSize {
+ kServerElapsedTimeSize = 8,
+ };
+
+ enum FieldIdOffset {
+ kServerElapsedTimeOffset = kVersionIdSize,
+ };
+
+ RpcServerStatsEncoding() = delete;
+ RpcServerStatsEncoding(const RpcServerStatsEncoding&) = delete;
+ RpcServerStatsEncoding(RpcServerStatsEncoding&&) = delete;
+ RpcServerStatsEncoding operator=(const RpcServerStatsEncoding&) = delete;
+ RpcServerStatsEncoding operator=(RpcServerStatsEncoding&&) = delete;
+};
+
+} // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H */
diff --git a/src/cpp/ext/filters/census/server_filter.cc b/src/cpp/ext/filters/census/server_filter.cc
new file mode 100644
index 0000000000..c7c62eefe5
--- /dev/null
+++ b/src/cpp/ext/filters/census/server_filter.cc
@@ -0,0 +1,198 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/server_filter.h"
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+#include "opencensus/stats/stats.h"
+#include "src/core/lib/surface/call.h"
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+#include "src/cpp/ext/filters/census/measures.h"
+
+namespace grpc {
+
+constexpr uint32_t CensusServerCallData::kMaxServerStatsLen;
+
+namespace {
+
+// server metadata elements
+struct ServerMetadataElements {
+ grpc_slice path;
+ grpc_slice tracing_slice;
+ grpc_slice census_proto;
+};
+
+void FilterInitialMetadata(grpc_metadata_batch* b,
+ ServerMetadataElements* sml) {
+ if (b->idx.named.path != nullptr) {
+ sml->path = grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.path->md));
+ }
+ if (b->idx.named.grpc_trace_bin != nullptr) {
+ sml->tracing_slice =
+ grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_trace_bin->md));
+ grpc_metadata_batch_remove(b, b->idx.named.grpc_trace_bin);
+ }
+ if (b->idx.named.grpc_tags_bin != nullptr) {
+ sml->census_proto =
+ grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_tags_bin->md));
+ grpc_metadata_batch_remove(b, b->idx.named.grpc_tags_bin);
+ }
+}
+
+} // namespace
+
+void CensusServerCallData::OnDoneRecvMessageCb(void* user_data,
+ grpc_error* error) {
+ grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
+ CensusServerCallData* calld =
+ reinterpret_cast<CensusServerCallData*>(elem->call_data);
+ CensusChannelData* channeld =
+ reinterpret_cast<CensusChannelData*>(elem->channel_data);
+ GPR_ASSERT(calld != nullptr);
+ GPR_ASSERT(channeld != nullptr);
+ // Stream messages are no longer valid after receiving trailing metadata.
+ if ((*calld->recv_message_) != nullptr) {
+ ++calld->recv_message_count_;
+ }
+ GRPC_CLOSURE_RUN(calld->initial_on_done_recv_message_, GRPC_ERROR_REF(error));
+}
+
+void CensusServerCallData::OnDoneRecvInitialMetadataCb(void* user_data,
+ grpc_error* error) {
+ grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
+ CensusServerCallData* calld =
+ reinterpret_cast<CensusServerCallData*>(elem->call_data);
+ GPR_ASSERT(calld != nullptr);
+ if (error == GRPC_ERROR_NONE) {
+ grpc_metadata_batch* initial_metadata = calld->recv_initial_metadata_;
+ GPR_ASSERT(initial_metadata != nullptr);
+ ServerMetadataElements sml;
+ sml.path = grpc_empty_slice();
+ sml.tracing_slice = grpc_empty_slice();
+ sml.census_proto = grpc_empty_slice();
+ FilterInitialMetadata(initial_metadata, &sml);
+ calld->path_ = grpc_slice_ref_internal(sml.path);
+ calld->method_ = GetMethod(&calld->path_);
+ calld->qualified_method_ = StrCat("Recv.", calld->method_);
+ const char* tracing_str =
+ GRPC_SLICE_IS_EMPTY(sml.tracing_slice)
+ ? ""
+ : reinterpret_cast<const char*>(
+ GRPC_SLICE_START_PTR(sml.tracing_slice));
+ size_t tracing_str_len = GRPC_SLICE_IS_EMPTY(sml.tracing_slice)
+ ? 0
+ : GRPC_SLICE_LENGTH(sml.tracing_slice);
+ const char* census_str = GRPC_SLICE_IS_EMPTY(sml.census_proto)
+ ? ""
+ : reinterpret_cast<const char*>(
+ GRPC_SLICE_START_PTR(sml.census_proto));
+ size_t census_str_len = GRPC_SLICE_IS_EMPTY(sml.census_proto)
+ ? 0
+ : GRPC_SLICE_LENGTH(sml.census_proto);
+
+ GenerateServerContext(absl::string_view(tracing_str, tracing_str_len),
+ absl::string_view(census_str, census_str_len),
+ /*primary_role*/ "", calld->qualified_method_,
+ &calld->context_);
+
+ grpc_slice_unref_internal(sml.tracing_slice);
+ grpc_slice_unref_internal(sml.census_proto);
+ grpc_slice_unref_internal(sml.path);
+ grpc_census_call_set_context(
+ calld->gc_, reinterpret_cast<census_context*>(&calld->context_));
+ }
+ GRPC_CLOSURE_RUN(calld->initial_on_done_recv_initial_metadata_,
+ GRPC_ERROR_REF(error));
+}
+
+void CensusServerCallData::StartTransportStreamOpBatch(
+ grpc_call_element* elem, TransportStreamOpBatch* op) {
+ if (op->recv_initial_metadata() != nullptr) {
+ // substitute our callback for the op callback
+ recv_initial_metadata_ = op->recv_initial_metadata()->batch();
+ initial_on_done_recv_initial_metadata_ = op->recv_initial_metadata_ready();
+ op->set_recv_initial_metadata_ready(&on_done_recv_initial_metadata_);
+ }
+ if (op->send_message() != nullptr) {
+ ++sent_message_count_;
+ }
+ if (op->recv_message() != nullptr) {
+ recv_message_ = op->op()->payload->recv_message.recv_message;
+ initial_on_done_recv_message_ =
+ op->op()->payload->recv_message.recv_message_ready;
+ op->op()->payload->recv_message.recv_message_ready = &on_done_recv_message_;
+ }
+ // We need to record the time when the trailing metadata was sent to mark the
+ // completeness of the request.
+ if (op->send_trailing_metadata() != nullptr) {
+ elapsed_time_ = absl::Now() - start_time_;
+ size_t len = ServerStatsSerialize(absl::ToInt64Nanoseconds(elapsed_time_),
+ stats_buf_, kMaxServerStatsLen);
+ if (len > 0) {
+ GRPC_LOG_IF_ERROR(
+ "census grpc_filter",
+ grpc_metadata_batch_add_tail(
+ op->send_trailing_metadata()->batch(), &census_bin_,
+ grpc_mdelem_from_slices(
+ GRPC_MDSTR_GRPC_SERVER_STATS_BIN,
+ grpc_slice_from_copied_buffer(stats_buf_, len))));
+ }
+ }
+ // Call next op.
+ grpc_call_next_op(elem, op->op());
+}
+
+grpc_error* CensusServerCallData::Init(grpc_call_element* elem,
+ const grpc_call_element_args* args) {
+ start_time_ = absl::Now();
+ gc_ =
+ grpc_call_from_top_element(grpc_call_stack_element(args->call_stack, 0));
+ GRPC_CLOSURE_INIT(&on_done_recv_initial_metadata_,
+ OnDoneRecvInitialMetadataCb, elem,
+ grpc_schedule_on_exec_ctx);
+ GRPC_CLOSURE_INIT(&on_done_recv_message_, OnDoneRecvMessageCb, elem,
+ grpc_schedule_on_exec_ctx);
+ auth_context_ = grpc_call_auth_context(gc_);
+ return GRPC_ERROR_NONE;
+}
+
+void CensusServerCallData::Destroy(grpc_call_element* elem,
+ const grpc_call_final_info* final_info,
+ grpc_closure* then_call_closure) {
+ const uint64_t request_size = GetOutgoingDataSize(final_info);
+ const uint64_t response_size = GetIncomingDataSize(final_info);
+ double elapsed_time_ms = absl::ToDoubleMilliseconds(elapsed_time_);
+ grpc_auth_context_release(auth_context_);
+ ::opencensus::stats::Record(
+ {{RpcServerSentBytesPerRpc(), static_cast<double>(response_size)},
+ {RpcServerReceivedBytesPerRpc(), static_cast<double>(request_size)},
+ {RpcServerServerLatency(), elapsed_time_ms},
+ {RpcServerSentMessagesPerRpc(), sent_message_count_},
+ {RpcServerReceivedMessagesPerRpc(), recv_message_count_}},
+ {{ServerMethodTagKey(), method_},
+ {ServerStatusTagKey(), StatusCodeToString(final_info->final_status)}});
+ grpc_slice_unref_internal(path_);
+ context_.EndSpan();
+}
+
+} // namespace grpc
diff --git a/src/cpp/ext/filters/census/server_filter.h b/src/cpp/ext/filters/census/server_filter.h
new file mode 100644
index 0000000000..e393ed3283
--- /dev/null
+++ b/src/cpp/ext/filters/census/server_filter.h
@@ -0,0 +1,101 @@
+/*
+ *
+ * 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_SERVER_FILTER_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_SERVER_FILTER_H
+
+#include <grpc/support/port_platform.h>
+
+#include "absl/strings/string_view.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+#include "include/grpc/grpc_security.h"
+#include "src/cpp/ext/filters/census/channel_filter.h"
+#include "src/cpp/ext/filters/census/context.h"
+
+namespace grpc {
+
+// A CallData class will be created for every grpc call within a channel. It is
+// used to store data and methods specific to that call. CensusServerCallData is
+// thread-compatible, however typically only 1 thread should be interacting with
+// a call at a time.
+class CensusServerCallData : public CallData {
+ public:
+ // Maximum size of server stats that are sent on the wire.
+ static constexpr uint32_t kMaxServerStatsLen = 16;
+
+ CensusServerCallData()
+ : gc_(nullptr),
+ auth_context_(nullptr),
+ recv_initial_metadata_(nullptr),
+ initial_on_done_recv_initial_metadata_(nullptr),
+ initial_on_done_recv_message_(nullptr),
+ recv_message_(nullptr),
+ recv_message_count_(0),
+ sent_message_count_(0) {
+ memset(&census_bin_, 0, sizeof(grpc_linked_mdelem));
+ memset(&path_, 0, sizeof(grpc_slice));
+ memset(&on_done_recv_initial_metadata_, 0, sizeof(grpc_closure));
+ memset(&on_done_recv_message_, 0, sizeof(grpc_closure));
+ }
+
+ 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;
+
+ static void OnDoneRecvInitialMetadataCb(void* user_data, grpc_error* error);
+
+ static void OnDoneRecvMessageCb(void* user_data, grpc_error* error);
+
+ private:
+ CensusContext context_;
+ // server method
+ absl::string_view method_;
+ std::string qualified_method_;
+ grpc_slice path_;
+ // Pointer to the grpc_call element
+ grpc_call* gc_;
+ // Authorization context for the call.
+ grpc_auth_context* auth_context_;
+ // Metadata element for census stats.
+ grpc_linked_mdelem census_bin_;
+ // recv callback
+ grpc_metadata_batch* recv_initial_metadata_;
+ grpc_closure* initial_on_done_recv_initial_metadata_;
+ grpc_closure on_done_recv_initial_metadata_;
+ // recv message
+ grpc_closure* initial_on_done_recv_message_;
+ grpc_closure on_done_recv_message_;
+ absl::Time start_time_;
+ absl::Duration elapsed_time_;
+ grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message_;
+ uint64_t recv_message_count_;
+ uint64_t sent_message_count_;
+ // Buffer needed for grpc_slice to reference it when adding metatdata to
+ // response.
+ char stats_buf_[kMaxServerStatsLen];
+};
+
+} // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_SERVER_FILTER_H */
diff --git a/src/cpp/ext/filters/census/views.cc b/src/cpp/ext/filters/census/views.cc
new file mode 100644
index 0000000000..2c0c5f7295
--- /dev/null
+++ b/src/cpp/ext/filters/census/views.cc
@@ -0,0 +1,491 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+
+#include "absl/time/time.h"
+#include "opencensus/stats/internal/aggregation_window.h"
+#include "opencensus/stats/internal/set_aggregation_window.h"
+#include "opencensus/stats/stats.h"
+
+namespace grpc {
+
+using ::opencensus::stats::Aggregation;
+using ::opencensus::stats::AggregationWindow;
+using ::opencensus::stats::BucketBoundaries;
+using ::opencensus::stats::ViewDescriptor;
+
+// These measure definitions should be kept in sync across opencensus
+// implementations.
+
+namespace {
+
+Aggregation BytesDistributionAggregation() {
+ return Aggregation::Distribution(BucketBoundaries::Explicit(
+ {0, 1024, 2048, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216,
+ 67108864, 268435456, 1073741824, 4294967296}));
+}
+
+Aggregation MillisDistributionAggregation() {
+ return Aggregation::Distribution(BucketBoundaries::Explicit(
+ {0, 0.01, 0.05, 0.1, 0.3, 0.6, 0.8, 1, 2, 3, 4,
+ 5, 6, 8, 10, 13, 16, 20, 25, 30, 40, 50,
+ 65, 80, 100, 130, 160, 200, 250, 300, 400, 500, 650,
+ 800, 1000, 2000, 5000, 10000, 20000, 50000, 100000}));
+}
+
+Aggregation CountDistributionAggregation() {
+ return Aggregation::Distribution(BucketBoundaries::Exponential(17, 1.0, 2.0));
+}
+
+ViewDescriptor MinuteDescriptor() {
+ auto descriptor = ViewDescriptor();
+ SetAggregationWindow(AggregationWindow::Interval(absl::Minutes(1)),
+ &descriptor);
+ return descriptor;
+}
+
+ViewDescriptor HourDescriptor() {
+ auto descriptor = ViewDescriptor();
+ SetAggregationWindow(AggregationWindow::Interval(absl::Hours(1)),
+ &descriptor);
+ return descriptor;
+}
+
+} // namespace
+
+void RegisterOpenCensusViewsForExport() {
+ ClientSentMessagesPerRpcCumulative().RegisterForExport();
+ ClientSentBytesPerRpcCumulative().RegisterForExport();
+ ClientReceivedMessagesPerRpcCumulative().RegisterForExport();
+ ClientReceivedBytesPerRpcCumulative().RegisterForExport();
+ ClientRoundtripLatencyCumulative().RegisterForExport();
+ ClientServerLatencyCumulative().RegisterForExport();
+
+ ServerSentMessagesPerRpcCumulative().RegisterForExport();
+ ServerSentBytesPerRpcCumulative().RegisterForExport();
+ ServerReceivedMessagesPerRpcCumulative().RegisterForExport();
+ ServerReceivedBytesPerRpcCumulative().RegisterForExport();
+ ServerServerLatencyCumulative().RegisterForExport();
+}
+
+// client cumulative
+const ViewDescriptor& ClientSentBytesPerRpcCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/client/sent_bytes_per_rpc/cumulative")
+ .set_measure(kRpcClientSentBytesPerRpcMeasureName)
+ .set_aggregation(BytesDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientReceivedBytesPerRpcCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/client/received_bytes_per_rpc/cumulative")
+ .set_measure(kRpcClientReceivedBytesPerRpcMeasureName)
+ .set_aggregation(BytesDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientRoundtripLatencyCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/client/roundtrip_latency/cumulative")
+ .set_measure(kRpcClientRoundtripLatencyMeasureName)
+ .set_aggregation(MillisDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientServerLatencyCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/client/server_latency/cumulative")
+ .set_measure(kRpcClientServerLatencyMeasureName)
+ .set_aggregation(MillisDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientCompletedRpcsCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/client/completed_rpcs/cumulative")
+ .set_measure(kRpcClientRoundtripLatencyMeasureName)
+ .set_aggregation(Aggregation::Count())
+ .add_column(ClientMethodTagKey())
+ .add_column(ClientStatusTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientSentMessagesPerRpcCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/client/received_messages_per_rpc/cumulative")
+ .set_measure(kRpcClientSentMessagesPerRpcMeasureName)
+ .set_aggregation(CountDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientReceivedMessagesPerRpcCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/client/sent_messages_per_rpc/cumulative")
+ .set_measure(kRpcClientReceivedMessagesPerRpcMeasureName)
+ .set_aggregation(CountDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+// server cumulative
+const ViewDescriptor& ServerSentBytesPerRpcCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/server/received_bytes_per_rpc/cumulative")
+ .set_measure(kRpcServerSentBytesPerRpcMeasureName)
+ .set_aggregation(BytesDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerReceivedBytesPerRpcCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/server/sent_bytes_per_rpc/cumulative")
+ .set_measure(kRpcServerReceivedBytesPerRpcMeasureName)
+ .set_aggregation(BytesDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerServerLatencyCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/server/elapsed_time/cumulative")
+ .set_measure(kRpcServerServerLatencyMeasureName)
+ .set_aggregation(MillisDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerCompletedRpcsCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/server/completed_rpcs/cumulative")
+ .set_measure(kRpcServerServerLatencyMeasureName)
+ .set_aggregation(Aggregation::Count())
+ .add_column(ServerMethodTagKey())
+ .add_column(ServerStatusTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerSentMessagesPerRpcCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/server/received_messages_per_rpc/cumulative")
+ .set_measure(kRpcServerSentMessagesPerRpcMeasureName)
+ .set_aggregation(CountDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerReceivedMessagesPerRpcCumulative() {
+ const static ViewDescriptor descriptor =
+ ViewDescriptor()
+ .set_name("grpc.io/server/sent_messages_per_rpc/cumulative")
+ .set_measure(kRpcServerReceivedMessagesPerRpcMeasureName)
+ .set_aggregation(CountDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+// client minute
+const ViewDescriptor& ClientSentBytesPerRpcMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/client/sent_bytes_per_rpc/minute")
+ .set_measure(kRpcClientSentBytesPerRpcMeasureName)
+ .set_aggregation(BytesDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientReceivedBytesPerRpcMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/client/received_bytes_per_rpc/minute")
+ .set_measure(kRpcClientReceivedBytesPerRpcMeasureName)
+ .set_aggregation(BytesDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientRoundtripLatencyMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/client/roundtrip_latency/minute")
+ .set_measure(kRpcClientRoundtripLatencyMeasureName)
+ .set_aggregation(MillisDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientServerLatencyMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/client/server_latency/minute")
+ .set_measure(kRpcClientServerLatencyMeasureName)
+ .set_aggregation(MillisDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientCompletedRpcsMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/client/completed_rpcs/minute")
+ .set_measure(kRpcClientRoundtripLatencyMeasureName)
+ .set_aggregation(Aggregation::Count())
+ .add_column(ClientMethodTagKey())
+ .add_column(ClientStatusTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientSentMessagesPerRpcMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/client/sent_messages_per_rpc/minute")
+ .set_measure(kRpcClientSentMessagesPerRpcMeasureName)
+ .set_aggregation(CountDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientReceivedMessagesPerRpcMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/client/received_messages_per_rpc/minute")
+ .set_measure(kRpcClientReceivedMessagesPerRpcMeasureName)
+ .set_aggregation(CountDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+// server minute
+const ViewDescriptor& ServerSentBytesPerRpcMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/server/sent_bytes_per_rpc/minute")
+ .set_measure(kRpcServerSentBytesPerRpcMeasureName)
+ .set_aggregation(BytesDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerReceivedBytesPerRpcMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/server/received_bytes_per_rpc/minute")
+ .set_measure(kRpcServerReceivedBytesPerRpcMeasureName)
+ .set_aggregation(BytesDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerServerLatencyMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/server/server_latency/minute")
+ .set_measure(kRpcServerServerLatencyMeasureName)
+ .set_aggregation(MillisDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerCompletedRpcsMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/server/completed_rpcs/minute")
+ .set_measure(kRpcServerServerLatencyMeasureName)
+ .set_aggregation(Aggregation::Count())
+ .add_column(ServerMethodTagKey())
+ .add_column(ServerStatusTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerSentMessagesPerRpcMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/server/sent_messages_per_rpc/minute")
+ .set_measure(kRpcServerSentMessagesPerRpcMeasureName)
+ .set_aggregation(CountDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerReceivedMessagesPerRpcMinute() {
+ const static ViewDescriptor descriptor =
+ MinuteDescriptor()
+ .set_name("grpc.io/server/received_messages_per_rpc/minute")
+ .set_measure(kRpcServerReceivedMessagesPerRpcMeasureName)
+ .set_aggregation(CountDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+// client hour
+const ViewDescriptor& ClientSentBytesPerRpcHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/client/sent_bytes_per_rpc/hour")
+ .set_measure(kRpcClientSentBytesPerRpcMeasureName)
+ .set_aggregation(BytesDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientReceivedBytesPerRpcHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/client/received_bytes_per_rpc/hour")
+ .set_measure(kRpcClientReceivedBytesPerRpcMeasureName)
+ .set_aggregation(BytesDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientRoundtripLatencyHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/client/roundtrip_latency/hour")
+ .set_measure(kRpcClientRoundtripLatencyMeasureName)
+ .set_aggregation(MillisDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientServerLatencyHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/client/server_latency/hour")
+ .set_measure(kRpcClientServerLatencyMeasureName)
+ .set_aggregation(MillisDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientCompletedRpcsHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/client/completed_rpcs/hour")
+ .set_measure(kRpcClientRoundtripLatencyMeasureName)
+ .set_aggregation(Aggregation::Count())
+ .add_column(ClientMethodTagKey())
+ .add_column(ClientStatusTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientSentMessagesPerRpcHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/client/sent_messages_per_rpc/hour")
+ .set_measure(kRpcClientSentMessagesPerRpcMeasureName)
+ .set_aggregation(CountDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ClientReceivedMessagesPerRpcHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/client/received_messages_per_rpc/hour")
+ .set_measure(kRpcClientReceivedMessagesPerRpcMeasureName)
+ .set_aggregation(CountDistributionAggregation())
+ .add_column(ClientMethodTagKey());
+ return descriptor;
+}
+
+// server hour
+const ViewDescriptor& ServerSentBytesPerRpcHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/server/sent_bytes_per_rpc/hour")
+ .set_measure(kRpcServerSentBytesPerRpcMeasureName)
+ .set_aggregation(BytesDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerReceivedBytesPerRpcHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/server/received_bytes_per_rpc/hour")
+ .set_measure(kRpcServerReceivedBytesPerRpcMeasureName)
+ .set_aggregation(BytesDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerServerLatencyHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/server/server_latency/hour")
+ .set_measure(kRpcServerServerLatencyMeasureName)
+ .set_aggregation(MillisDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerCompletedRpcsHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/server/completed_rpcs/hour")
+ .set_measure(kRpcServerServerLatencyMeasureName)
+ .set_aggregation(Aggregation::Count())
+ .add_column(ServerMethodTagKey())
+ .add_column(ServerStatusTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerSentMessagesPerRpcHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/server/sent_messages_per_rpc/hour")
+ .set_measure(kRpcServerSentMessagesPerRpcMeasureName)
+ .set_aggregation(CountDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+const ViewDescriptor& ServerReceivedMessagesPerRpcHour() {
+ const static ViewDescriptor descriptor =
+ HourDescriptor()
+ .set_name("grpc.io/server/received_messages_per_rpc/hour")
+ .set_measure(kRpcServerReceivedMessagesPerRpcMeasureName)
+ .set_aggregation(CountDistributionAggregation())
+ .add_column(ServerMethodTagKey());
+ return descriptor;
+}
+
+} // namespace grpc
diff --git a/src/csharp/Grpc.Core/Interceptors/CallInvokerExtensions.cs b/src/csharp/Grpc.Core/Interceptors/CallInvokerExtensions.cs
index 421b5d379e..39c24d0157 100644
--- a/src/csharp/Grpc.Core/Interceptors/CallInvokerExtensions.cs
+++ b/src/csharp/Grpc.Core/Interceptors/CallInvokerExtensions.cs
@@ -24,7 +24,6 @@ namespace Grpc.Core.Interceptors
{
/// <summary>
/// Extends the CallInvoker class to provide the interceptor facility on the client side.
- /// This is an EXPERIMENTAL API.
/// </summary>
public static class CallInvokerExtensions
{
diff --git a/src/csharp/Grpc.Core/Interceptors/ChannelExtensions.cs b/src/csharp/Grpc.Core/Interceptors/ChannelExtensions.cs
index 00b2fa8bec..c7d0c2472a 100644
--- a/src/csharp/Grpc.Core/Interceptors/ChannelExtensions.cs
+++ b/src/csharp/Grpc.Core/Interceptors/ChannelExtensions.cs
@@ -22,7 +22,6 @@ namespace Grpc.Core.Interceptors
{
/// <summary>
/// Provides extension methods to make it easy to register interceptors on Channel objects.
- /// This is an EXPERIMENTAL API.
/// </summary>
public static class ChannelExtensions
{
diff --git a/src/csharp/Grpc.Core/Interceptors/ClientInterceptorContext.cs b/src/csharp/Grpc.Core/Interceptors/ClientInterceptorContext.cs
index de06a77077..4665fc553b 100644
--- a/src/csharp/Grpc.Core/Interceptors/ClientInterceptorContext.cs
+++ b/src/csharp/Grpc.Core/Interceptors/ClientInterceptorContext.cs
@@ -25,7 +25,6 @@ namespace Grpc.Core.Interceptors
{
/// <summary>
/// Carries along the context associated with intercepted invocations on the client side.
- /// This is an EXPERIMENTAL API.
/// </summary>
public struct ClientInterceptorContext<TRequest, TResponse>
where TRequest : class
diff --git a/src/csharp/Grpc.Core/Interceptors/Interceptor.cs b/src/csharp/Grpc.Core/Interceptors/Interceptor.cs
index 56a30c34af..ab708034f3 100644
--- a/src/csharp/Grpc.Core/Interceptors/Interceptor.cs
+++ b/src/csharp/Grpc.Core/Interceptors/Interceptor.cs
@@ -25,7 +25,6 @@ namespace Grpc.Core.Interceptors
{
/// <summary>
/// Serves as the base class for gRPC interceptors.
- /// This is an EXPERIMENTAL API.
/// </summary>
public abstract class Interceptor
{
diff --git a/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs b/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs
index b9b53247ce..8987544f7f 100644
--- a/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs
+++ b/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs
@@ -24,14 +24,12 @@ namespace Grpc.Core.Interceptors
{
/// <summary>
/// Extends the ServerServiceDefinition class to add methods used to register interceptors on the server side.
- /// This is an EXPERIMENTAL API.
/// </summary>
public static class ServerServiceDefinitionExtensions
{
/// <summary>
/// Returns a <see cref="Grpc.Core.ServerServiceDefinition" /> instance that
/// intercepts incoming calls to the underlying service handler through the given interceptor.
- /// This is an EXPERIMENTAL API.
/// </summary>
/// <param name="serverServiceDefinition">The <see cref="Grpc.Core.ServerServiceDefinition" /> instance to register interceptors on.</param>
/// <param name="interceptor">The interceptor to intercept the incoming invocations with.</param>
@@ -52,7 +50,6 @@ namespace Grpc.Core.Interceptors
/// <summary>
/// Returns a <see cref="Grpc.Core.ServerServiceDefinition" /> instance that
/// intercepts incoming calls to the underlying service handler through the given interceptors.
- /// This is an EXPERIMENTAL API.
/// </summary>
/// <param name="serverServiceDefinition">The <see cref="Grpc.Core.ServerServiceDefinition" /> instance to register interceptors on.</param>
/// <param name="interceptors">
diff --git a/src/csharp/README.md b/src/csharp/README.md
index e117e66afd..92be4bf1e5 100644
--- a/src/csharp/README.md
+++ b/src/csharp/README.md
@@ -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
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 3e6ec474b7..87a2516f8d 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -935,11 +935,12 @@ grpcsharp_ssl_credentials_create(const char* pem_root_certs,
if (key_cert_pair_cert_chain || key_cert_pair_private_key) {
key_cert_pair.cert_chain = key_cert_pair_cert_chain;
key_cert_pair.private_key = key_cert_pair_private_key;
- return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL);
+ return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL,
+ NULL);
} else {
GPR_ASSERT(!key_cert_pair_cert_chain);
GPR_ASSERT(!key_cert_pair_private_key);
- return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL);
+ return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL, NULL);
}
}
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m
index f4b933751f..348989904a 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.m
+++ b/src/objective-c/GRPCClient/private/GRPCHost.m
@@ -183,14 +183,14 @@ static NSMutableDictionary *kHostCache;
grpc_channel_credentials *creds;
if (pemPrivateKey == nil && pemCertChain == nil) {
- creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL);
+ creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL, NULL);
} else {
grpc_ssl_pem_key_cert_pair key_cert_pair;
NSData *privateKeyASCII = [self nullTerminatedDataWithString:pemPrivateKey];
NSData *certChainASCII = [self nullTerminatedDataWithString:pemCertChain];
key_cert_pair.private_key = privateKeyASCII.bytes;
key_cert_pair.cert_chain = certChainASCII.bytes;
- creds = grpc_ssl_credentials_create(rootsASCII.bytes, &key_cert_pair, NULL);
+ creds = grpc_ssl_credentials_create(rootsASCII.bytes, &key_cert_pair, NULL, NULL);
}
@synchronized(self) {
diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c
index 10d7380ca1..af1372878d 100644
--- a/src/php/ext/grpc/channel_credentials.c
+++ b/src/php/ext/grpc/channel_credentials.c
@@ -158,7 +158,7 @@ PHP_METHOD(ChannelCredentials, createSsl) {
grpc_channel_credentials *creds = grpc_ssl_credentials_create(
pem_root_certs,
- pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL);
+ pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL, NULL);
zval *creds_object = grpc_php_wrap_channel_credentials(creds, hashstr, false
TSRMLS_CC);
efree(hashkey);
diff --git a/src/proto/census/census.options b/src/proto/census/census.options
deleted file mode 100644
index a1f80395c7..0000000000
--- a/src/proto/census/census.options
+++ /dev/null
@@ -1,3 +0,0 @@
-google.census.Tag.key max_size:255
-google.census.Tag.value max_size:255
-google.census.View.tag_key max_count:15
diff --git a/src/proto/census/census.proto b/src/proto/census/census.proto
deleted file mode 100644
index ae7d7763e8..0000000000
--- a/src/proto/census/census.proto
+++ /dev/null
@@ -1,307 +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.
-
-syntax = "proto3";
-
-package google.census;
-
-// All the census protos.
-//
-// Nomenclature note: capitalized names below (like Resource) are protos.
-//
-// Census lets you define a Resource - something which can be measured, like the
-// latency of an RPC, the number of CPU cycles spent on an operation, or
-// anything else you care to measure. You can record individual instances of
-// measurements (a double value) for every Resource of interest. These
-// individual measurements are aggregated together into an Aggregation. There
-// are two Aggregation types available: Distribution (describes the
-// distribution of all measurements, possibly with a histogram) and
-// IntervalStats (the count and mean of measurements across specified time
-// periods). An Aggregation is described by an AggregationDescriptor.
-//
-// You can define how your stats are broken down by Tag values and which
-// Aggregations to use through a View. The corresponding combination of
-// Resource/View/Aggregation which is available to census clients is called a
-// Metric.
-
-
-// The following two types are copied from
-// google/protobuf/{duration,timestamp}.proto. Ideally, we would be able to
-// import them, but this causes compilation issues on C-based systems
-// (e.g. https://koti.kapsi.fi/jpa/nanopb/), which cannot process the C++
-// headers generated from the standard protobuf distribution. See the relevant
-// proto files for full documentation of these types.
-
-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 {
- // Represents seconds of UTC time since Unix epoch
- // 1970-01-01T00:00:00Z. Must be from 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;
-}
-
-// Describes a Resource.
-message Resource {
- // name of resource, e.g. rpc_latency, cpu. Must be unique.
- string name = 1;
-
- // More detailed description of the resource, used in documentation.
- string description = 2;
-
- // Fundamental units of measurement supported by Census
- // TODO(aveitch): expand this to include other S.I. units?
- enum BasicUnit {
- UNKNOWN = 0;
- BITS = 1;
- BYTES = 2;
- SECS = 3;
- CORES = 4;
- MAX_UNITS = 5;
- }
-
- // MeasurementUnit lets you build compound units of the form
- // 10^n * (A * B * ...) / (X * Y * ...),
- // where the elements in the numerator and denominator are all BasicUnits. A
- // MeasurementUnit must have at least one BasicUnit in its numerator.
- //
- // To specify multiplication in the numerator or denominator, simply specify
- // multiple numerator or denominator fields. For example:
- //
- // - byte-seconds (i.e. bytes * seconds):
- // numerator: BYTES
- // numerator: SECS
- //
- // - events/sec^2 (i.e. rate of change of events/sec):
- // numerator: COUNT
- // denominator: SECS
- // denominator: SECS
- //
- // To specify multiples (in power of 10) of units, specify a non-zero prefix
- // value, for example:
- //
- // - MB/s (i.e. megabytes / s):
- // prefix: 6
- // numerator: BYTES
- // denominator: SECS
- //
- // - nanoseconds
- // prefix: -9
- // numerator: SECS
- message MeasurementUnit {
- int32 prefix = 1;
- repeated BasicUnit numerator = 2;
- repeated BasicUnit denominator = 3;
- }
-
- // The units in which Resource values are measured.
- MeasurementUnit unit = 3;
-}
-
-// An Aggregation summarizes a series of individual Resource measurements, an
-// AggregationDescriptor describes an Aggregation.
-message AggregationDescriptor {
- enum AggregationType {
- // Unspecified. Should not be used.
- UNKNOWN = 0;
- // A count of measurements made.
- COUNT = 1;
- // A Distribution.
- DISTRIBUTION = 2;
- // Counts over fixed time intervals.
- INTERVAL = 3;
- }
- // The type of Aggregation.
- AggregationType type = 1;
-
- // At most one set of options. It is illegal to specifiy an option for
- // COUNT Aggregations. interval_boundaries must be set for INTERVAL types.
- // bucket_boundaries are optional for DISTRIBUTION types.
- oneof options {
- // Defines histogram bucket boundaries for Distributions.
- BucketBoundaries bucket_boundaries = 2;
- // Defines the time windows to record for IntervalStats.
- IntervalBoundaries interval_boundaries = 3;
- }
-
- // A Distribution may optionally contain a histogram of the values in the
- // population. The bucket boundaries for that histogram are described by
- // `bucket_boundaries`. This defines `size(bounds) + 1` (= N) buckets. The
- // boundaries for bucket index i are:
- //
- // [-infinity, bounds[i]) for i == 0
- // [bounds[i-1], bounds[i]) for 0 < i < N-2
- // [bounds[i-1], +infinity) for i == N-1
- //
- // i.e. an underflow bucket (number 0), zero or more finite buckets (1
- // through N - 2, and an overflow bucket (N - 1), with inclusive lower
- // bounds and exclusive upper bounds.
- //
- // There must be at least one element in `bounds`. If `bounds` has only one
- // element, there are no finite buckets, and that single element is the
- // common boundary of the overflow and underflow buckets.
- message BucketBoundaries {
- // The values must be monotonically increasing.
- repeated double bounds = 1;
- }
-
- // For Interval stats, describe the size of each window.
- message IntervalBoundaries {
- // For each time window, specify a duration in seconds.
- repeated double window_size = 1;
- }
-}
-
-// Distribution contains summary statistics for a population of values and,
-// optionally, a histogram representing the distribution of those values across
-// a specified set of histogram buckets, as defined in
-// Aggregation.bucket_options.
-//
-// The summary statistics are the count, mean, minimum, and the maximum of the
-// set of population of values.
-//
-// Although it is not forbidden, it is generally a bad idea to include
-// non-finite values (infinities or NaNs) in the population of values, as this
-// will render the `mean` field meaningless.
-message Distribution {
- // The number of values in the population. Must be non-negative.
- int64 count = 1;
-
- // The arithmetic mean of the values in the population. If `count` is zero
- // then this field must be zero.
- double mean = 2;
-
- // Describes a range of population values.
- message Range {
- // The minimum of the population values.
- double min = 1;
- // The maximum of the population values.
- double max = 2;
- }
-
- // The range of the population values. If `count` is zero, this field will not
- // be defined.
- Range range = 3;
-
- // A Distribution may optionally contain a histogram of the values in the
- // population. The histogram is given in `bucket_count` as counts of values
- // that fall into one of a sequence of non-overlapping buckets, as described
- // by `AggregationDescriptor.options.bucket_boundaries`.
- // The sum of the values in `bucket_counts` must equal the value in `count`.
- //
- // Bucket counts are given in order under the numbering scheme described
- // above (the underflow bucket has number 0; the finite buckets, if any,
- // have numbers 1 through N-2; the overflow bucket has number N-1).
- //
- // The size of `bucket_count` must be no greater than N as defined in
- // `bucket_boundaries`.
- //
- // Any suffix of trailing zero bucket_count fields may be omitted.
- repeated int64 bucket_count = 4;
-}
-
-// Record summary stats over various time windows.
-message IntervalStats {
- // Summary statistic over a single time window.
- message Window {
- // The window duration. Must be positive.
- Duration window_size = 1;
- // The number of measurements in this window.
- int64 count = 2;
- // The arithmetic mean of all measurements in the window.
- double mean = 3;
- }
-
- // Full set of windows for this aggregation.
- repeated Window window = 1;
-}
-
-// A Tag: key-value pair.
-message Tag {
- string key = 1;
- string value = 2;
-}
-
-// A View specifies an Aggregation and a set of tag keys. The Aggregation will
-// be broken down by the unique set of matching tag values for each measurement.
-message View {
- // Name of view. Must be unique.
- string name = 1;
-
- // More detailed description, for documentation purposes.
- string description = 2;
-
- // Name of Resource to be broken down for this view.
- string resource_name = 3;
-
- // Aggregation type to associate with this View.
- AggregationDescriptor aggregation = 4;
-
- // Tag keys to match with a given Resource measurement. If no keys are
- // specified, then all stats are recorded. Keys must be unique.
- repeated string tag_key = 5;
-}
-
-// An Aggregation summarizes a series of individual Resource measurements.
-message Aggregation {
- // Name of this aggregation.
- string name = 1;
-
- // More detailed description, for documentation purposes.
- string description = 2;
-
- // The data for this Aggregation.
- oneof data {
- uint64 count = 3;
- Distribution distribution = 4;
- IntervalStats interval_stats = 5;
- }
-
- // Tags associated with this Aggregation.
- repeated Tag tag = 6;
-}
-
-// A Metric represents all the Aggregations for a particular view.
-message Metric {
- // View associated with this Metric.
- string view_name = 1;
-
- // Aggregations - each will have a unique set of tag values for the tag_keys
- // associated with the corresponding View.
- repeated Aggregation aggregation = 2;
-
- // Start and end timestamps over which the metric was accumulated. These
- // values are not relevant/defined for IntervalStats aggregations, which are
- // always accumulated over a fixed time period.
- Timestamp start = 3;
- Timestamp end = 4;
-}
diff --git a/src/proto/census/trace_context.options b/src/proto/census/trace_context.options
deleted file mode 100644
index e69de29bb2..0000000000
--- a/src/proto/census/trace_context.options
+++ /dev/null
diff --git a/src/proto/census/trace_context.proto b/src/proto/census/trace_context.proto
deleted file mode 100644
index 7e5087dbee..0000000000
--- a/src/proto/census/trace_context.proto
+++ /dev/null
@@ -1,29 +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.
-
-syntax = "proto3";
-
-package google.trace;
-
-// Tracing information that is propagated with RPC's.
-message TraceContext {
- // A TraceId uniquely represents a single Trace. It is a 128-bit nonce.
- // The 128-bit ID is split into 2 64-bit chunks. (REQUIRED)
- fixed64 trace_id_hi = 1;
- fixed64 trace_id_lo = 2;
- // ID of parent (client) span. (REQUIRED)
- fixed64 span_id = 3;
- // Span option flags. First bit is true if this trace is sampled. (OPTIONAL)
- fixed32 span_options = 4;
-}
diff --git a/src/proto/grpc/channelz/channelz.proto b/src/proto/grpc/channelz/channelz.proto
index 14db66a654..d930dfcfb4 100644
--- a/src/proto/grpc/channelz/channelz.proto
+++ b/src/proto/grpc/channelz/channelz.proto
@@ -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;
}
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
index f4ccfbc016..d2c0389ca6 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
@@ -142,12 +142,12 @@ cdef class SSLChannelCredentials(ChannelCredentials):
c_pem_root_certificates = self._pem_root_certificates
if self._private_key is None and self._certificate_chain is None:
return grpc_ssl_credentials_create(
- c_pem_root_certificates, NULL, NULL)
+ c_pem_root_certificates, NULL, NULL, NULL)
else:
c_pem_key_certificate_pair.private_key = self._private_key
c_pem_key_certificate_pair.certificate_chain = self._certificate_chain
return grpc_ssl_credentials_create(
- c_pem_root_certificates, &c_pem_key_certificate_pair, NULL)
+ c_pem_root_certificates, &c_pem_key_certificate_pair, NULL, NULL)
cdef class CompositeChannelCredentials(ChannelCredentials):
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index cfefeaf938..bcbfec0c9f 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -453,11 +453,14 @@ cdef extern from "grpc/grpc_security.h":
# We don't care about the internals (and in fact don't know them)
pass
-
ctypedef struct grpc_ssl_session_cache:
# We don't care about the internals (and in fact don't know them)
pass
+ ctypedef struct verify_peer_options:
+ # We don't care about the internals (and in fact don't know them)
+ pass
+
ctypedef void (*grpc_ssl_roots_override_callback)(char **pem_root_certs)
grpc_ssl_session_cache *grpc_ssl_session_cache_create_lru(size_t capacity)
@@ -469,7 +472,7 @@ cdef extern from "grpc/grpc_security.h":
grpc_channel_credentials *grpc_google_default_credentials_create() nogil
grpc_channel_credentials *grpc_ssl_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
- void *reserved) nogil
+ verify_peer_options *verify_options, void *reserved) nogil
grpc_channel_credentials *grpc_composite_channel_credentials_create(
grpc_channel_credentials *creds1, grpc_call_credentials *creds2,
void *reserved) nogil
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index d7d489c5a4..b20b8155a0 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -64,6 +64,7 @@ CORE_SOURCE_FILES = [
'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',
@@ -353,7 +354,7 @@ CORE_SOURCE_FILES = [
'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/core/ext/census/grpc_context.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',
'src/core/ext/filters/http/client_authority_filter.cc',
diff --git a/src/python/grpcio_testing/MANIFEST.in b/src/python/grpcio_testing/MANIFEST.in
new file mode 100644
index 0000000000..39b3565217
--- /dev/null
+++ b/src/python/grpcio_testing/MANIFEST.in
@@ -0,0 +1,3 @@
+include grpc_version.py
+recursive-include grpc_testing *.py
+global-exclude *.pyc
diff --git a/src/python/grpcio_testing/README.rst b/src/python/grpcio_testing/README.rst
new file mode 100644
index 0000000000..c699b80fb6
--- /dev/null
+++ b/src/python/grpcio_testing/README.rst
@@ -0,0 +1,10 @@
+gRPC Python Testing Package
+===========================
+
+Testing utilities for gRPC Python
+
+Dependencies
+------------
+
+Depends on the `grpcio` package, available from PyPI via `pip install grpcio`.
+
diff --git a/src/ruby/end2end/multiple_killed_watching_threads_driver.rb b/src/ruby/end2end/multiple_killed_watching_threads_driver.rb
index 8ec2073d98..7b39f5a347 100755
--- a/src/ruby/end2end/multiple_killed_watching_threads_driver.rb
+++ b/src/ruby/end2end/multiple_killed_watching_threads_driver.rb
@@ -58,10 +58,6 @@ def main
run_multiple_killed_watches(10, 0.1)
STDERR.puts '1000 iterations, sleep 0.001 before killing thread'
run_multiple_killed_watches(1000, 0.001)
- STDERR.puts '10000 iterations, sleep 0.00001 before killing thread'
- run_multiple_killed_watches(10_000, 0.00001)
- STDERR.puts '20000 iterations, sleep 0.00001 before killing thread'
- run_multiple_killed_watches(20_000, 0.00001)
end
main
diff --git a/src/ruby/end2end/package_with_underscore_checker.rb b/src/ruby/end2end/package_with_underscore_checker.rb
new file mode 100644
index 0000000000..27ea00ffa7
--- /dev/null
+++ b/src/ruby/end2end/package_with_underscore_checker.rb
@@ -0,0 +1,54 @@
+# 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.
+
+require 'open3'
+require 'tmpdir'
+
+def main
+ root_dir = File.join(File.dirname(__FILE__), '..', '..', '..')
+ pb_dir = File.join(root_dir, 'src', 'ruby', 'end2end', 'protos')
+
+ fail 'CONFIG env variable unexpectedly unset' unless ENV['CONFIG']
+ bins_sub_dir = ENV['CONFIG']
+ bins_dir = File.join(root_dir, 'bins', bins_sub_dir)
+
+ plugin = File.join(bins_dir, 'grpc_ruby_plugin')
+ protoc = File.join(bins_dir, 'protobuf', 'protoc')
+
+ got = nil
+
+ Dir.mktmpdir do |tmp_dir|
+ gen_out = File.join(tmp_dir, 'package_with_underscore', 'service_services_pb.rb')
+
+ pid = spawn(
+ protoc,
+ "--proto_path=#{pb_dir}",
+ 'package_with_underscore/service.proto',
+ "--grpc_out=#{tmp_dir}",
+ "--plugin=protoc-gen-grpc=#{plugin}"
+ )
+ Process.waitpid2(pid)
+ File.open(gen_out) { |f| got = f.read }
+ end
+
+ correct_modularized_rpc = 'rpc :TestOne, ' \
+ 'Grpc::Testing::PackageWithUnderscore::Data::Request, ' \
+ 'Grpc::Testing::PackageWithUnderscore::Data::Response'
+
+ return if got.include?(correct_modularized_rpc)
+
+ fail 'generated file does not match with correct_modularized_rpc'
+end
+
+main
diff --git a/src/ruby/spec/pb/package_with_underscore/data.proto b/src/ruby/end2end/protos/package_with_underscore/data.proto
index 2706f1d7be..2706f1d7be 100644
--- a/src/ruby/spec/pb/package_with_underscore/data.proto
+++ b/src/ruby/end2end/protos/package_with_underscore/data.proto
diff --git a/src/ruby/spec/pb/package_with_underscore/service.proto b/src/ruby/end2end/protos/package_with_underscore/service.proto
index 814c7898cd..814c7898cd 100644
--- a/src/ruby/spec/pb/package_with_underscore/service.proto
+++ b/src/ruby/end2end/protos/package_with_underscore/service.proto
diff --git a/src/ruby/ext/grpc/rb_channel_credentials.c b/src/ruby/ext/grpc/rb_channel_credentials.c
index b23a32caf1..178224c6e0 100644
--- a/src/ruby/ext/grpc/rb_channel_credentials.c
+++ b/src/ruby/ext/grpc/rb_channel_credentials.c
@@ -159,12 +159,12 @@ static VALUE grpc_rb_channel_credentials_init(int argc, VALUE* argv,
pem_root_certs_cstr = RSTRING_PTR(pem_root_certs);
}
if (pem_private_key == Qnil && pem_cert_chain == Qnil) {
- creds = grpc_ssl_credentials_create(pem_root_certs_cstr, NULL, NULL);
+ creds = grpc_ssl_credentials_create(pem_root_certs_cstr, NULL, NULL, NULL);
} else {
key_cert_pair.private_key = RSTRING_PTR(pem_private_key);
key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain);
- creds =
- grpc_ssl_credentials_create(pem_root_certs_cstr, &key_cert_pair, NULL);
+ creds = grpc_ssl_credentials_create(pem_root_certs_cstr, &key_cert_pair,
+ NULL, NULL);
}
if (creds == NULL) {
rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 02f84c0b96..031699ce8e 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -68,8 +68,6 @@ grpc_channel_get_info_type grpc_channel_get_info_import;
grpc_insecure_channel_create_type grpc_insecure_channel_create_import;
grpc_lame_client_channel_create_type grpc_lame_client_channel_create_import;
grpc_channel_destroy_type grpc_channel_destroy_import;
-grpc_channel_get_trace_type grpc_channel_get_trace_import;
-grpc_channel_get_uuid_type grpc_channel_get_uuid_import;
grpc_call_cancel_type grpc_call_cancel_import;
grpc_call_cancel_with_status_type grpc_call_cancel_with_status_import;
grpc_call_ref_type grpc_call_ref_import;
@@ -316,8 +314,6 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_insecure_channel_create_import = (grpc_insecure_channel_create_type) GetProcAddress(library, "grpc_insecure_channel_create");
grpc_lame_client_channel_create_import = (grpc_lame_client_channel_create_type) GetProcAddress(library, "grpc_lame_client_channel_create");
grpc_channel_destroy_import = (grpc_channel_destroy_type) GetProcAddress(library, "grpc_channel_destroy");
- grpc_channel_get_trace_import = (grpc_channel_get_trace_type) GetProcAddress(library, "grpc_channel_get_trace");
- grpc_channel_get_uuid_import = (grpc_channel_get_uuid_type) GetProcAddress(library, "grpc_channel_get_uuid");
grpc_call_cancel_import = (grpc_call_cancel_type) GetProcAddress(library, "grpc_call_cancel");
grpc_call_cancel_with_status_import = (grpc_call_cancel_with_status_type) GetProcAddress(library, "grpc_call_cancel_with_status");
grpc_call_ref_import = (grpc_call_ref_type) GetProcAddress(library, "grpc_call_ref");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index b2186a69aa..474405ae3f 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -179,12 +179,6 @@ extern grpc_lame_client_channel_create_type grpc_lame_client_channel_create_impo
typedef void(*grpc_channel_destroy_type)(grpc_channel* channel);
extern grpc_channel_destroy_type grpc_channel_destroy_import;
#define grpc_channel_destroy grpc_channel_destroy_import
-typedef char*(*grpc_channel_get_trace_type)(grpc_channel* channel);
-extern grpc_channel_get_trace_type grpc_channel_get_trace_import;
-#define grpc_channel_get_trace grpc_channel_get_trace_import
-typedef intptr_t(*grpc_channel_get_uuid_type)(grpc_channel* channel);
-extern grpc_channel_get_uuid_type grpc_channel_get_uuid_import;
-#define grpc_channel_get_uuid grpc_channel_get_uuid_import
typedef grpc_call_error(*grpc_call_cancel_type)(grpc_call* call, void* reserved);
extern grpc_call_cancel_type grpc_call_cancel_import;
#define grpc_call_cancel grpc_call_cancel_import
@@ -317,7 +311,7 @@ extern grpc_google_default_credentials_create_type grpc_google_default_credentia
typedef void(*grpc_set_ssl_roots_override_callback_type)(grpc_ssl_roots_override_callback cb);
extern grpc_set_ssl_roots_override_callback_type grpc_set_ssl_roots_override_callback_import;
#define grpc_set_ssl_roots_override_callback grpc_set_ssl_roots_override_callback_import
-typedef grpc_channel_credentials*(*grpc_ssl_credentials_create_type)(const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, void* reserved);
+typedef grpc_channel_credentials*(*grpc_ssl_credentials_create_type)(const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, const verify_peer_options* verify_options, void* reserved);
extern grpc_ssl_credentials_create_type grpc_ssl_credentials_create_import;
#define grpc_ssl_credentials_create grpc_ssl_credentials_create_import
typedef void(*grpc_call_credentials_release_type)(grpc_call_credentials* creds);
diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb
index 86240814bd..6e601bdc91 100644
--- a/src/ruby/lib/grpc/generic/active_call.rb
+++ b/src/ruby/lib/grpc/generic/active_call.rb
@@ -120,7 +120,7 @@ module GRPC
@send_initial_md_mutex.synchronize do
return if @metadata_sent
@metadata_to_send.merge!(new_metadata)
- @metadata_tag = ActiveCall.client_invoke(@call, @metadata_to_send)
+ ActiveCall.client_invoke(@call, @metadata_to_send)
@metadata_sent = true
end
end
diff --git a/src/ruby/spec/call_credentials_spec.rb b/src/ruby/spec/call_credentials_spec.rb
index 86f30b46f1..d949ba2235 100644
--- a/src/ruby/spec/call_credentials_spec.rb
+++ b/src/ruby/spec/call_credentials_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
describe GRPC::Core::CallCredentials do
CallCredentials = GRPC::Core::CallCredentials
diff --git a/src/ruby/spec/call_spec.rb b/src/ruby/spec/call_spec.rb
index 1cc0500242..22d345f658 100644
--- a/src/ruby/spec/call_spec.rb
+++ b/src/ruby/spec/call_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
include GRPC::Core::StatusCodes
diff --git a/src/ruby/spec/channel_credentials_spec.rb b/src/ruby/spec/channel_credentials_spec.rb
index e53f316208..b05e5aebf8 100644
--- a/src/ruby/spec/channel_credentials_spec.rb
+++ b/src/ruby/spec/channel_credentials_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
describe GRPC::Core::ChannelCredentials do
ChannelCredentials = GRPC::Core::ChannelCredentials
diff --git a/src/ruby/spec/channel_spec.rb b/src/ruby/spec/channel_spec.rb
index 5b2e355963..3c9eca47ec 100644
--- a/src/ruby/spec/channel_spec.rb
+++ b/src/ruby/spec/channel_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
def load_test_certs
test_root = File.join(File.dirname(__FILE__), 'testdata')
diff --git a/src/ruby/spec/client_auth_spec.rb b/src/ruby/spec/client_auth_spec.rb
index b955ad231e..c563ed3227 100644
--- a/src/ruby/spec/client_auth_spec.rb
+++ b/src/ruby/spec/client_auth_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
def create_channel_creds
test_root = File.join(File.dirname(__FILE__), 'testdata')
@@ -39,17 +39,6 @@ def create_server_creds
true) # force client auth
end
-# A test message
-class EchoMsg
- def self.marshal(_o)
- ''
- end
-
- def self.unmarshal(_o)
- EchoMsg.new
- end
-end
-
# a test service that checks the cert of its peer
class SslTestService
include GRPC::GenericService
diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb
index afbfb0bc43..afde5073a6 100644
--- a/src/ruby/spec/client_server_spec.rb
+++ b/src/ruby/spec/client_server_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
include GRPC::Core
diff --git a/src/ruby/spec/compression_options_spec.rb b/src/ruby/spec/compression_options_spec.rb
index 03c3cd9f07..05318e6686 100644
--- a/src/ruby/spec/compression_options_spec.rb
+++ b/src/ruby/spec/compression_options_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
describe GRPC::Core::CompressionOptions do
# Note these constants should be updated
diff --git a/src/ruby/spec/error_sanity_spec.rb b/src/ruby/spec/error_sanity_spec.rb
index b8f0638695..c36635ea26 100644
--- a/src/ruby/spec/error_sanity_spec.rb
+++ b/src/ruby/spec/error_sanity_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
StatusCodes = GRPC::Core::StatusCodes
diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb
index da50f8d0c9..3f878cc100 100644
--- a/src/ruby/spec/generic/client_stub_spec.rb
+++ b/src/ruby/spec/generic/client_stub_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
Thread.abort_on_exception = true
diff --git a/src/ruby/spec/generic/rpc_desc_spec.rb b/src/ruby/spec/generic/rpc_desc_spec.rb
index 6852b9804f..b4ffe5eb92 100644
--- a/src/ruby/spec/generic/rpc_desc_spec.rb
+++ b/src/ruby/spec/generic/rpc_desc_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
require 'grpc/generic/rpc_desc'
describe GRPC::RpcDesc do
diff --git a/src/ruby/spec/generic/rpc_server_pool_spec.rb b/src/ruby/spec/generic/rpc_server_pool_spec.rb
index 27a42c82c1..0f2dac272e 100644
--- a/src/ruby/spec/generic/rpc_server_pool_spec.rb
+++ b/src/ruby/spec/generic/rpc_server_pool_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
Thread.abort_on_exception = true
diff --git a/src/ruby/spec/generic/service_spec.rb b/src/ruby/spec/generic/service_spec.rb
index ad1c268d32..57aec89ce5 100644
--- a/src/ruby/spec/generic/service_spec.rb
+++ b/src/ruby/spec/generic/service_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
require 'grpc/generic/rpc_desc'
require 'grpc/generic/service'
diff --git a/src/ruby/spec/google_rpc_status_utils_spec.rb b/src/ruby/spec/google_rpc_status_utils_spec.rb
index 3263589b6a..740c3794b6 100644
--- a/src/ruby/spec/google_rpc_status_utils_spec.rb
+++ b/src/ruby/spec/google_rpc_status_utils_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
require_relative '../lib/grpc/google_rpc_status_utils'
require_relative '../pb/src/proto/grpc/testing/messages_pb'
require_relative '../pb/src/proto/grpc/testing/messages_pb'
@@ -114,17 +114,6 @@ describe 'conversion from a status struct to a google protobuf status' do
end
end
-# Test message
-class EchoMsg
- def self.marshal(_o)
- ''
- end
-
- def self.unmarshal(_o)
- EchoMsg.new
- end
-end
-
# A test service that fills in the "reserved" grpc-status-details-bin trailer,
# for client-side testing of GoogleRpcStatus protobuf extraction from trailers.
class GoogleRpcStatusTestService
diff --git a/src/ruby/spec/pb/duplicate/codegen_spec.rb b/src/ruby/spec/pb/duplicate/codegen_spec.rb
index 9f82858d15..fed7c1c8be 100644
--- a/src/ruby/spec/pb/duplicate/codegen_spec.rb
+++ b/src/ruby/spec/pb/duplicate/codegen_spec.rb
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+require 'spec_helper'
require 'open3'
require 'tmpdir'
diff --git a/src/ruby/spec/pb/health/checker_spec.rb b/src/ruby/spec/pb/health/checker_spec.rb
index 58a602327c..84e63c2e54 100644
--- a/src/ruby/spec/pb/health/checker_spec.rb
+++ b/src/ruby/spec/pb/health/checker_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
require 'grpc/health/v1/health_pb'
require 'grpc/health/checker'
require 'open3'
diff --git a/src/ruby/spec/pb/package_with_underscore/checker_spec.rb b/src/ruby/spec/pb/package_with_underscore/checker_spec.rb
deleted file mode 100644
index dac7c14a9a..0000000000
--- a/src/ruby/spec/pb/package_with_underscore/checker_spec.rb
+++ /dev/null
@@ -1,51 +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.
-
-require 'open3'
-require 'tmpdir'
-
-describe 'Package with underscore protobuf code generation' do
- it 'should have the same content as created by code generation' do
- root_dir = File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..')
- pb_dir = File.join(root_dir, 'src', 'ruby', 'spec', 'pb')
-
- fail 'CONFIG env variable unexpectedly unset' unless ENV['CONFIG']
- bins_sub_dir = ENV['CONFIG']
- bins_dir = File.join(root_dir, 'bins', bins_sub_dir)
-
- plugin = File.join(bins_dir, 'grpc_ruby_plugin')
- protoc = File.join(bins_dir, 'protobuf', 'protoc')
-
- got = nil
-
- Dir.mktmpdir do |tmp_dir|
- gen_out = File.join(tmp_dir, 'package_with_underscore', 'service_services_pb.rb')
-
- pid = spawn(
- protoc,
- '-I.',
- 'package_with_underscore/service.proto',
- "--grpc_out=#{tmp_dir}",
- "--plugin=protoc-gen-grpc=#{plugin}",
- chdir: pb_dir)
- Process.waitpid2(pid)
- File.open(gen_out) { |f| got = f.read }
- end
-
- correct_modularized_rpc = 'rpc :TestOne, ' \
- 'Grpc::Testing::PackageWithUnderscore::Data::Request, ' \
- 'Grpc::Testing::PackageWithUnderscore::Data::Response'
- expect(got).to include(correct_modularized_rpc)
- end
-end
diff --git a/src/ruby/spec/server_credentials_spec.rb b/src/ruby/spec/server_credentials_spec.rb
index 673d832f62..f773a5f701 100644
--- a/src/ruby/spec/server_credentials_spec.rb
+++ b/src/ruby/spec/server_credentials_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
def load_test_certs
test_root = File.join(File.dirname(__FILE__), 'testdata')
diff --git a/src/ruby/spec/server_spec.rb b/src/ruby/spec/server_spec.rb
index 6eaac5ded1..76038d8b8b 100644
--- a/src/ruby/spec/server_spec.rb
+++ b/src/ruby/spec/server_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
def load_test_certs
test_root = File.join(File.dirname(__FILE__), 'testdata')
diff --git a/src/ruby/spec/spec_helper.rb b/src/ruby/spec/spec_helper.rb
index 8fe9e6e808..8fe2c16b35 100644
--- a/src/ruby/spec/spec_helper.rb
+++ b/src/ruby/spec/spec_helper.rb
@@ -31,6 +31,7 @@ end if ENV['COVERAGE_NAME']
require 'rspec'
require 'logging'
require 'rspec/logging_helper'
+require 'grpc'
require_relative 'support/services'
require_relative 'support/helpers'
diff --git a/src/ruby/spec/support/services.rb b/src/ruby/spec/support/services.rb
index 27cc8e61ac..27239cd66c 100644
--- a/src/ruby/spec/support/services.rb
+++ b/src/ruby/spec/support/services.rb
@@ -13,7 +13,7 @@
# limitations under the License.
# Test stubs for various scenarios
-require 'grpc'
+require 'spec_helper'
# A test message
class EchoMsg
diff --git a/src/ruby/spec/time_consts_spec.rb b/src/ruby/spec/time_consts_spec.rb
index f7afe6b70a..41655ab106 100644
--- a/src/ruby/spec/time_consts_spec.rb
+++ b/src/ruby/spec/time_consts_spec.rb
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'grpc'
+require 'spec_helper'
TimeConsts = GRPC::Core::TimeConsts
diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template
index a7f59e15a7..de13d02e2a 100644
--- a/templates/CMakeLists.txt.template
+++ b/templates/CMakeLists.txt.template
@@ -87,6 +87,7 @@
# Options
option(gRPC_BUILD_TESTS "Build tests" OFF)
option(gRPC_BUILD_CODEGEN "Build codegen" ON)
+ option(gRPC_BUILD_CSHARP_EXT "Build C# extensions" ON)
set(gRPC_INSTALL_default ON)
if (NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
@@ -298,6 +299,11 @@
if (gRPC_BUILD_TESTS)
${cc_library(lib)}
endif (gRPC_BUILD_TESTS)
+ % elif lib.name in ['grpc_csharp_ext']:
+ if (gRPC_BUILD_CSHARP_EXT)
+ ${cc_library(lib)}
+ ${cc_install(lib)}
+ endif (gRPC_BUILD_CSHARP_EXT)
% else:
${cc_library(lib)}
% if not lib.build in ["tool"]:
diff --git a/templates/config.m4.template b/templates/config.m4.template
index cc19d98375..19f9904911 100644
--- a/templates/config.m4.template
+++ b/templates/config.m4.template
@@ -11,11 +11,12 @@
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)
diff --git a/templates/config.w32.template b/templates/config.w32.template
index ef25e55596..5e37cf568c 100644
--- a/templates/config.w32.template
+++ b/templates/config.w32.template
@@ -23,13 +23,14 @@
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");
<%
dirs = {}
for lib in libs:
diff --git a/test/core/bad_ssl/bad_ssl_test.cc b/test/core/bad_ssl/bad_ssl_test.cc
index e2ea7540ef..73d251eff4 100644
--- a/test/core/bad_ssl/bad_ssl_test.cc
+++ b/test/core/bad_ssl/bad_ssl_test.cc
@@ -37,7 +37,7 @@ static void* tag(intptr_t t) { return (void*)t; }
static void run_test(const char* target, size_t nops) {
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
+ grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
grpc_channel* channel;
grpc_call* c;
diff --git a/test/core/channel/BUILD b/test/core/channel/BUILD
index c554b20148..da419f00cf 100644
--- a/test/core/channel/BUILD
+++ b/test/core/channel/BUILD
@@ -84,6 +84,23 @@ grpc_cc_test(
)
grpc_cc_test(
+ name = "channelz_test",
+ srcs = ["channelz_test.cc"],
+ language = "C++",
+ deps = [
+ "//:gpr",
+ "//:grpc",
+ "//:grpc++",
+ "//test/core/util:gpr_test_util",
+ "//test/core/util:grpc_test_util",
+ "//test/cpp/util:channel_trace_proto_helper",
+ ],
+ external_deps = [
+ "gtest",
+ ],
+)
+
+grpc_cc_test(
name = "channelz_registry_test",
srcs = ["channelz_registry_test.cc"],
language = "C++",
@@ -105,6 +122,7 @@ grpc_cc_test(
language = "C++",
deps = [
"//:grpc",
+ "//test/core/util:gpr_test_util",
],
external_deps = [
"gtest",
diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc
index d99a32d91d..bbddee3f14 100644
--- a/test/core/channel/channel_trace_test.cc
+++ b/test/core/channel/channel_trace_test.cc
@@ -25,6 +25,7 @@
#include <grpc/support/log.h>
#include "src/core/lib/channel/channel_trace.h"
+#include "src/core/lib/channel/channelz.h"
#include "src/core/lib/channel/channelz_registry.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/exec_ctx.h"
@@ -39,6 +40,7 @@
#include <string.h>
namespace grpc_core {
+namespace channelz {
namespace testing {
namespace {
@@ -69,7 +71,7 @@ void ValidateChannelTraceData(grpc_json* json,
ASSERT_NE(json, nullptr);
grpc_json* num_events_logged_json = GetJsonChild(json, "numEventsLogged");
ASSERT_NE(num_events_logged_json, nullptr);
- grpc_json* start_time = GetJsonChild(json, "creationTime");
+ grpc_json* start_time = GetJsonChild(json, "creationTimestamp");
ASSERT_NE(start_time, nullptr);
size_t num_events_logged =
(size_t)strtol(num_events_logged_json->value, nullptr, 0);
@@ -77,35 +79,47 @@ void ValidateChannelTraceData(grpc_json* json,
ValidateJsonArraySize(json, "events", actual_num_events_expected);
}
-void AddSimpleTrace(const RefCountedPtr<ChannelTrace>& tracer) {
+void AddSimpleTrace(ChannelTrace* tracer) {
tracer->AddTraceEvent(ChannelTrace::Severity::Info,
grpc_slice_from_static_string("simple trace"));
}
// checks for the existence of all the required members of the tracer.
-void ValidateChannelTrace(const RefCountedPtr<ChannelTrace>& tracer,
+void ValidateChannelTrace(ChannelTrace* tracer,
size_t expected_num_event_logged, size_t max_nodes) {
if (!max_nodes) return;
- char* json_str = tracer->RenderTrace();
+ grpc_json* json = tracer->RenderJSON();
+ EXPECT_NE(json, nullptr);
+ char* json_str = grpc_json_dump_to_string(json, 0);
+ grpc_json_destroy(json);
grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str);
- grpc_json* json = grpc_json_parse_string(json_str);
- ValidateChannelTraceData(json, expected_num_event_logged,
+ grpc_json* parsed_json = grpc_json_parse_string(json_str);
+ ValidateChannelTraceData(parsed_json, expected_num_event_logged,
GPR_MIN(expected_num_event_logged, max_nodes));
- grpc_json_destroy(json);
+ grpc_json_destroy(parsed_json);
gpr_free(json_str);
}
-void ValidateTraceDataMatchedUuidLookup(
- const RefCountedPtr<ChannelTrace>& tracer) {
- intptr_t uuid = tracer->GetUuid();
- if (uuid == -1) return; // Doesn't make sense to lookup if tracing disabled
- char* tracer_json_str = tracer->RenderTrace();
- ChannelTrace* uuid_lookup = ChannelzRegistry::Get<ChannelTrace>(uuid);
- char* uuid_lookup_json_str = uuid_lookup->RenderTrace();
- EXPECT_EQ(strcmp(tracer_json_str, uuid_lookup_json_str), 0);
- gpr_free(tracer_json_str);
- gpr_free(uuid_lookup_json_str);
-}
+class ChannelFixture {
+ public:
+ ChannelFixture(int max_trace_nodes) {
+ grpc_arg client_a;
+ client_a.type = GRPC_ARG_INTEGER;
+ client_a.key =
+ const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE);
+ client_a.value.integer = max_trace_nodes;
+ grpc_channel_args client_args = {1, &client_a};
+ channel_ =
+ grpc_insecure_channel_create("fake_target", &client_args, nullptr);
+ }
+
+ ~ChannelFixture() { grpc_channel_destroy(channel_); }
+
+ grpc_channel* channel() { return channel_; }
+
+ private:
+ grpc_channel* channel_;
+};
} // anonymous namespace
@@ -115,25 +129,22 @@ class ChannelTracerTest : public ::testing::TestWithParam<size_t> {};
// lookups by uuid.
TEST_P(ChannelTracerTest, BasicTest) {
grpc_core::ExecCtx exec_ctx;
- RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateTraceDataMatchedUuidLookup(tracer);
- tracer->AddTraceEvent(ChannelTrace::Severity::Info,
- grpc_slice_from_static_string("trace three"));
- tracer->AddTraceEvent(ChannelTrace::Severity::Error,
- grpc_slice_from_static_string("trace four error"));
- ValidateChannelTrace(tracer, 4, GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateChannelTrace(tracer, 6, GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateChannelTrace(tracer, 10, GetParam());
- ValidateTraceDataMatchedUuidLookup(tracer);
- tracer.reset(nullptr);
+ ChannelTrace tracer(GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ tracer.AddTraceEvent(ChannelTrace::Severity::Info,
+ grpc_slice_from_static_string("trace three"));
+ tracer.AddTraceEvent(ChannelTrace::Severity::Error,
+ grpc_slice_from_static_string("trace four error"));
+ ValidateChannelTrace(&tracer, 4, GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ ValidateChannelTrace(&tracer, 6, GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ ValidateChannelTrace(&tracer, 10, GetParam());
}
// Tests more complex functionality, like a parent channel tracking
@@ -141,42 +152,43 @@ TEST_P(ChannelTracerTest, BasicTest) {
// and this function will both hold refs to the subchannel.
TEST_P(ChannelTracerTest, ComplexTest) {
grpc_core::ExecCtx exec_ctx;
- RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- RefCountedPtr<ChannelTrace> sc1 = MakeRefCounted<ChannelTrace>(GetParam());
- tracer->AddTraceEventReferencingSubchannel(
+ ChannelTrace tracer(GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ ChannelFixture channel1(GetParam());
+ RefCountedPtr<ChannelNode> sc1 =
+ MakeRefCounted<ChannelNode>(channel1.channel(), GetParam());
+ tracer.AddTraceEventReferencingSubchannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel one created"), sc1);
- ValidateChannelTrace(tracer, 3, GetParam());
- AddSimpleTrace(sc1);
- AddSimpleTrace(sc1);
- AddSimpleTrace(sc1);
- ValidateChannelTrace(sc1, 3, GetParam());
- AddSimpleTrace(sc1);
- AddSimpleTrace(sc1);
- AddSimpleTrace(sc1);
- ValidateChannelTrace(sc1, 6, GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateChannelTrace(tracer, 5, GetParam());
- ValidateTraceDataMatchedUuidLookup(tracer);
- RefCountedPtr<ChannelTrace> sc2 = MakeRefCounted<ChannelTrace>(GetParam());
- tracer->AddTraceEventReferencingChannel(
+ ValidateChannelTrace(&tracer, 3, GetParam());
+ AddSimpleTrace(sc1->trace());
+ AddSimpleTrace(sc1->trace());
+ AddSimpleTrace(sc1->trace());
+ ValidateChannelTrace(sc1->trace(), 3, GetParam());
+ AddSimpleTrace(sc1->trace());
+ AddSimpleTrace(sc1->trace());
+ AddSimpleTrace(sc1->trace());
+ ValidateChannelTrace(sc1->trace(), 6, GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ ValidateChannelTrace(&tracer, 5, GetParam());
+ ChannelFixture channel2(GetParam());
+ RefCountedPtr<ChannelNode> sc2 =
+ MakeRefCounted<ChannelNode>(channel2.channel(), GetParam());
+ tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("LB channel two created"), sc2);
- tracer->AddTraceEventReferencingSubchannel(
+ tracer.AddTraceEventReferencingSubchannel(
ChannelTrace::Severity::Warning,
grpc_slice_from_static_string("subchannel one inactive"), sc1);
- ValidateChannelTrace(tracer, 7, GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateTraceDataMatchedUuidLookup(tracer);
- tracer.reset(nullptr);
+ ValidateChannelTrace(&tracer, 7, GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
sc1.reset(nullptr);
sc2.reset(nullptr);
}
@@ -186,39 +198,44 @@ TEST_P(ChannelTracerTest, ComplexTest) {
// gets deleted.
TEST_P(ChannelTracerTest, TestNesting) {
grpc_core::ExecCtx exec_ctx;
- RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam());
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateChannelTrace(tracer, 2, GetParam());
- RefCountedPtr<ChannelTrace> sc1 = MakeRefCounted<ChannelTrace>(GetParam());
- tracer->AddTraceEventReferencingChannel(
+ ChannelTrace tracer(GetParam());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ ValidateChannelTrace(&tracer, 2, GetParam());
+ ChannelFixture channel1(GetParam());
+ RefCountedPtr<ChannelNode> sc1 =
+ MakeRefCounted<ChannelNode>(channel1.channel(), GetParam());
+ tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel one created"), sc1);
- ValidateChannelTrace(tracer, 3, GetParam());
- AddSimpleTrace(sc1);
- RefCountedPtr<ChannelTrace> conn1 = MakeRefCounted<ChannelTrace>(GetParam());
+ ValidateChannelTrace(&tracer, 3, GetParam());
+ AddSimpleTrace(sc1->trace());
+ ChannelFixture channel2(GetParam());
+ RefCountedPtr<ChannelNode> conn1 =
+ MakeRefCounted<ChannelNode>(channel2.channel(), GetParam());
// nesting one level deeper.
- sc1->AddTraceEventReferencingSubchannel(
+ sc1->trace()->AddTraceEventReferencingSubchannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("connection one created"), conn1);
- ValidateChannelTrace(tracer, 3, GetParam());
- AddSimpleTrace(conn1);
- AddSimpleTrace(tracer);
- AddSimpleTrace(tracer);
- ValidateChannelTrace(tracer, 5, GetParam());
- ValidateChannelTrace(conn1, 1, GetParam());
- RefCountedPtr<ChannelTrace> sc2 = MakeRefCounted<ChannelTrace>(GetParam());
- tracer->AddTraceEventReferencingSubchannel(
+ ValidateChannelTrace(&tracer, 3, GetParam());
+ AddSimpleTrace(conn1->trace());
+ AddSimpleTrace(&tracer);
+ AddSimpleTrace(&tracer);
+ ValidateChannelTrace(&tracer, 5, GetParam());
+ ValidateChannelTrace(conn1->trace(), 1, GetParam());
+ ChannelFixture channel3(GetParam());
+ RefCountedPtr<ChannelNode> sc2 =
+ MakeRefCounted<ChannelNode>(channel3.channel(), GetParam());
+ tracer.AddTraceEventReferencingSubchannel(
ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel two created"), sc2);
// this trace should not get added to the parents children since it is already
// present in the tracer.
- tracer->AddTraceEventReferencingChannel(
+ tracer.AddTraceEventReferencingChannel(
ChannelTrace::Severity::Warning,
grpc_slice_from_static_string("subchannel one inactive"), sc1);
- AddSimpleTrace(tracer);
- ValidateChannelTrace(tracer, 8, GetParam());
- tracer.reset(nullptr);
+ AddSimpleTrace(&tracer);
+ ValidateChannelTrace(&tracer, 8, GetParam());
sc1.reset(nullptr);
sc2.reset(nullptr);
conn1.reset(nullptr);
@@ -228,6 +245,7 @@ INSTANTIATE_TEST_CASE_P(ChannelTracerTestSweep, ChannelTracerTest,
::testing::Values(0, 1, 2, 6, 10, 15));
} // namespace testing
+} // namespace channelz
} // namespace grpc_core
int main(int argc, char** argv) {
diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc
new file mode 100644
index 0000000000..058eea914c
--- /dev/null
+++ b/test/core/channel/channelz_test.cc
@@ -0,0 +1,216 @@
+/*
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <gtest/gtest.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/lib/channel/channel_trace.h"
+#include "src/core/lib/channel/channelz.h"
+#include "src/core/lib/channel/channelz_registry.h"
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/json/json.h"
+#include "src/core/lib/surface/channel.h"
+
+#include "test/core/util/test_config.h"
+#include "test/cpp/util/channel_trace_proto_helper.h"
+
+#include <grpc/support/string_util.h>
+#include <stdlib.h>
+#include <string.h>
+
+namespace grpc_core {
+namespace channelz {
+namespace testing {
+
+// testing peer to access channel internals
+class ChannelNodePeer {
+ public:
+ ChannelNodePeer(ChannelNode* channel) : channel_(channel) {}
+ grpc_millis last_call_started_millis() {
+ return (grpc_millis)gpr_atm_no_barrier_load(
+ &channel_->last_call_started_millis_);
+ }
+
+ private:
+ ChannelNode* channel_;
+};
+
+namespace {
+
+grpc_json* GetJsonChild(grpc_json* parent, const char* key) {
+ EXPECT_NE(parent, nullptr);
+ for (grpc_json* child = parent->child; child != nullptr;
+ child = child->next) {
+ if (child->key != nullptr && strcmp(child->key, key) == 0) return child;
+ }
+ return nullptr;
+}
+
+class ChannelFixture {
+ public:
+ ChannelFixture(int max_trace_nodes) {
+ grpc_arg client_a[2];
+ client_a[0].type = GRPC_ARG_INTEGER;
+ client_a[0].key =
+ const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE);
+ client_a[0].value.integer = max_trace_nodes;
+ client_a[1].type = GRPC_ARG_INTEGER;
+ client_a[1].key = const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ);
+ client_a[1].value.integer = true;
+ grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
+ channel_ =
+ grpc_insecure_channel_create("fake_target", &client_args, nullptr);
+ }
+
+ ~ChannelFixture() { grpc_channel_destroy(channel_); }
+
+ grpc_channel* channel() { return channel_; }
+
+ private:
+ grpc_channel* channel_;
+};
+
+struct validate_channel_data_args {
+ int64_t calls_started;
+ int64_t calls_failed;
+ int64_t calls_succeeded;
+};
+
+void ValidateChildInteger(grpc_json* json, int64_t expect, const char* key) {
+ grpc_json* gotten_json = GetJsonChild(json, key);
+ ASSERT_NE(gotten_json, nullptr);
+ int64_t gotten_number = (int64_t)strtol(gotten_json->value, nullptr, 0);
+ EXPECT_EQ(gotten_number, expect);
+}
+
+void ValidateCounters(char* json_str, validate_channel_data_args args) {
+ grpc_json* json = grpc_json_parse_string(json_str);
+ ASSERT_NE(json, nullptr);
+ grpc_json* data = GetJsonChild(json, "data");
+ ValidateChildInteger(data, args.calls_started, "callsStarted");
+ ValidateChildInteger(data, args.calls_failed, "callsFailed");
+ ValidateChildInteger(data, args.calls_succeeded, "callsSucceeded");
+ grpc_json_destroy(json);
+}
+
+void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) {
+ char* json_str = channel->RenderJSON();
+ grpc::testing::ValidateChannelProtoJsonTranslation(json_str);
+ ValidateCounters(json_str, args);
+ gpr_free(json_str);
+}
+
+grpc_millis GetLastCallStartedMillis(ChannelNode* channel) {
+ ChannelNodePeer peer(channel);
+ return peer.last_call_started_millis();
+}
+
+void ChannelzSleep(int64_t sleep_us) {
+ gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_micros(sleep_us, GPR_TIMESPAN)));
+ grpc_core::ExecCtx::Get()->InvalidateNow();
+}
+
+} // anonymous namespace
+
+class ChannelzChannelTest : public ::testing::TestWithParam<size_t> {};
+
+TEST_P(ChannelzChannelTest, BasicChannel) {
+ grpc_core::ExecCtx exec_ctx;
+ ChannelFixture channel(GetParam());
+ ChannelNode* channelz_channel =
+ grpc_channel_get_channelz_node(channel.channel());
+ char* json_str = channelz_channel->RenderJSON();
+ ValidateCounters(json_str, {0, 0, 0});
+ gpr_free(json_str);
+}
+
+TEST(ChannelzChannelTest, ChannelzDisabled) {
+ grpc_core::ExecCtx exec_ctx;
+ grpc_channel* channel =
+ grpc_insecure_channel_create("fake_target", nullptr, nullptr);
+ ChannelNode* channelz_channel = grpc_channel_get_channelz_node(channel);
+ ASSERT_EQ(channelz_channel, nullptr);
+ grpc_channel_destroy(channel);
+}
+
+TEST_P(ChannelzChannelTest, BasicChannelAPIFunctionality) {
+ grpc_core::ExecCtx exec_ctx;
+ ChannelFixture channel(GetParam());
+ ChannelNode* channelz_channel =
+ grpc_channel_get_channelz_node(channel.channel());
+ channelz_channel->RecordCallStarted();
+ channelz_channel->RecordCallFailed();
+ channelz_channel->RecordCallSucceeded();
+ ValidateChannel(channelz_channel, {1, 1, 1});
+ channelz_channel->RecordCallStarted();
+ channelz_channel->RecordCallFailed();
+ channelz_channel->RecordCallSucceeded();
+ channelz_channel->RecordCallStarted();
+ channelz_channel->RecordCallFailed();
+ channelz_channel->RecordCallSucceeded();
+ ValidateChannel(channelz_channel, {3, 3, 3});
+}
+
+TEST_P(ChannelzChannelTest, LastCallStartedMillis) {
+ grpc_core::ExecCtx exec_ctx;
+ ChannelFixture channel(GetParam());
+ ChannelNode* channelz_channel =
+ grpc_channel_get_channelz_node(channel.channel());
+ // start a call to set the last call started timestamp
+ channelz_channel->RecordCallStarted();
+ grpc_millis millis1 = GetLastCallStartedMillis(channelz_channel);
+ // time gone by should not affect the timestamp
+ ChannelzSleep(100);
+ grpc_millis millis2 = GetLastCallStartedMillis(channelz_channel);
+ EXPECT_EQ(millis1, millis2);
+ // calls succeeded or failed should not affect the timestamp
+ ChannelzSleep(100);
+ channelz_channel->RecordCallFailed();
+ channelz_channel->RecordCallSucceeded();
+ grpc_millis millis3 = GetLastCallStartedMillis(channelz_channel);
+ EXPECT_EQ(millis1, millis3);
+ // another call started should affect the timestamp
+ // sleep for extra long to avoid flakes (since we cache Now())
+ ChannelzSleep(5000);
+ channelz_channel->RecordCallStarted();
+ grpc_millis millis4 = GetLastCallStartedMillis(channelz_channel);
+ EXPECT_NE(millis1, millis4);
+}
+
+INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest,
+ ::testing::Values(0, 1, 2, 6, 10, 15));
+
+} // namespace testing
+} // namespace channelz
+} // namespace grpc_core
+
+int main(int argc, char** argv) {
+ grpc_test_init(argc, argv);
+ grpc_init();
+ ::testing::InitGoogleTest(&argc, argv);
+ int ret = RUN_ALL_TESTS();
+ grpc_shutdown();
+ return ret;
+}
diff --git a/test/core/end2end/end2end_nosec_tests.cc b/test/core/end2end/end2end_nosec_tests.cc
index a70128254a..061b23b5d6 100644
--- a/test/core/end2end/end2end_nosec_tests.cc
+++ b/test/core/end2end/end2end_nosec_tests.cc
@@ -54,6 +54,8 @@ extern void cancel_in_a_vacuum(grpc_end2end_test_config config);
extern void cancel_in_a_vacuum_pre_init(void);
extern void cancel_with_status(grpc_end2end_test_config config);
extern void cancel_with_status_pre_init(void);
+extern void channelz(grpc_end2end_test_config config);
+extern void channelz_pre_init(void);
extern void compressed_payload(grpc_end2end_test_config config);
extern void compressed_payload_pre_init(void);
extern void connectivity(grpc_end2end_test_config config);
@@ -201,6 +203,7 @@ void grpc_end2end_tests_pre_init(void) {
cancel_before_invoke_pre_init();
cancel_in_a_vacuum_pre_init();
cancel_with_status_pre_init();
+ channelz_pre_init();
compressed_payload_pre_init();
connectivity_pre_init();
default_host_pre_init();
@@ -287,6 +290,7 @@ void grpc_end2end_tests(int argc, char **argv,
cancel_before_invoke(config);
cancel_in_a_vacuum(config);
cancel_with_status(config);
+ channelz(config);
compressed_payload(config);
connectivity(config);
default_host(config);
@@ -404,6 +408,10 @@ void grpc_end2end_tests(int argc, char **argv,
cancel_with_status(config);
continue;
}
+ if (0 == strcmp("channelz", argv[i])) {
+ channelz(config);
+ continue;
+ }
if (0 == strcmp("compressed_payload", argv[i])) {
compressed_payload(config);
continue;
diff --git a/test/core/end2end/end2end_tests.cc b/test/core/end2end/end2end_tests.cc
index bf75dd4579..7ae475cdef 100644
--- a/test/core/end2end/end2end_tests.cc
+++ b/test/core/end2end/end2end_tests.cc
@@ -56,6 +56,8 @@ extern void cancel_in_a_vacuum(grpc_end2end_test_config config);
extern void cancel_in_a_vacuum_pre_init(void);
extern void cancel_with_status(grpc_end2end_test_config config);
extern void cancel_with_status_pre_init(void);
+extern void channelz(grpc_end2end_test_config config);
+extern void channelz_pre_init(void);
extern void compressed_payload(grpc_end2end_test_config config);
extern void compressed_payload_pre_init(void);
extern void connectivity(grpc_end2end_test_config config);
@@ -204,6 +206,7 @@ void grpc_end2end_tests_pre_init(void) {
cancel_before_invoke_pre_init();
cancel_in_a_vacuum_pre_init();
cancel_with_status_pre_init();
+ channelz_pre_init();
compressed_payload_pre_init();
connectivity_pre_init();
default_host_pre_init();
@@ -291,6 +294,7 @@ void grpc_end2end_tests(int argc, char **argv,
cancel_before_invoke(config);
cancel_in_a_vacuum(config);
cancel_with_status(config);
+ channelz(config);
compressed_payload(config);
connectivity(config);
default_host(config);
@@ -412,6 +416,10 @@ void grpc_end2end_tests(int argc, char **argv,
cancel_with_status(config);
continue;
}
+ if (0 == strcmp("channelz", argv[i])) {
+ channelz(config);
+ continue;
+ }
if (0 == strcmp("compressed_payload", argv[i])) {
compressed_payload(config);
continue;
diff --git a/test/core/end2end/fixtures/h2_oauth2.cc b/test/core/end2end/fixtures/h2_oauth2.cc
index d44aafd50a..37397d6450 100644
--- a/test/core/end2end/fixtures/h2_oauth2.cc
+++ b/test/core/end2end/fixtures/h2_oauth2.cc
@@ -146,7 +146,7 @@ static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack(
grpc_end2end_test_fixture* f, grpc_channel_args* client_args) {
grpc_core::ExecCtx exec_ctx;
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr);
+ grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr, nullptr);
grpc_call_credentials* oauth2_creds = grpc_md_only_test_credentials_create(
"authorization", oauth2_md, true /* is_async */);
grpc_channel_credentials* ssl_oauth2_creds =
diff --git a/test/core/end2end/fixtures/h2_ssl.cc b/test/core/end2end/fixtures/h2_ssl.cc
index 999cd4cdfb..4d6c815716 100644
--- a/test/core/end2end/fixtures/h2_ssl.cc
+++ b/test/core/end2end/fixtures/h2_ssl.cc
@@ -101,7 +101,7 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture* f) {
static void chttp2_init_client_simple_ssl_secure_fullstack(
grpc_end2end_test_fixture* f, grpc_channel_args* client_args) {
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
+ grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
grpc_arg ssl_name_override = {
GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.cc b/test/core/end2end/fixtures/h2_ssl_proxy.cc
index 9ab50c6217..09cbf974b6 100644
--- a/test/core/end2end/fixtures/h2_ssl_proxy.cc
+++ b/test/core/end2end/fixtures/h2_ssl_proxy.cc
@@ -55,7 +55,7 @@ static grpc_channel* create_proxy_client(const char* target,
grpc_channel_args* client_args) {
grpc_channel* channel;
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
+ grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
grpc_arg ssl_name_override = {
GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
@@ -138,7 +138,7 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture* f) {
static void chttp2_init_client_simple_ssl_secure_fullstack(
grpc_end2end_test_fixture* f, grpc_channel_args* client_args) {
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
+ grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr);
grpc_arg ssl_name_override = {
GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
diff --git a/test/core/end2end/fuzzers/api_fuzzer.cc b/test/core/end2end/fuzzers/api_fuzzer.cc
index ccb194cdf5..eacfd4a8c3 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.cc
+++ b/test/core/end2end/fuzzers/api_fuzzer.cc
@@ -222,7 +222,7 @@ static grpc_channel_credentials* read_ssl_channel_creds(input_stream* inp) {
grpc_channel_credentials* creds = grpc_ssl_credentials_create(
root_certs,
private_key != nullptr && certs != nullptr ? &key_cert_pair : nullptr,
- nullptr);
+ nullptr, nullptr);
cred_artifact_ctx_finish(&ctx);
return creds;
}
@@ -1046,6 +1046,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
op->reserved = nullptr;
op->flags = grpc_fuzzer_get_next_uint32(&inp);
}
+ if (g_channel == nullptr) ok = false;
if (ok) {
validator* v = make_finished_batch_validator(g_active_call, has_ops);
g_active_call->pending_ops++;
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index 1851214191..04dc2a8785 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -106,6 +106,7 @@ END2END_TESTS = {
needs_compression=True),
'connectivity': connectivity_test_options._replace(needs_names=True,
proxyable=False, cpu_cost=LOWCPU, exclude_iomgrs=['uv']),
+ 'channelz': default_test_options,
'default_host': default_test_options._replace(
needs_fullstack=True, needs_dns=True, needs_names=True),
'call_host_override': default_test_options._replace(
diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl
index 706f4fa86d..67769a8cb1 100755
--- a/test/core/end2end/generate_tests.bzl
+++ b/test/core/end2end/generate_tests.bzl
@@ -113,6 +113,7 @@ END2END_TESTS = {
'compressed_payload': test_options(proxyable=False, exclude_inproc=True),
'connectivity': test_options(needs_fullstack=True, needs_names=True,
proxyable=False),
+ 'channelz': test_options(),
'default_host': test_options(needs_fullstack=True, needs_dns=True,
needs_names=True),
'disappearing_server': test_options(needs_fullstack=True,needs_names=True),
diff --git a/test/core/end2end/h2_ssl_cert_test.cc b/test/core/end2end/h2_ssl_cert_test.cc
index 9ed6f23798..2c5ee3b156 100644
--- a/test/core/end2end/h2_ssl_cert_test.cc
+++ b/test/core/end2end/h2_ssl_cert_test.cc
@@ -169,8 +169,8 @@ typedef enum { NONE, SELF_SIGNED, SIGNED, BAD_CERT_PAIR } certtype;
default: \
break; \
} \
- ssl_creds = \
- grpc_ssl_credentials_create(test_root_cert, key_cert_pair, NULL); \
+ ssl_creds = grpc_ssl_credentials_create(test_root_cert, key_cert_pair, \
+ NULL, NULL); \
grpc_arg ssl_name_override = { \
GRPC_ARG_STRING, \
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), \
diff --git a/test/core/end2end/h2_ssl_session_reuse_test.cc b/test/core/end2end/h2_ssl_session_reuse_test.cc
index d5984be93f..b2f398625a 100644
--- a/test/core/end2end/h2_ssl_session_reuse_test.cc
+++ b/test/core/end2end/h2_ssl_session_reuse_test.cc
@@ -66,7 +66,7 @@ grpc_channel* client_create(char* server_addr, grpc_ssl_session_cache* cache) {
grpc_ssl_pem_key_cert_pair signed_client_key_cert_pair = {
test_signed_client_key, test_signed_client_cert};
grpc_channel_credentials* client_creds = grpc_ssl_credentials_create(
- test_root_cert, &signed_client_key_cert_pair, nullptr);
+ test_root_cert, &signed_client_key_cert_pair, nullptr, nullptr);
grpc_arg args[] = {
grpc_channel_arg_string_create(
diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc
new file mode 100644
index 0000000000..eb052119ca
--- /dev/null
+++ b/test/core/end2end/tests/channelz.cc
@@ -0,0 +1,299 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "test/core/end2end/end2end_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "src/core/lib/surface/channel.h"
+
+#include <grpc/byte_buffer.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+#include "src/core/lib/gpr/string.h"
+#include "test/core/end2end/cq_verifier.h"
+
+static void* tag(intptr_t t) { return (void*)t; }
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+ const char* test_name,
+ grpc_channel_args* client_args,
+ grpc_channel_args* server_args) {
+ grpc_end2end_test_fixture f;
+ gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
+ f = config.create_fixture(client_args, server_args);
+ config.init_server(&f, server_args);
+ config.init_client(&f, client_args);
+ return f;
+}
+
+static gpr_timespec n_seconds_from_now(int n) {
+ return grpc_timeout_seconds_to_deadline(n);
+}
+
+static gpr_timespec five_seconds_from_now(void) {
+ return n_seconds_from_now(5);
+}
+
+static void drain_cq(grpc_completion_queue* cq) {
+ grpc_event ev;
+ do {
+ ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr);
+ } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+}
+
+static void shutdown_server(grpc_end2end_test_fixture* f) {
+ if (!f->server) return;
+ grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000));
+ GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
+ grpc_timeout_seconds_to_deadline(5),
+ nullptr)
+ .type == GRPC_OP_COMPLETE);
+ grpc_server_destroy(f->server);
+ f->server = nullptr;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture* f) {
+ if (!f->client) return;
+ grpc_channel_destroy(f->client);
+ f->client = nullptr;
+}
+
+static void end_test(grpc_end2end_test_fixture* f) {
+ shutdown_server(f);
+ shutdown_client(f);
+
+ grpc_completion_queue_shutdown(f->cq);
+ drain_cq(f->cq);
+ grpc_completion_queue_destroy(f->cq);
+ grpc_completion_queue_destroy(f->shutdown_cq);
+}
+
+static void run_one_request(grpc_end2end_test_config config,
+ grpc_end2end_test_fixture f,
+ bool request_is_success) {
+ grpc_call* c;
+ grpc_call* s;
+ cq_verifier* cqv = cq_verifier_create(f.cq);
+ grpc_op ops[6];
+ grpc_op* op;
+ grpc_metadata_array initial_metadata_recv;
+ grpc_metadata_array trailing_metadata_recv;
+ grpc_metadata_array request_metadata_recv;
+ grpc_call_details call_details;
+ grpc_status_code status;
+ grpc_call_error error;
+ grpc_slice details;
+ int was_cancelled = 2;
+
+ gpr_timespec deadline = five_seconds_from_now();
+ c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+ grpc_slice_from_static_string("/foo"), nullptr,
+ deadline, nullptr);
+ GPR_ASSERT(c);
+
+ grpc_metadata_array_init(&initial_metadata_recv);
+ grpc_metadata_array_init(&trailing_metadata_recv);
+ grpc_metadata_array_init(&request_metadata_recv);
+ grpc_call_details_init(&call_details);
+
+ memset(ops, 0, sizeof(ops));
+ op = ops;
+ op->op = GRPC_OP_SEND_INITIAL_METADATA;
+ op->data.send_initial_metadata.count = 0;
+ op->flags = 0;
+ op->reserved = nullptr;
+ op++;
+ op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+ op->flags = 0;
+ op->reserved = nullptr;
+ op++;
+ op->op = GRPC_OP_RECV_INITIAL_METADATA;
+ op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+ op->flags = 0;
+ op->reserved = nullptr;
+ op++;
+ op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+ op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+ op->data.recv_status_on_client.status = &status;
+ op->data.recv_status_on_client.status_details = &details;
+ op->data.recv_status_on_client.error_string = nullptr;
+ op->flags = 0;
+ op->reserved = nullptr;
+ op++;
+ error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
+ nullptr);
+ GPR_ASSERT(GRPC_CALL_OK == error);
+
+ error =
+ grpc_server_request_call(f.server, &s, &call_details,
+ &request_metadata_recv, f.cq, f.cq, tag(101));
+ GPR_ASSERT(GRPC_CALL_OK == error);
+ CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
+ cq_verify(cqv);
+
+ memset(ops, 0, sizeof(ops));
+ op = ops;
+ op->op = GRPC_OP_SEND_INITIAL_METADATA;
+ op->data.send_initial_metadata.count = 0;
+ op->flags = 0;
+ op->reserved = nullptr;
+ op++;
+ op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+ op->data.send_status_from_server.trailing_metadata_count = 0;
+ op->data.send_status_from_server.status =
+ request_is_success ? GRPC_STATUS_OK : GRPC_STATUS_UNIMPLEMENTED;
+ grpc_slice status_details = grpc_slice_from_static_string("xyz");
+ op->data.send_status_from_server.status_details = &status_details;
+ op->flags = 0;
+ op->reserved = nullptr;
+ op++;
+ op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+ op->data.recv_close_on_server.cancelled = &was_cancelled;
+ op->flags = 0;
+ op->reserved = nullptr;
+ op++;
+ error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(102),
+ nullptr);
+ GPR_ASSERT(GRPC_CALL_OK == error);
+
+ CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
+ CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
+ cq_verify(cqv);
+
+ GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+ GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
+ GPR_ASSERT(0 == call_details.flags);
+
+ grpc_slice_unref(details);
+ grpc_metadata_array_destroy(&initial_metadata_recv);
+ grpc_metadata_array_destroy(&trailing_metadata_recv);
+ grpc_metadata_array_destroy(&request_metadata_recv);
+ grpc_call_details_destroy(&call_details);
+
+ grpc_call_unref(c);
+ grpc_call_unref(s);
+
+ cq_verifier_destroy(cqv);
+}
+
+static void test_channelz(grpc_end2end_test_config config) {
+ grpc_end2end_test_fixture f;
+
+ grpc_arg client_a;
+ client_a.type = GRPC_ARG_INTEGER;
+ client_a.key = const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ);
+ client_a.value.integer = true;
+ grpc_channel_args client_args = {1, &client_a};
+
+ f = begin_test(config, "test_channelz", &client_args, nullptr);
+ grpc_core::channelz::ChannelNode* channelz_channel =
+ grpc_channel_get_channelz_node(f.client);
+
+ GPR_ASSERT(channelz_channel != nullptr);
+ char* json = channelz_channel->RenderJSON();
+ GPR_ASSERT(json != nullptr);
+ GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"0\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"0\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"0\""));
+ gpr_free(json);
+
+ // one successful request
+ run_one_request(config, f, true);
+
+ json = channelz_channel->RenderJSON();
+ GPR_ASSERT(json != nullptr);
+ GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"1\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"0\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\""));
+ gpr_free(json);
+
+ // one failed request
+ run_one_request(config, f, false);
+
+ json = channelz_channel->RenderJSON();
+ GPR_ASSERT(json != nullptr);
+ gpr_log(GPR_INFO, "%s", json);
+ GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\""));
+ // channel tracing is not enables, so these should not be preset.
+ GPR_ASSERT(nullptr == strstr(json, "\"trace\""));
+ GPR_ASSERT(nullptr == strstr(json, "\"description\":\"Channel created\""));
+ GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\""));
+ gpr_free(json);
+
+ end_test(&f);
+ config.tear_down_data(&f);
+}
+
+static void test_channelz_with_channel_trace(grpc_end2end_test_config config) {
+ grpc_end2end_test_fixture f;
+
+ grpc_arg client_a[2];
+ client_a[0].type = GRPC_ARG_INTEGER;
+ client_a[0].key =
+ const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE);
+ client_a[0].value.integer = 5;
+ client_a[1].type = GRPC_ARG_INTEGER;
+ client_a[1].key = const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ);
+ client_a[1].value.integer = true;
+ grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
+
+ f = begin_test(config, "test_channelz_with_channel_trace", &client_args,
+ nullptr);
+ grpc_core::channelz::ChannelNode* channelz_channel =
+ grpc_channel_get_channelz_node(f.client);
+
+ GPR_ASSERT(channelz_channel != nullptr);
+ char* json = channelz_channel->RenderJSON();
+ GPR_ASSERT(json != nullptr);
+ gpr_log(GPR_INFO, "%s", json);
+ GPR_ASSERT(nullptr != strstr(json, "\"trace\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"description\":\"Channel created\""));
+ GPR_ASSERT(nullptr != strstr(json, "\"severity\":\"CT_INFO\""));
+ gpr_free(json);
+
+ end_test(&f);
+ config.tear_down_data(&f);
+}
+
+static void test_channelz_disabled(grpc_end2end_test_config config) {
+ grpc_end2end_test_fixture f;
+
+ f = begin_test(config, "test_channelz_disabled", nullptr, nullptr);
+ grpc_core::channelz::ChannelNode* channelz_channel =
+ grpc_channel_get_channelz_node(f.client);
+ GPR_ASSERT(channelz_channel == nullptr);
+ // one successful request
+ run_one_request(config, f, true);
+ GPR_ASSERT(channelz_channel == nullptr);
+ end_test(&f);
+ config.tear_down_data(&f);
+}
+
+void channelz(grpc_end2end_test_config config) {
+ test_channelz(config);
+ test_channelz_with_channel_trace(config);
+ test_channelz_disabled(config);
+}
+
+void channelz_pre_init(void) {}
diff --git a/test/core/gprpp/inlined_vector_test.cc b/test/core/gprpp/inlined_vector_test.cc
index ae34947718..41f4338f8a 100644
--- a/test/core/gprpp/inlined_vector_test.cc
+++ b/test/core/gprpp/inlined_vector_test.cc
@@ -27,10 +27,12 @@ namespace testing {
TEST(InlinedVectorTest, CreateAndIterate) {
const int kNumElements = 9;
InlinedVector<int, 2> v;
+ EXPECT_TRUE(v.empty());
for (int i = 0; i < kNumElements; ++i) {
v.push_back(i);
}
EXPECT_EQ(static_cast<size_t>(kNumElements), v.size());
+ EXPECT_FALSE(v.empty());
for (int i = 0; i < kNumElements; ++i) {
EXPECT_EQ(i, v[i]);
EXPECT_EQ(i, &v[i] - &v[0]); // Ensure contiguous allocation.
diff --git a/test/core/handshake/BUILD b/test/core/handshake/BUILD
index a3276b9343..712cd59197 100644
--- a/test/core/handshake/BUILD
+++ b/test/core/handshake/BUILD
@@ -82,3 +82,21 @@ grpc_cc_test(
"//test/core/util:grpc_test_util",
],
)
+
+grpc_cc_test(
+ name = "handshake_verify_peer_options",
+ srcs = ["verify_peer_options.cc"],
+ language = "C++",
+ data = [
+ "//src/core/tsi/test_creds:ca.pem",
+ "//src/core/tsi/test_creds:server1.key",
+ "//src/core/tsi/test_creds:server1.pem",
+ ],
+ deps = [
+ "//:gpr",
+ "//:grpc",
+ "//test/core/util:gpr_test_util",
+ "//test/core/util:grpc_test_util",
+ ],
+)
+
diff --git a/test/core/handshake/client_ssl.cc b/test/core/handshake/client_ssl.cc
index 8ac763ac4b..467df6e229 100644
--- a/test/core/handshake/client_ssl.cc
+++ b/test/core/handshake/client_ssl.cc
@@ -251,8 +251,8 @@ static bool client_ssl_test(char* server_alpn_preferred) {
reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
pem_key_cert_pair.cert_chain =
reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
- grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(ca_cert, &pem_key_cert_pair, nullptr);
+ grpc_channel_credentials* ssl_creds = grpc_ssl_credentials_create(
+ ca_cert, &pem_key_cert_pair, nullptr, nullptr);
// Establish a channel pointing at the TLS server. Since the gRPC runtime is
// lazy, this won't necessarily establish a connection yet.
diff --git a/test/core/handshake/verify_peer_options.cc b/test/core/handshake/verify_peer_options.cc
new file mode 100644
index 0000000000..86c524b4a5
--- /dev/null
+++ b/test/core/handshake/verify_peer_options.cc
@@ -0,0 +1,275 @@
+/*
+ *
+ * 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 "src/core/lib/iomgr/port.h"
+
+// This test won't work except with posix sockets enabled
+#ifdef GRPC_POSIX_SOCKET
+
+#include <arpa/inet.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/gprpp/thd.h"
+#include "src/core/lib/iomgr/load_file.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+
+#define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem"
+#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key"
+#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem"
+
+// Simple gRPC server. This listens until client_handshake_complete occurs.
+static gpr_event client_handshake_complete;
+
+static void server_thread(void* arg) {
+ const int port = *static_cast<int*>(arg);
+
+ // Load key pair and establish server SSL credentials.
+ grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
+ grpc_slice ca_slice, cert_slice, key_slice;
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_CA_PATH, 1, &ca_slice)));
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_KEY_PATH, 1, &key_slice)));
+ const char* ca_cert =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice);
+ pem_key_cert_pair.private_key =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
+ pem_key_cert_pair.cert_chain =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
+ grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create(
+ ca_cert, &pem_key_cert_pair, 1, 0, nullptr);
+
+ // Start server listening on local port.
+ char* addr;
+ gpr_asprintf(&addr, "127.0.0.1:%d", port);
+ grpc_server* server = grpc_server_create(nullptr, nullptr);
+ GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds));
+ free(addr);
+
+ grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
+
+ grpc_server_register_completion_queue(server, cq, nullptr);
+ grpc_server_start(server);
+
+ // Wait a bounded number of time until client_handshake_complete is set,
+ // sleeping between polls. The total time spent (deadline * retries)
+ // should be strictly greater than the client retry limit so that the
+ // client will always timeout first.
+ int retries = 60;
+ while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) {
+ const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1);
+ grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
+ GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT);
+ }
+
+ gpr_log(GPR_INFO, "Shutting down server");
+ grpc_server_shutdown_and_notify(server, cq, nullptr);
+ grpc_server_cancel_all_calls(server);
+ grpc_completion_queue_shutdown(cq);
+
+ const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(60);
+ grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
+ GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
+
+ grpc_server_destroy(server);
+ grpc_completion_queue_destroy(cq);
+ grpc_server_credentials_release(ssl_creds);
+ grpc_slice_unref(cert_slice);
+ grpc_slice_unref(key_slice);
+ grpc_slice_unref(ca_slice);
+}
+
+// This test launches a minimal TLS grpc server on a separate thread and then
+// establishes a TLS handshake via the core library to the server. The client
+// uses the supplied verify options.
+static bool verify_peer_options_test(verify_peer_options* verify_options) {
+ bool success = true;
+
+ grpc_init();
+ int port = grpc_pick_unused_port_or_die();
+ gpr_event_init(&client_handshake_complete);
+
+ // Launch the gRPC server thread.
+ bool ok;
+ grpc_core::Thread thd("grpc_client_ssl_test", server_thread, &port, &ok);
+ GPR_ASSERT(ok);
+ thd.Start();
+
+ // Load key pair and establish client SSL credentials.
+ grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
+ grpc_slice ca_slice, cert_slice, key_slice;
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_CA_PATH, 1, &ca_slice)));
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_KEY_PATH, 1, &key_slice)));
+ const char* ca_cert =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(ca_slice);
+ pem_key_cert_pair.private_key =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(key_slice);
+ pem_key_cert_pair.cert_chain =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
+ grpc_channel_credentials* ssl_creds = grpc_ssl_credentials_create(
+ ca_cert, &pem_key_cert_pair, verify_options, nullptr);
+
+ // Establish a channel pointing at the TLS server. Since the gRPC runtime is
+ // lazy, this won't necessarily establish a connection yet.
+ char* target;
+ gpr_asprintf(&target, "127.0.0.1:%d", port);
+ grpc_arg ssl_name_override = {
+ GRPC_ARG_STRING,
+ const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
+ {const_cast<char*>("foo.test.google.fr")}};
+ grpc_channel_args grpc_args;
+ grpc_args.num_args = 1;
+ grpc_args.args = &ssl_name_override;
+ grpc_channel* channel =
+ grpc_secure_channel_create(ssl_creds, target, &grpc_args, nullptr);
+ GPR_ASSERT(channel);
+ gpr_free(target);
+
+ // Initially the channel will be idle, the
+ // grpc_channel_check_connectivity_state triggers an attempt to connect.
+ GPR_ASSERT(grpc_channel_check_connectivity_state(
+ channel, 1 /* try_to_connect */) == GRPC_CHANNEL_IDLE);
+
+ // Wait a bounded number of times for the channel to be ready. When the
+ // channel is ready, the initial TLS handshake will have successfully
+ // completed. The total time spent on the client side (retries * deadline)
+ // should be greater than the server side time limit.
+ int retries = 10;
+ grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
+
+ while (state != GRPC_CHANNEL_READY && retries-- > 0) {
+ grpc_channel_watch_connectivity_state(
+ channel, state, grpc_timeout_seconds_to_deadline(3), cq, nullptr);
+ gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5);
+ grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr);
+ GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
+ state =
+ grpc_channel_check_connectivity_state(channel, 0 /* try_to_connect */);
+ }
+ grpc_completion_queue_destroy(cq);
+ if (retries < 0) {
+ success = false;
+ }
+
+ grpc_channel_destroy(channel);
+ grpc_channel_credentials_release(ssl_creds);
+ grpc_slice_unref(cert_slice);
+ grpc_slice_unref(key_slice);
+ grpc_slice_unref(ca_slice);
+
+ // Now that the client is completely cleaned up, trigger the server to
+ // shutdown
+ gpr_event_set(&client_handshake_complete, &client_handshake_complete);
+ // Wait for the server to completely shutdown
+ thd.Join();
+
+ grpc_shutdown();
+
+ return success;
+}
+
+static int callback_return_value = 0;
+static char callback_target_host[4096];
+static char callback_target_pem[4096];
+static void* callback_userdata = nullptr;
+static void* destruct_userdata = nullptr;
+
+static int verify_callback(const char* target_host, const char* target_pem,
+ void* userdata) {
+ if (target_host != nullptr) {
+ snprintf(callback_target_host, sizeof(callback_target_host), "%s",
+ target_host);
+ } else {
+ callback_target_host[0] = '\0';
+ }
+ if (target_pem != nullptr) {
+ snprintf(callback_target_pem, sizeof(callback_target_pem), "%s",
+ target_pem);
+ } else {
+ callback_target_pem[0] = '\0';
+ }
+ callback_userdata = userdata;
+ return callback_return_value;
+}
+
+static void verify_destruct(void* userdata) { destruct_userdata = userdata; }
+
+int main(int argc, char* argv[]) {
+ int userdata = 42;
+ verify_peer_options verify_options;
+
+ // Load the server's cert so that we can assert it gets passed to the callback
+ grpc_slice cert_slice;
+ GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
+ grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
+ const char* server_cert =
+ reinterpret_cast<const char*> GRPC_SLICE_START_PTR(cert_slice);
+
+ // Running with all-null values should have no effect
+ verify_options.verify_peer_callback = nullptr;
+ verify_options.verify_peer_callback_userdata = nullptr;
+ verify_options.verify_peer_destruct = nullptr;
+ GPR_ASSERT(verify_peer_options_test(&verify_options));
+ GPR_ASSERT(strlen(callback_target_host) == 0);
+ GPR_ASSERT(strlen(callback_target_pem) == 0);
+ GPR_ASSERT(callback_userdata == nullptr);
+ GPR_ASSERT(destruct_userdata == nullptr);
+
+ // Running with the callbacks and verify we get the expected values
+ verify_options.verify_peer_callback = verify_callback;
+ verify_options.verify_peer_callback_userdata = static_cast<void*>(&userdata);
+ verify_options.verify_peer_destruct = verify_destruct;
+ GPR_ASSERT(verify_peer_options_test(&verify_options));
+ GPR_ASSERT(strcmp(callback_target_host, "foo.test.google.fr") == 0);
+ GPR_ASSERT(strcmp(callback_target_pem, server_cert) == 0);
+ GPR_ASSERT(callback_userdata == static_cast<void*>(&userdata));
+ GPR_ASSERT(destruct_userdata == static_cast<void*>(&userdata));
+
+ // If the callback returns non-zero, initializing the channel should fail.
+ callback_return_value = 1;
+ GPR_ASSERT(!verify_peer_options_test(&verify_options));
+
+ grpc_slice_unref(cert_slice);
+
+ return 0;
+}
+
+#else /* GRPC_POSIX_SOCKET */
+
+int main(int argc, char** argv) { return 1; }
+
+#endif /* GRPC_POSIX_SOCKET */
diff --git a/test/core/security/BUILD b/test/core/security/BUILD
index 70bcc8c9c3..12aa84d93b 100644
--- a/test/core/security/BUILD
+++ b/test/core/security/BUILD
@@ -183,6 +183,7 @@ grpc_cc_test(
"//:gpr",
"//:gpr_base",
"//:grpc",
+ "//test/core/util:gpr_test_util",
],
)
@@ -195,6 +196,7 @@ grpc_cc_test(
"//:gpr",
"//:gpr_base",
"//:grpc",
+ "//test/core/util:gpr_test_util",
],
)
@@ -206,6 +208,7 @@ grpc_cc_test(
"//:alts_util",
"//:gpr",
"//:grpc",
+ "//test/core/util:gpr_test_util",
],
)
@@ -220,5 +223,6 @@ grpc_cc_test(
"//:grpc_secure",
"//:tsi",
"//:tsi_interface",
+ "//test/core/util:gpr_test_util",
],
)
diff --git a/test/core/statistics/census_log_tests.h b/test/core/statistics/census_log_tests.h
deleted file mode 100644
index ed808636e3..0000000000
--- a/test/core/statistics/census_log_tests.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef GRPC_TEST_CORE_STATISTICS_CENSUS_LOG_TESTS_H
-#define GRPC_TEST_CORE_STATISTICS_CENSUS_LOG_TESTS_H
-
-void test_invalid_record_size();
-void test_end_write_with_different_size();
-void test_read_pending_record();
-void test_read_beyond_pending_record();
-void test_detached_while_reading();
-void test_fill_log_no_fragmentation();
-void test_fill_circular_log_no_fragmentation();
-void test_fill_log_with_straddling_records();
-void test_fill_circular_log_with_straddling_records();
-void test_multiple_writers_circular_log();
-void test_multiple_writers();
-void test_performance();
-void test_small_log();
-
-#endif /* GRPC_TEST_CORE_STATISTICS_CENSUS_LOG_TESTS_H */
diff --git a/test/core/statistics/census_stub_test.cc b/test/core/statistics/census_stub_test.cc
deleted file mode 100644
index 507ae0a9fa..0000000000
--- a/test/core/statistics/census_stub_test.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include "src/core/ext/census/census_interface.h"
-#include "src/core/ext/census/census_rpc_stats.h"
-#include "test/core/util/test_config.h"
-
-/* Tests census noop stubs in a simulated rpc flow */
-void test_census_stubs(void) {
- census_op_id op_id;
- census_rpc_stats* stats = census_rpc_stats_create_empty();
- census_aggregated_rpc_stats data_map = {0, NULL};
-
- /* Initializes census library at server start up time. */
- census_init();
- /* Starts tracing at the beginning of a rpc. */
- op_id = census_tracing_start_op();
- /* Appends custom annotations on a trace object. */
- census_tracing_print(op_id, "annotation foo");
- census_tracing_print(op_id, "annotation bar");
- /* Appends method tag on the trace object. */
- census_add_method_tag(op_id, "service_foo/method.bar");
- /* Either record client side stats or server side stats associated with the
- op_id. Here for testing purpose, we record both. */
- census_record_rpc_client_stats(op_id, stats);
- census_record_rpc_server_stats(op_id, stats);
- /* Ends a tracing. */
- census_tracing_end_op(op_id);
- /* In process stats queries. */
- census_get_server_stats(&data_map);
- census_aggregated_rpc_stats_set_empty(&data_map);
- census_get_client_stats(&data_map);
- census_aggregated_rpc_stats_set_empty(&data_map);
- gpr_free(stats);
- census_shutdown();
-}
-
-int main(int argc, char** argv) {
- grpc_test_init(argc, argv);
- test_census_stubs();
- return 0;
-}
diff --git a/test/core/statistics/multiple_writers_circular_buffer_test.cc b/test/core/statistics/multiple_writers_circular_buffer_test.cc
deleted file mode 100644
index 6d3411289e..0000000000
--- a/test/core/statistics/multiple_writers_circular_buffer_test.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "test/core/statistics/census_log_tests.h"
-
-#include <stdlib.h>
-
-#include <grpc/support/time.h>
-#include "test/core/util/test_config.h"
-
-int main(int argc, char** argv) {
- grpc_test_init(argc, argv);
- srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
- test_multiple_writers_circular_log();
- return 0;
-}
diff --git a/test/core/statistics/quick_test.cc b/test/core/statistics/quick_test.cc
deleted file mode 100644
index 91ecdde818..0000000000
--- a/test/core/statistics/quick_test.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "test/core/statistics/census_log_tests.h"
-
-#include <stdlib.h>
-
-#include <grpc/support/time.h>
-#include "test/core/util/test_config.h"
-
-int main(int argc, char** argv) {
- grpc_test_init(argc, argv);
- srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
- test_invalid_record_size();
- test_end_write_with_different_size();
- test_read_pending_record();
- test_read_beyond_pending_record();
- test_detached_while_reading();
- test_fill_log_no_fragmentation();
- test_fill_circular_log_no_fragmentation();
- test_fill_log_with_straddling_records();
- test_fill_circular_log_with_straddling_records();
- return 0;
-}
diff --git a/test/core/statistics/rpc_stats_test.cc b/test/core/statistics/rpc_stats_test.cc
deleted file mode 100644
index a2a648e2ad..0000000000
--- a/test/core/statistics/rpc_stats_test.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/port_platform.h>
-#include <grpc/support/string.h>
-#include <grpc/support/time.h>
-
-#include "src/core/ext/census/census_interface.h"
-#include "src/core/ext/census/census_rpc_stats.h"
-#include "src/core/ext/census/census_tracing.h"
-#include "test/core/util/test_config.h"
-
-/* Ensure all possible state transitions are called without causing problem */
-static void test_init_shutdown(void) {
- census_stats_store_init();
- census_stats_store_init();
- census_stats_store_shutdown();
- census_stats_store_shutdown();
- census_stats_store_init();
-}
-
-static void test_create_and_destroy(void) {
- census_rpc_stats* stats = NULL;
- census_aggregated_rpc_stats agg_stats = {0, NULL};
-
- stats = census_rpc_stats_create_empty();
- GPR_ASSERT(stats != NULL);
- GPR_ASSERT(stats->cnt == 0 && stats->rpc_error_cnt == 0 &&
- stats->app_error_cnt == 0 && stats->elapsed_time_ms == 0.0 &&
- stats->api_request_bytes == 0 && stats->wire_request_bytes == 0 &&
- stats->api_response_bytes == 0 && stats->wire_response_bytes == 0);
- gpr_free(stats);
-
- census_aggregated_rpc_stats_set_empty(&agg_stats);
- GPR_ASSERT(agg_stats.num_entries == 0);
- GPR_ASSERT(agg_stats.stats == NULL);
- agg_stats.num_entries = 1;
- agg_stats.stats = (census_per_method_rpc_stats*)gpr_malloc(
- sizeof(census_per_method_rpc_stats));
- agg_stats.stats[0].method = gpr_strdup("foo");
- census_aggregated_rpc_stats_set_empty(&agg_stats);
- GPR_ASSERT(agg_stats.num_entries == 0);
- GPR_ASSERT(agg_stats.stats == NULL);
-}
-
-#define ASSERT_NEAR(a, b) \
- GPR_ASSERT((a - b) * (a - b) < 1e-24 * (a + b) * (a + b))
-
-static void test_record_and_get_stats(void) {
- census_rpc_stats stats = {1, 2, 3, 4, 5.1, 6.2, 7.3, 8.4};
- census_op_id id;
- census_aggregated_rpc_stats agg_stats = {0, NULL};
-
- /* Record client stats twice with the same op_id. */
- census_init();
- id = census_tracing_start_op();
- census_add_method_tag(id, "m1");
- census_record_rpc_client_stats(id, &stats);
- census_record_rpc_client_stats(id, &stats);
- census_tracing_end_op(id);
- /* Server stats expect to be empty */
- census_get_server_stats(&agg_stats);
- GPR_ASSERT(agg_stats.num_entries == 0);
- GPR_ASSERT(agg_stats.stats == NULL);
- /* Client stats expect to have one entry */
- census_get_client_stats(&agg_stats);
- GPR_ASSERT(agg_stats.num_entries == 1);
- GPR_ASSERT(agg_stats.stats != NULL);
- GPR_ASSERT(strcmp(agg_stats.stats[0].method, "m1") == 0);
- GPR_ASSERT(agg_stats.stats[0].minute_stats.cnt == 2 &&
- agg_stats.stats[0].hour_stats.cnt == 2 &&
- agg_stats.stats[0].total_stats.cnt == 2);
- ASSERT_NEAR(agg_stats.stats[0].minute_stats.wire_response_bytes, 16.8);
- ASSERT_NEAR(agg_stats.stats[0].hour_stats.wire_response_bytes, 16.8);
- ASSERT_NEAR(agg_stats.stats[0].total_stats.wire_response_bytes, 16.8);
- /* Get stats again, results should be the same. */
- census_get_client_stats(&agg_stats);
- GPR_ASSERT(agg_stats.num_entries == 1);
- census_aggregated_rpc_stats_set_empty(&agg_stats);
- census_shutdown();
-
- /* Record both server (once) and client (twice) stats with different op_ids.
- */
- census_init();
- id = census_tracing_start_op();
- census_add_method_tag(id, "m2");
- census_record_rpc_client_stats(id, &stats);
- census_tracing_end_op(id);
- id = census_tracing_start_op();
- census_add_method_tag(id, "m3");
- census_record_rpc_server_stats(id, &stats);
- census_tracing_end_op(id);
- id = census_tracing_start_op();
- census_add_method_tag(id, "m4");
- census_record_rpc_client_stats(id, &stats);
- census_tracing_end_op(id);
- /* Check server stats */
- census_get_server_stats(&agg_stats);
- GPR_ASSERT(agg_stats.num_entries == 1);
- GPR_ASSERT(strcmp(agg_stats.stats[0].method, "m3") == 0);
- GPR_ASSERT(agg_stats.stats[0].minute_stats.app_error_cnt == 3 &&
- agg_stats.stats[0].hour_stats.app_error_cnt == 3 &&
- agg_stats.stats[0].total_stats.app_error_cnt == 3);
- census_aggregated_rpc_stats_set_empty(&agg_stats);
- /* Check client stats */
- census_get_client_stats(&agg_stats);
- GPR_ASSERT(agg_stats.num_entries == 2);
- GPR_ASSERT(agg_stats.stats != NULL);
- GPR_ASSERT((strcmp(agg_stats.stats[0].method, "m2") == 0 &&
- strcmp(agg_stats.stats[1].method, "m4") == 0) ||
- (strcmp(agg_stats.stats[0].method, "m4") == 0 &&
- strcmp(agg_stats.stats[1].method, "m2") == 0));
- GPR_ASSERT(agg_stats.stats[0].minute_stats.cnt == 1 &&
- agg_stats.stats[1].minute_stats.cnt == 1);
- census_aggregated_rpc_stats_set_empty(&agg_stats);
- census_shutdown();
-}
-
-static void test_record_stats_on_unknown_op_id(void) {
- census_op_id unknown_id = {0xDEAD, 0xBEEF};
- census_rpc_stats stats = {1, 2, 3, 4, 5.1, 6.2, 7.3, 8.4};
- census_aggregated_rpc_stats agg_stats = {0, NULL};
-
- census_init();
- /* Tests that recording stats against unknown id is noop. */
- census_record_rpc_client_stats(unknown_id, &stats);
- census_record_rpc_server_stats(unknown_id, &stats);
- census_get_server_stats(&agg_stats);
- GPR_ASSERT(agg_stats.num_entries == 0);
- GPR_ASSERT(agg_stats.stats == NULL);
- census_get_client_stats(&agg_stats);
- GPR_ASSERT(agg_stats.num_entries == 0);
- GPR_ASSERT(agg_stats.stats == NULL);
- census_aggregated_rpc_stats_set_empty(&agg_stats);
- census_shutdown();
-}
-
-/* Test that record stats is noop when trace store is uninitialized. */
-static void test_record_stats_with_trace_store_uninitialized(void) {
- census_rpc_stats stats = {1, 2, 3, 4, 5.1, 6.2, 7.3, 8.4};
- census_op_id id = {0, 0};
- census_aggregated_rpc_stats agg_stats = {0, NULL};
-
- census_init();
- id = census_tracing_start_op();
- census_add_method_tag(id, "m");
- census_tracing_end_op(id);
- /* shuts down trace store only. */
- census_tracing_shutdown();
- census_record_rpc_client_stats(id, &stats);
- census_get_client_stats(&agg_stats);
- GPR_ASSERT(agg_stats.num_entries == 0);
- census_stats_store_shutdown();
-}
-
-int main(int argc, char** argv) {
- grpc_test_init(argc, argv);
- test_init_shutdown();
- test_create_and_destroy();
- test_record_and_get_stats();
- test_record_stats_on_unknown_op_id();
- test_record_stats_with_trace_store_uninitialized();
- return 0;
-}
diff --git a/test/core/statistics/small_log_test.cc b/test/core/statistics/small_log_test.cc
deleted file mode 100644
index fb8dfc9988..0000000000
--- a/test/core/statistics/small_log_test.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "test/core/statistics/census_log_tests.h"
-
-#include <stdlib.h>
-
-#include <grpc/support/time.h>
-#include "test/core/util/test_config.h"
-
-int main(int argc, char** argv) {
- grpc_test_init(argc, argv);
- srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
- test_small_log();
- return 0;
-}
diff --git a/test/core/surface/num_external_connectivity_watchers_test.cc b/test/core/surface/num_external_connectivity_watchers_test.cc
index 467deeeaec..7b7a0b6dfc 100644
--- a/test/core/surface/num_external_connectivity_watchers_test.cc
+++ b/test/core/surface/num_external_connectivity_watchers_test.cc
@@ -168,7 +168,7 @@ static const test_fixture insecure_test = {
static grpc_channel* secure_test_create_channel(const char* addr) {
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr);
+ grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr, nullptr);
grpc_arg ssl_name_override = {
GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c
index 52a1b03998..29083061bb 100644
--- a/test/core/surface/public_headers_must_be_c89.c
+++ b/test/core/surface/public_headers_must_be_c89.c
@@ -106,8 +106,6 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_insecure_channel_create);
printf("%lx", (unsigned long) grpc_lame_client_channel_create);
printf("%lx", (unsigned long) grpc_channel_destroy);
- printf("%lx", (unsigned long) grpc_channel_get_trace);
- printf("%lx", (unsigned long) grpc_channel_get_uuid);
printf("%lx", (unsigned long) grpc_call_cancel);
printf("%lx", (unsigned long) grpc_call_cancel_with_status);
printf("%lx", (unsigned long) grpc_call_ref);
diff --git a/test/core/surface/sequential_connectivity_test.cc b/test/core/surface/sequential_connectivity_test.cc
index 9aba4c499e..10562b3be9 100644
--- a/test/core/surface/sequential_connectivity_test.cc
+++ b/test/core/surface/sequential_connectivity_test.cc
@@ -144,7 +144,7 @@ static void secure_test_add_port(grpc_server* server, const char* addr) {
static grpc_channel* secure_test_create_channel(const char* addr) {
grpc_channel_credentials* ssl_creds =
- grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr);
+ grpc_ssl_credentials_create(test_root_cert, nullptr, nullptr, nullptr);
grpc_arg ssl_name_override = {
GRPC_ARG_STRING,
const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
diff --git a/test/core/transport/BUILD b/test/core/transport/BUILD
index 84fb3a1421..7ca1c1d943 100644
--- a/test/core/transport/BUILD
+++ b/test/core/transport/BUILD
@@ -129,6 +129,7 @@ grpc_cc_test(
language = "C++",
deps = [
"//:grpc",
+ "//test/core/util:gpr_test_util",
],
external_deps = [
"gtest",
diff --git a/test/core/tsi/alts/crypt/BUILD b/test/core/tsi/alts/crypt/BUILD
index cf9dbca316..abe1e83656 100644
--- a/test/core/tsi/alts/crypt/BUILD
+++ b/test/core/tsi/alts/crypt/BUILD
@@ -27,6 +27,7 @@ grpc_cc_test(
"//:alts_frame_protector",
"//:gpr",
"//:grpc",
+ "//test/core/util:gpr_test_util",
],
)
diff --git a/test/core/tsi/alts/frame_protector/BUILD b/test/core/tsi/alts/frame_protector/BUILD
index dd1966b379..6ff3015f4d 100644
--- a/test/core/tsi/alts/frame_protector/BUILD
+++ b/test/core/tsi/alts/frame_protector/BUILD
@@ -27,6 +27,7 @@ grpc_cc_test(
"//:gpr",
"//:grpc",
"//test/core/tsi/alts/crypt:alts_crypt_test_util",
+ "//test/core/util:gpr_test_util",
],
)
@@ -39,6 +40,7 @@ grpc_cc_test(
"//:gpr",
"//:grpc",
"//test/core/tsi/alts/crypt:alts_crypt_test_util",
+ "//test/core/util:gpr_test_util",
],
)
@@ -54,6 +56,7 @@ grpc_cc_test(
"//:tsi_interface",
"//test/core/tsi/alts/crypt:alts_crypt_test_util",
"//test/core/tsi:transport_security_test_lib",
+ "//test/core/util:gpr_test_util",
],
)
@@ -67,5 +70,6 @@ grpc_cc_test(
"//:gpr_base",
"//:grpc",
"//test/core/tsi/alts/crypt:alts_crypt_test_util",
+ "//test/core/util:gpr_test_util",
],
)
diff --git a/test/core/tsi/alts/handshaker/BUILD b/test/core/tsi/alts/handshaker/BUILD
index 809742744c..3f1a681c1a 100644
--- a/test/core/tsi/alts/handshaker/BUILD
+++ b/test/core/tsi/alts/handshaker/BUILD
@@ -37,6 +37,7 @@ grpc_cc_test(
"//:tsi",
"//:tsi_interface",
"//:grpc",
+ "//test/core/util:gpr_test_util",
],
)
@@ -47,6 +48,7 @@ grpc_cc_test(
deps = [
":alts_handshaker_service_api_test_lib",
"//:grpc",
+ "//test/core/util:gpr_test_util",
],
)
@@ -60,6 +62,7 @@ grpc_cc_test(
"//:gpr_base",
"//:grpc",
"//:tsi",
+ "//test/core/util:gpr_test_util",
],
)
@@ -71,6 +74,7 @@ grpc_cc_test(
":alts_handshaker_service_api_test_lib",
"//:grpc",
"//:tsi",
+ "//test/core/util:gpr_test_util",
],
)
@@ -81,6 +85,7 @@ grpc_cc_test(
deps = [
"//:alts_util",
"//:grpc",
+ "//test/core/util:gpr_test_util",
],
)
diff --git a/test/core/tsi/alts/zero_copy_frame_protector/BUILD b/test/core/tsi/alts/zero_copy_frame_protector/BUILD
index 2b41dae043..a3b797327e 100644
--- a/test/core/tsi/alts/zero_copy_frame_protector/BUILD
+++ b/test/core/tsi/alts/zero_copy_frame_protector/BUILD
@@ -28,6 +28,7 @@ grpc_cc_test(
"//:grpc",
"//:grpc_base_c",
"//test/core/tsi/alts/crypt:alts_crypt_test_util",
+ "//test/core/util:gpr_test_util",
],
)
@@ -40,6 +41,7 @@ grpc_cc_test(
"//:gpr",
"//:grpc",
"//test/core/tsi/alts/crypt:alts_crypt_test_util",
+ "//test/core/util:gpr_test_util",
],
)
@@ -53,5 +55,6 @@ grpc_cc_test(
"//:grpc",
"//:grpc_base_c",
"//test/core/tsi/alts/crypt:alts_crypt_test_util",
+ "//test/core/util:gpr_test_util",
],
)
diff --git a/test/core/util/BUILD b/test/core/util/BUILD
index f52570cde5..5492dcfa79 100644
--- a/test/core/util/BUILD
+++ b/test/core/util/BUILD
@@ -32,6 +32,11 @@ grpc_cc_library(
"test_config.h",
],
deps = ["//:gpr"],
+ data = [
+ "lsan_suppressions.txt",
+ "tsan_suppressions.txt",
+ "ubsan_suppressions.txt",
+ ],
)
grpc_cc_library(
diff --git a/tools/lsan_suppressions.txt b/test/core/util/lsan_suppressions.txt
index 204ddbef5e..204ddbef5e 100644
--- a/tools/lsan_suppressions.txt
+++ b/test/core/util/lsan_suppressions.txt
diff --git a/tools/tsan_suppressions.txt b/test/core/util/tsan_suppressions.txt
index e0c7907228..e0c7907228 100644
--- a/tools/tsan_suppressions.txt
+++ b/test/core/util/tsan_suppressions.txt
diff --git a/tools/ubsan_suppressions.txt b/test/core/util/ubsan_suppressions.txt
index 2268adc169..2268adc169 100644
--- a/tools/ubsan_suppressions.txt
+++ b/test/core/util/ubsan_suppressions.txt
diff --git a/test/cpp/client/BUILD b/test/cpp/client/BUILD
index 12825e88c2..c03ea92d34 100644
--- a/test/cpp/client/BUILD
+++ b/test/cpp/client/BUILD
@@ -28,6 +28,7 @@ grpc_cc_test(
"//:gpr",
"//:grpc",
"//:grpc++",
+ "//test/core/util:gpr_test_util",
],
)
diff --git a/test/cpp/ext/filters/census/BUILD b/test/cpp/ext/filters/census/BUILD
new file mode 100644
index 0000000000..6567dc667a
--- /dev/null
+++ b/test/cpp/ext/filters/census/BUILD
@@ -0,0 +1,42 @@
+# 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.
+
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
+load("//bazel:cc_grpc_library.bzl", "cc_grpc_library")
+
+licenses(["notice"]) # Apache v2
+
+grpc_package(name = "test/core/ext/census")
+
+grpc_cc_test(
+ name = "grpc_opencensus_plugin_test",
+ srcs = [
+ "stats_plugin_end2end_test.cc",
+ ],
+ language = "C++",
+ external_deps = [
+ "gtest",
+ "gmock",
+ "opencensus-stats-test",
+ ],
+ deps = [
+ "//:grpc++",
+ "//:grpc_opencensus_plugin",
+ "//src/proto/grpc/testing:echo_proto",
+ "//test/core/util:gpr_test_util",
+ "//test/core/util:grpc_test_util",
+ "//test/cpp/util:test_util",
+ "//test/cpp/util:test_config",
+ ],
+)
diff --git a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc
new file mode 100644
index 0000000000..664504a090
--- /dev/null
+++ b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc
@@ -0,0 +1,376 @@
+/*
+ *
+ * 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 <string>
+#include <thread> // NOLINT
+#include <vector>
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "include/grpc++/grpc++.h"
+#include "opencensus/stats/stats.h"
+#include "opencensus/stats/testing/test_utils.h"
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/core/util/test_config.h"
+
+namespace grpc {
+namespace testing {
+namespace {
+
+using ::opencensus::stats::Aggregation;
+using ::opencensus::stats::Distribution;
+using ::opencensus::stats::View;
+using ::opencensus::stats::ViewDescriptor;
+using ::opencensus::stats::testing::TestUtils;
+
+class EchoServer final : public EchoTestService::Service {
+ ::grpc::Status Echo(::grpc::ServerContext* context,
+ const EchoRequest* request,
+ EchoResponse* response) override {
+ if (request->param().expected_error().code() == 0) {
+ response->set_message(request->message());
+ return ::grpc::Status::OK;
+ } else {
+ return ::grpc::Status(static_cast<::grpc::StatusCode>(
+ request->param().expected_error().code()),
+ "");
+ }
+ }
+};
+
+class StatsPluginEnd2EndTest : public ::testing::Test {
+ protected:
+ static void SetUpTestCase() { RegisterOpenCensusPlugin(); }
+
+ void SetUp() {
+ // Set up a synchronous server on a different thread to avoid the asynch
+ // interface.
+ ::grpc::ServerBuilder builder;
+ int port;
+ // Use IPv4 here because it's less flaky than IPv6 ("[::]:0") on Travis.
+ builder.AddListeningPort("0.0.0.0:0", ::grpc::InsecureServerCredentials(),
+ &port);
+ builder.RegisterService(&service_);
+ server_ = builder.BuildAndStart();
+ ASSERT_NE(nullptr, server_);
+ ASSERT_NE(0, port);
+ server_address_ = absl::StrCat("0.0.0.0:", port);
+ server_thread_ = std::thread(&StatsPluginEnd2EndTest::RunServerLoop, this);
+
+ stub_ = EchoTestService::NewStub(::grpc::CreateChannel(
+ server_address_, ::grpc::InsecureChannelCredentials()));
+ }
+
+ void TearDown() {
+ server_->Shutdown();
+ server_thread_.join();
+ }
+
+ void RunServerLoop() { server_->Wait(); }
+
+ const std::string client_method_name_ = "grpc.testing.EchoTestService/Echo";
+ const std::string server_method_name_ = "grpc.testing.EchoTestService/Echo";
+
+ std::string server_address_;
+ EchoServer service_;
+ std::unique_ptr<grpc::Server> server_;
+ std::thread server_thread_;
+
+ std::unique_ptr<EchoTestService::Stub> stub_;
+};
+
+TEST_F(StatsPluginEnd2EndTest, ErrorCount) {
+ const auto client_method_descriptor =
+ ViewDescriptor()
+ .set_measure(kRpcClientRoundtripLatencyMeasureName)
+ .set_name("client_method")
+ .set_aggregation(Aggregation::Count())
+ .add_column(ClientMethodTagKey());
+ View client_method_view(client_method_descriptor);
+ const auto server_method_descriptor =
+ ViewDescriptor()
+ .set_measure(kRpcServerServerLatencyMeasureName)
+ .set_name("server_method")
+ .set_aggregation(Aggregation::Count())
+ .add_column(ServerMethodTagKey());
+ View server_method_view(server_method_descriptor);
+
+ const auto client_status_descriptor =
+ ViewDescriptor()
+ .set_measure(kRpcClientRoundtripLatencyMeasureName)
+ .set_name("client_status")
+ .set_aggregation(Aggregation::Count())
+ .add_column(ClientStatusTagKey());
+ View client_status_view(client_status_descriptor);
+ const auto server_status_descriptor =
+ ViewDescriptor()
+ .set_measure(kRpcServerServerLatencyMeasureName)
+ .set_name("server_status")
+ .set_aggregation(Aggregation::Count())
+ .add_column(ServerStatusTagKey());
+ View server_status_view(server_status_descriptor);
+
+ // Cover all valid statuses.
+ for (int i = 0; i <= 16; ++i) {
+ EchoRequest request;
+ request.set_message("foo");
+ request.mutable_param()->mutable_expected_error()->set_code(i);
+ EchoResponse response;
+ ::grpc::ClientContext context;
+ ::grpc::Status status = stub_->Echo(&context, request, &response);
+ }
+ absl::SleepFor(absl::Milliseconds(500));
+ TestUtils::Flush();
+
+ EXPECT_THAT(client_method_view.GetData().int_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(client_method_name_), 17)));
+ EXPECT_THAT(server_method_view.GetData().int_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(server_method_name_), 17)));
+
+ auto codes = {
+ ::testing::Pair(::testing::ElementsAre("OK"), 1),
+ ::testing::Pair(::testing::ElementsAre("CANCELLED"), 1),
+ ::testing::Pair(::testing::ElementsAre("UNKNOWN"), 1),
+ ::testing::Pair(::testing::ElementsAre("INVALID_ARGUMENT"), 1),
+ ::testing::Pair(::testing::ElementsAre("DEADLINE_EXCEEDED"), 1),
+ ::testing::Pair(::testing::ElementsAre("NOT_FOUND"), 1),
+ ::testing::Pair(::testing::ElementsAre("ALREADY_EXISTS"), 1),
+ ::testing::Pair(::testing::ElementsAre("PERMISSION_DENIED"), 1),
+ ::testing::Pair(::testing::ElementsAre("UNAUTHENTICATED"), 1),
+ ::testing::Pair(::testing::ElementsAre("RESOURCE_EXHAUSTED"), 1),
+ ::testing::Pair(::testing::ElementsAre("FAILED_PRECONDITION"), 1),
+ ::testing::Pair(::testing::ElementsAre("ABORTED"), 1),
+ ::testing::Pair(::testing::ElementsAre("OUT_OF_RANGE"), 1),
+ ::testing::Pair(::testing::ElementsAre("UNIMPLEMENTED"), 1),
+ ::testing::Pair(::testing::ElementsAre("INTERNAL"), 1),
+ ::testing::Pair(::testing::ElementsAre("UNAVAILABLE"), 1),
+ ::testing::Pair(::testing::ElementsAre("DATA_LOSS"), 1),
+ };
+
+ EXPECT_THAT(client_status_view.GetData().int_data(),
+ ::testing::UnorderedElementsAreArray(codes));
+ EXPECT_THAT(server_status_view.GetData().int_data(),
+ ::testing::UnorderedElementsAreArray(codes));
+}
+
+TEST_F(StatsPluginEnd2EndTest, RequestReceivedBytesPerRpc) {
+ View client_sent_bytes_per_rpc_view(ClientSentBytesPerRpcCumulative());
+ View client_received_bytes_per_rpc_view(
+ ClientReceivedBytesPerRpcCumulative());
+ View server_sent_bytes_per_rpc_view(ServerSentBytesPerRpcCumulative());
+ View server_received_bytes_per_rpc_view(
+ ServerReceivedBytesPerRpcCumulative());
+
+ {
+ EchoRequest request;
+ request.set_message("foo");
+ EchoResponse response;
+ ::grpc::ClientContext context;
+ ::grpc::Status status = stub_->Echo(&context, request, &response);
+ ASSERT_TRUE(status.ok());
+ EXPECT_EQ("foo", response.message());
+ }
+ absl::SleepFor(absl::Milliseconds(500));
+ TestUtils::Flush();
+
+ EXPECT_THAT(client_received_bytes_per_rpc_view.GetData().distribution_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(client_method_name_),
+ ::testing::AllOf(::testing::Property(&Distribution::count, 1),
+ ::testing::Property(&Distribution::mean,
+ ::testing::Gt(0.0))))));
+ EXPECT_THAT(client_sent_bytes_per_rpc_view.GetData().distribution_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(client_method_name_),
+ ::testing::AllOf(::testing::Property(&Distribution::count, 1),
+ ::testing::Property(&Distribution::mean,
+ ::testing::Gt(0.0))))));
+ EXPECT_THAT(server_received_bytes_per_rpc_view.GetData().distribution_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(server_method_name_),
+ ::testing::AllOf(::testing::Property(&Distribution::count, 1),
+ ::testing::Property(&Distribution::mean,
+ ::testing::Gt(0.0))))));
+ EXPECT_THAT(server_sent_bytes_per_rpc_view.GetData().distribution_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(server_method_name_),
+ ::testing::AllOf(::testing::Property(&Distribution::count, 1),
+ ::testing::Property(&Distribution::mean,
+ ::testing::Gt(0.0))))));
+}
+
+TEST_F(StatsPluginEnd2EndTest, Latency) {
+ View client_latency_view(ClientRoundtripLatencyCumulative());
+ View client_server_latency_view(ClientServerLatencyCumulative());
+ View server_server_latency_view(ServerServerLatencyCumulative());
+
+ const absl::Time start_time = absl::Now();
+ {
+ EchoRequest request;
+ request.set_message("foo");
+ EchoResponse response;
+ ::grpc::ClientContext context;
+ ::grpc::Status status = stub_->Echo(&context, request, &response);
+ ASSERT_TRUE(status.ok());
+ EXPECT_EQ("foo", response.message());
+ }
+ // We do not know exact latency/elapsed time, but we know it is less than the
+ // entire time spent making the RPC.
+ const double max_time = absl::ToDoubleMilliseconds(absl::Now() - start_time);
+
+ absl::SleepFor(absl::Milliseconds(500));
+ TestUtils::Flush();
+
+ EXPECT_THAT(
+ client_latency_view.GetData().distribution_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(client_method_name_),
+ ::testing::AllOf(
+ ::testing::Property(&Distribution::count, 1),
+ ::testing::Property(&Distribution::mean, ::testing::Gt(0.0)),
+ ::testing::Property(&Distribution::mean,
+ ::testing::Lt(max_time))))));
+
+ // Elapsed time is a subinterval of total latency.
+ const auto client_latency = client_latency_view.GetData()
+ .distribution_data()
+ .find({client_method_name_})
+ ->second.mean();
+ EXPECT_THAT(
+ client_server_latency_view.GetData().distribution_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(client_method_name_),
+ ::testing::AllOf(
+ ::testing::Property(&Distribution::count, 1),
+ ::testing::Property(&Distribution::mean, ::testing::Gt(0.0)),
+ ::testing::Property(&Distribution::mean,
+ ::testing::Lt(client_latency))))));
+
+ // client server elapsed time should be the same value propagated to the
+ // client.
+ const auto client_elapsed_time = client_server_latency_view.GetData()
+ .distribution_data()
+ .find({client_method_name_})
+ ->second.mean();
+ EXPECT_THAT(
+ server_server_latency_view.GetData().distribution_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(server_method_name_),
+ ::testing::AllOf(
+ ::testing::Property(&Distribution::count, 1),
+ ::testing::Property(&Distribution::mean,
+ ::testing::DoubleEq(client_elapsed_time))))));
+}
+
+TEST_F(StatsPluginEnd2EndTest, CompletedRpcs) {
+ View client_completed_rpcs_view(ClientCompletedRpcsCumulative());
+ View server_completed_rpcs_view(ServerCompletedRpcsCumulative());
+
+ EchoRequest request;
+ request.set_message("foo");
+ EchoResponse response;
+ const int count = 5;
+ for (int i = 0; i < count; ++i) {
+ {
+ ::grpc::ClientContext context;
+ ::grpc::Status status = stub_->Echo(&context, request, &response);
+ ASSERT_TRUE(status.ok());
+ EXPECT_EQ("foo", response.message());
+ }
+ absl::SleepFor(absl::Milliseconds(500));
+ TestUtils::Flush();
+
+ EXPECT_THAT(client_completed_rpcs_view.GetData().int_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(client_method_name_, "OK"), i + 1)));
+ EXPECT_THAT(server_completed_rpcs_view.GetData().int_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(server_method_name_, "OK"), i + 1)));
+ }
+}
+
+TEST_F(StatsPluginEnd2EndTest, RequestReceivedMessagesPerRpc) {
+ // TODO: Use streaming RPCs.
+ View client_received_messages_per_rpc_view(
+ ClientSentMessagesPerRpcCumulative());
+ View client_sent_messages_per_rpc_view(
+ ClientReceivedMessagesPerRpcCumulative());
+ View server_received_messages_per_rpc_view(
+ ServerSentMessagesPerRpcCumulative());
+ View server_sent_messages_per_rpc_view(
+ ServerReceivedMessagesPerRpcCumulative());
+
+ EchoRequest request;
+ request.set_message("foo");
+ EchoResponse response;
+ const int count = 5;
+ for (int i = 0; i < count; ++i) {
+ {
+ ::grpc::ClientContext context;
+ ::grpc::Status status = stub_->Echo(&context, request, &response);
+ ASSERT_TRUE(status.ok());
+ EXPECT_EQ("foo", response.message());
+ }
+ absl::SleepFor(absl::Milliseconds(500));
+ TestUtils::Flush();
+
+ EXPECT_THAT(
+ client_received_messages_per_rpc_view.GetData().distribution_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(client_method_name_),
+ ::testing::AllOf(::testing::Property(&Distribution::count, i + 1),
+ ::testing::Property(&Distribution::mean,
+ ::testing::DoubleEq(1.0))))));
+ EXPECT_THAT(
+ client_sent_messages_per_rpc_view.GetData().distribution_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(client_method_name_),
+ ::testing::AllOf(::testing::Property(&Distribution::count, i + 1),
+ ::testing::Property(&Distribution::mean,
+ ::testing::DoubleEq(1.0))))));
+ EXPECT_THAT(
+ server_received_messages_per_rpc_view.GetData().distribution_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(server_method_name_),
+ ::testing::AllOf(::testing::Property(&Distribution::count, i + 1),
+ ::testing::Property(&Distribution::mean,
+ ::testing::DoubleEq(1.0))))));
+ EXPECT_THAT(
+ server_sent_messages_per_rpc_view.GetData().distribution_data(),
+ ::testing::UnorderedElementsAre(::testing::Pair(
+ ::testing::ElementsAre(server_method_name_),
+ ::testing::AllOf(::testing::Property(&Distribution::count, i + 1),
+ ::testing::Property(&Distribution::mean,
+ ::testing::DoubleEq(1.0))))));
+ }
+}
+
+} // namespace
+} // namespace testing
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ grpc_test_init(argc, argv);
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD
index 5dcfd94ed3..7b27aed4c3 100644
--- a/test/cpp/microbenchmarks/BUILD
+++ b/test/cpp/microbenchmarks/BUILD
@@ -24,6 +24,7 @@ grpc_cc_test(
external_deps = [
"benchmark",
],
+ deps = ["//test/core/util:gpr_test_util",]
)
grpc_cc_library(
@@ -148,3 +149,15 @@ grpc_cc_binary(
srcs = ["bm_chttp2_hpack.cc"],
deps = [":helpers"],
)
+
+grpc_cc_binary(
+ name = "bm_opencensus_plugin",
+ testonly = 1,
+ srcs = ["bm_opencensus_plugin.cc"],
+ language = "C++",
+ deps = [
+ ":helpers",
+ "//:grpc_opencensus_plugin",
+ "//src/proto/grpc/testing:echo_proto",
+ ],
+)
diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc
index 831b29c506..dd1610dc3d 100644
--- a/test/cpp/microbenchmarks/bm_call_create.cc
+++ b/test/cpp/microbenchmarks/bm_call_create.cc
@@ -621,18 +621,26 @@ typedef struct {
static void StartTransportStreamOp(grpc_call_element* elem,
grpc_transport_stream_op_batch* op) {
call_data* calld = static_cast<call_data*>(elem->call_data);
+ // Construct list of closures to return.
+ grpc_core::CallCombinerClosureList closures;
if (op->recv_initial_metadata) {
- GRPC_CALL_COMBINER_START(
- calld->call_combiner,
- op->payload->recv_initial_metadata.recv_initial_metadata_ready,
- GRPC_ERROR_NONE, "recv_initial_metadata");
+ closures.Add(op->payload->recv_initial_metadata.recv_initial_metadata_ready,
+ GRPC_ERROR_NONE, "recv_initial_metadata");
}
if (op->recv_message) {
- GRPC_CALL_COMBINER_START(calld->call_combiner,
- op->payload->recv_message.recv_message_ready,
- GRPC_ERROR_NONE, "recv_message");
+ closures.Add(op->payload->recv_message.recv_message_ready, GRPC_ERROR_NONE,
+ "recv_message");
}
- GRPC_CLOSURE_SCHED(op->on_complete, GRPC_ERROR_NONE);
+ if (op->recv_trailing_metadata) {
+ closures.Add(
+ op->payload->recv_trailing_metadata.recv_trailing_metadata_ready,
+ GRPC_ERROR_NONE, "recv_trailing_metadata");
+ }
+ if (op->on_complete != nullptr) {
+ closures.Add(op->on_complete, GRPC_ERROR_NONE, "on_complete");
+ }
+ // Execute closures.
+ closures.RunClosures(calld->call_combiner);
}
static void StartTransportOp(grpc_channel_element* elem,
diff --git a/test/cpp/microbenchmarks/bm_opencensus_plugin.cc b/test/cpp/microbenchmarks/bm_opencensus_plugin.cc
new file mode 100644
index 0000000000..9d42eb891d
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_opencensus_plugin.cc
@@ -0,0 +1,118 @@
+/*
+ *
+ * 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 <benchmark/benchmark.h>
+#include <string>
+#include <thread> // NOLINT
+
+#include "absl/base/call_once.h"
+#include "absl/strings/str_cat.h"
+#include "include/grpc++/grpc++.h"
+#include "opencensus/stats/stats.h"
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/cpp/microbenchmarks/helpers.h"
+
+absl::once_flag once;
+void RegisterOnce() { absl::call_once(once, grpc::RegisterOpenCensusPlugin); }
+
+class EchoServer final : public grpc::testing::EchoTestService::Service {
+ grpc::Status Echo(grpc::ServerContext* context,
+ const grpc::testing::EchoRequest* request,
+ grpc::testing::EchoResponse* response) override {
+ if (request->param().expected_error().code() == 0) {
+ response->set_message(request->message());
+ return grpc::Status::OK;
+ } else {
+ return grpc::Status(static_cast<grpc::StatusCode>(
+ request->param().expected_error().code()),
+ "");
+ }
+ }
+};
+
+// An EchoServerThread object creates an EchoServer on a separate thread and
+// shuts down the server and thread when it goes out of scope.
+class EchoServerThread final {
+ public:
+ EchoServerThread() {
+ grpc::ServerBuilder builder;
+ int port;
+ builder.AddListeningPort("[::]:0", grpc::InsecureServerCredentials(),
+ &port);
+ builder.RegisterService(&service_);
+ server_ = builder.BuildAndStart();
+ if (server_ == nullptr || port == 0) {
+ std::abort();
+ }
+ server_address_ = absl::StrCat("[::]:", port);
+ server_thread_ = std::thread(&EchoServerThread::RunServerLoop, this);
+ }
+
+ ~EchoServerThread() {
+ server_->Shutdown();
+ server_thread_.join();
+ }
+
+ const std::string& address() { return server_address_; }
+
+ private:
+ void RunServerLoop() { server_->Wait(); }
+
+ std::string server_address_;
+ EchoServer service_;
+ std::unique_ptr<grpc::Server> server_;
+ std::thread server_thread_;
+};
+
+static void BM_E2eLatencyCensusDisabled(benchmark::State& state) {
+ EchoServerThread server;
+ std::unique_ptr<grpc::testing::EchoTestService::Stub> stub =
+ grpc::testing::EchoTestService::NewStub(grpc::CreateChannel(
+ server.address(), grpc::InsecureChannelCredentials()));
+
+ grpc::testing::EchoResponse response;
+ for (auto _ : state) {
+ grpc::testing::EchoRequest request;
+ grpc::ClientContext context;
+ grpc::Status status = stub->Echo(&context, request, &response);
+ }
+}
+BENCHMARK(BM_E2eLatencyCensusDisabled);
+
+static void BM_E2eLatencyCensusEnabled(benchmark::State& state) {
+ RegisterOnce();
+ // This we can safely repeat, and doing so clears accumulated data to avoid
+ // initialization costs varying between runs.
+ grpc::RegisterOpenCensusViewsForExport();
+
+ EchoServerThread server;
+ std::unique_ptr<grpc::testing::EchoTestService::Stub> stub =
+ grpc::testing::EchoTestService::NewStub(grpc::CreateChannel(
+ server.address(), grpc::InsecureChannelCredentials()));
+
+ grpc::testing::EchoResponse response;
+ for (auto _ : state) {
+ grpc::testing::EchoRequest request;
+ grpc::ClientContext context;
+ grpc::Status status = stub->Echo(&context, request, &response);
+ }
+}
+BENCHMARK(BM_E2eLatencyCensusEnabled);
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/util/BUILD b/test/cpp/util/BUILD
index b1153d2df3..9b42bb28b1 100644
--- a/test/cpp/util/BUILD
+++ b/test/cpp/util/BUILD
@@ -217,6 +217,7 @@ grpc_cc_test(
],
deps = [
"//:grpc++",
+ "//test/core/util:gpr_test_util",
],
)
@@ -260,6 +261,7 @@ grpc_cc_test(
deps = [
"//:grpc++_error_details",
"//src/proto/grpc/testing:echo_messages_proto",
+ "//test/core/util:gpr_test_util",
],
)
diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc
index fbc9f1501c..ee310784c2 100644
--- a/test/cpp/util/channel_trace_proto_helper.cc
+++ b/test/cpp/util/channel_trace_proto_helper.cc
@@ -30,26 +30,47 @@
namespace grpc {
namespace testing {
-void ValidateChannelTraceProtoJsonTranslation(char* tracer_json_c_str) {
- std::string tracer_json_str(tracer_json_c_str);
- grpc::channelz::ChannelTrace channel_trace;
+namespace {
+
+// Generic helper that takes in a json string, converts it to a proto, and
+// then back to json. This ensures that the json string was correctly formatted
+// according to https://developers.google.com/protocol-buffers/docs/proto3#json
+template <typename Message>
+void VaidateProtoJsonTranslation(char* json_c_str) {
+ std::string json_str(json_c_str);
+ Message msg;
google::protobuf::util::JsonParseOptions parse_options;
// If the following line is failing, then uncomment the last line of the
// comment, and uncomment the lines that print the two strings. You can
// then compare the output, and determine what fields are missing.
//
- // options.ignore_unknown_fields = true;
- ASSERT_EQ(google::protobuf::util::JsonStringToMessage(
- tracer_json_str, &channel_trace, parse_options),
+ // parse_options.ignore_unknown_fields = true;
+ EXPECT_EQ(google::protobuf::util::JsonStringToMessage(json_str, &msg,
+ parse_options),
google::protobuf::util::Status::OK);
std::string proto_json_str;
- ASSERT_EQ(google::protobuf::util::MessageToJsonString(channel_trace,
- &proto_json_str),
+ google::protobuf::util::JsonPrintOptions print_options;
+ // We usually do not want this to be true, however it can be helpful to
+ // uncomment and see the output produced then all fields are printed.
+ // print_options.always_print_primitive_fields = true;
+ EXPECT_EQ(google::protobuf::util::MessageToJsonString(msg, &proto_json_str,
+ print_options),
google::protobuf::util::Status::OK);
// uncomment these to compare the the json strings.
- // gpr_log(GPR_ERROR, "tracer json: %s", tracer_json_str.c_str());
+ // gpr_log(GPR_ERROR, "tracer json: %s", json_str.c_str());
// gpr_log(GPR_ERROR, "proto json: %s", proto_json_str.c_str());
- ASSERT_EQ(tracer_json_str, proto_json_str);
+ EXPECT_EQ(json_str, proto_json_str);
+}
+
+} // namespace
+
+void ValidateChannelTraceProtoJsonTranslation(char* tracer_json_c_str) {
+ VaidateProtoJsonTranslation<grpc::channelz::v1::ChannelTrace>(
+ tracer_json_c_str);
+}
+
+void ValidateChannelProtoJsonTranslation(char* channel_json_c_str) {
+ VaidateProtoJsonTranslation<grpc::channelz::v1::Channel>(channel_json_c_str);
}
} // namespace testing
diff --git a/test/cpp/util/channel_trace_proto_helper.h b/test/cpp/util/channel_trace_proto_helper.h
index d7043d9f06..d1a3603372 100644
--- a/test/cpp/util/channel_trace_proto_helper.h
+++ b/test/cpp/util/channel_trace_proto_helper.h
@@ -23,6 +23,7 @@ namespace grpc {
namespace testing {
void ValidateChannelTraceProtoJsonTranslation(char* tracer_json_c_str);
+void ValidateChannelProtoJsonTranslation(char* channel_json_c_str);
} // namespace testing
} // namespace grpc
diff --git a/test/distrib/python/test_packages.sh b/test/distrib/python/test_packages.sh
index 6bf49d45b9..755daa1021 100755
--- a/test/distrib/python/test_packages.sh
+++ b/test/distrib/python/test_packages.sh
@@ -28,10 +28,12 @@ else
echo "Testing Python source distribution"
ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-[0-9]*.tar.gz)
TOOLS_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-tools-[0-9]*.tar.gz)
- HEALTH_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-health-checking-[0-9]*.tar.gz)
- REFLECTION_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-reflection-[0-9]*.tar.gz)
fi
+HEALTH_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-health-checking-[0-9]*.tar.gz)
+REFLECTION_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-reflection-[0-9]*.tar.gz)
+TESTING_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-testing-[0-9]*.tar.gz)
+
VIRTUAL_ENV=$(mktemp -d)
virtualenv "$VIRTUAL_ENV"
PYTHON=$VIRTUAL_ENV/bin/python
@@ -53,13 +55,9 @@ function at_least_one_installs() {
at_least_one_installs "${ARCHIVES[@]}"
at_least_one_installs "${TOOLS_ARCHIVES[@]}"
-
-if [[ "$1" == "source" ]]
-then
- echo "Testing Python health and reflection packages"
- at_least_one_installs "${HEALTH_ARCHIVES[@]}"
- at_least_one_installs "${REFLECTION_ARCHIVES[@]}"
-fi
+at_least_one_installs "${HEALTH_ARCHIVES[@]}"
+at_least_one_installs "${REFLECTION_ARCHIVES[@]}"
+at_least_one_installs "${TESTING_ARCHIVES[@]}"
#
diff --git a/tools/bazel.rc b/tools/bazel.rc
index 19e7921ca9..39f8071535 100644
--- a/tools/bazel.rc
+++ b/tools/bazel.rc
@@ -11,7 +11,7 @@ build:asan --copt -fno-omit-frame-pointer
build:asan --copt -DGPR_NO_DIRECT_SYSCALLS
build:asan --linkopt -fsanitize=address
build:asan --action_env=ASAN_OPTIONS=detect_leaks=1:color=always
-build:asan --action_env=LSAN_OPTIONS=suppressions=lsan_suppressions.txt:report_objects=1
+build:asan --action_env=LSAN_OPTIONS=suppressions=test/core/util/lsan_suppressions.txt:report_objects=1
build:msan --strip=never
build:msan --copt -fsanitize-coverage=edge
@@ -32,7 +32,7 @@ build:tsan --copt -fno-omit-frame-pointer
build:tsan --copt -DGPR_NO_DIRECT_SYSCALLS
build:tsan --copt -DGRPC_TSAN
build:tsan --linkopt -fsanitize=thread
-build:tsan --action_env=TSAN_OPTIONS=suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
+build:tsan --action_env=TSAN_OPTIONS=suppressions=test/core/util/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
build:ubsan --strip=never
build:ubsan --copt -fsanitize-coverage=edge
@@ -42,7 +42,7 @@ build:ubsan --copt -DGRPC_UBSAN
build:ubsan --copt -DNDEBUG
build:ubsan --copt -fno-sanitize=function,vptr
build:ubsan --linkopt -fsanitize=undefined
-build:ubsan --action_env=UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1:suppressions=tools/ubsan_suppressions.txt
+build:ubsan --action_env=UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1:suppressions=test/core/util/ubsan_suppressions.txt
build:basicprof --strip=never
build:basicprof --copt -DNDEBUG
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index e552b4ed56..c230d987f9 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -1012,6 +1012,7 @@ src/core/lib/channel/channel_args.h \
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 \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 478c417ab3..c84dd1c86c 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -864,7 +864,6 @@ include/grpc/support/time.h \
include/grpc/support/workaround_list.h \
src/core/README.md \
src/core/ext/README.md \
-src/core/ext/census/grpc_context.cc \
src/core/ext/filters/client_channel/README.md \
src/core/ext/filters/client_channel/backup_poller.cc \
src/core/ext/filters/client_channel/backup_poller.h \
@@ -1039,6 +1038,8 @@ src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_stack_builder.h \
src/core/lib/channel/channel_trace.cc \
src/core/lib/channel/channel_trace.h \
+src/core/lib/channel/channelz.cc \
+src/core/lib/channel/channelz.h \
src/core/lib/channel/channelz_registry.cc \
src/core/lib/channel/channelz_registry.h \
src/core/lib/channel/connected_channel.cc \
@@ -1500,6 +1501,7 @@ src/core/tsi/transport_security.h \
src/core/tsi/transport_security_grpc.cc \
src/core/tsi/transport_security_grpc.h \
src/core/tsi/transport_security_interface.h \
+src/cpp/ext/filters/census/grpc_context.cc \
third_party/nanopb/pb.h \
third_party/nanopb/pb_common.c \
third_party/nanopb/pb_common.h \
diff --git a/tools/internal_ci/linux/grpc_tsan_on_foundry.sh b/tools/internal_ci/linux/grpc_tsan_on_foundry.sh
index fafa1ceecb..1396fc4e42 100644
--- a/tools/internal_ci/linux/grpc_tsan_on_foundry.sh
+++ b/tools/internal_ci/linux/grpc_tsan_on_foundry.sh
@@ -14,5 +14,5 @@
# limitations under the License.
export UPLOAD_TEST_RESULTS=true
-EXTRA_FLAGS="--copt=-gmlt --strip=never --copt=-fsanitize=thread --linkopt=-fsanitize=thread --test_timeout=3600"
+EXTRA_FLAGS="--copt=-gmlt --strip=never --copt=-fsanitize=thread --linkopt=-fsanitize=thread --test_timeout=3600 --action_env=TSAN_OPTIONS=suppressions=test/core/util/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1"
github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}"
diff --git a/tools/run_tests/artifacts/build_artifact_python.sh b/tools/run_tests/artifacts/build_artifact_python.sh
index 846a415396..2878005bb2 100755
--- a/tools/run_tests/artifacts/build_artifact_python.sh
+++ b/tools/run_tests/artifacts/build_artifact_python.sh
@@ -99,12 +99,16 @@ then
"${PIP}" install grpcio --no-index --find-links "file://$ARTIFACT_DIR/"
"${PIP}" install grpcio-tools --no-index --find-links "file://$ARTIFACT_DIR/"
- # Build gRPC health-checking source distribution
+ # Build grpcio_testing source distribution
+ ${SETARCH_CMD} "${PYTHON}" src/python/grpcio_testing/setup.py sdist
+ cp -r src/python/grpcio_testing/dist/* "$ARTIFACT_DIR"
+
+ # Build grpcio_health_checking source distribution
${SETARCH_CMD} "${PYTHON}" src/python/grpcio_health_checking/setup.py \
preprocess build_package_protos sdist
cp -r src/python/grpcio_health_checking/dist/* "$ARTIFACT_DIR"
- # Build gRPC reflection source distribution
+ # Build grpcio_reflection source distribution
${SETARCH_CMD} "${PYTHON}" src/python/grpcio_reflection/setup.py \
preprocess build_package_protos sdist
cp -r src/python/grpcio_reflection/dist/* "$ARTIFACT_DIR"
diff --git a/tools/run_tests/generated/configs.json b/tools/run_tests/generated/configs.json
index a14340cb7b..74c6286240 100644
--- a/tools/run_tests/generated/configs.json
+++ b/tools/run_tests/generated/configs.json
@@ -6,7 +6,7 @@
"config": "asan-trace-cmp",
"environ": {
"ASAN_OPTIONS": "detect_leaks=1:color=always",
- "LSAN_OPTIONS": "suppressions=tools/lsan_suppressions.txt:report_objects=1"
+ "LSAN_OPTIONS": "suppressions=test/core/util/lsan_suppressions.txt:report_objects=1"
}
},
{
@@ -16,7 +16,7 @@
"config": "asan",
"environ": {
"ASAN_OPTIONS": "detect_leaks=1:color=always",
- "LSAN_OPTIONS": "suppressions=tools/lsan_suppressions.txt:report_objects=1"
+ "LSAN_OPTIONS": "suppressions=test/core/util/lsan_suppressions.txt:report_objects=1"
}
},
{
@@ -47,13 +47,13 @@
{
"config": "ubsan",
"environ": {
- "UBSAN_OPTIONS": "halt_on_error=1:print_stacktrace=1:suppressions=tools/ubsan_suppressions.txt"
+ "UBSAN_OPTIONS": "halt_on_error=1:print_stacktrace=1:suppressions=test/core/util/ubsan_suppressions.txt"
}
},
{
"config": "tsan",
"environ": {
- "TSAN_OPTIONS": "suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1"
+ "TSAN_OPTIONS": "suppressions=test/core/util/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1"
}
},
{
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 413efa5eac..333ae01c49 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -1177,6 +1177,23 @@
{
"deps": [
"gpr",
+ "gpr_test_util",
+ "grpc",
+ "grpc_test_util"
+ ],
+ "headers": [],
+ "is_filegroup": false,
+ "language": "c",
+ "name": "handshake_verify_peer_options",
+ "src": [
+ "test/core/handshake/verify_peer_options.cc"
+ ],
+ "third_party": false,
+ "type": "target"
+ },
+ {
+ "deps": [
+ "gpr",
"grpc_test_util"
],
"headers": [],
@@ -3106,6 +3123,27 @@
{
"deps": [
"gpr",
+ "gpr_test_util",
+ "grpc",
+ "grpc++",
+ "grpc++_channelz_proto",
+ "grpc++_test",
+ "grpc++_test_util",
+ "grpc_test_util"
+ ],
+ "headers": [],
+ "is_filegroup": false,
+ "language": "c++",
+ "name": "channelz_test",
+ "src": [
+ "test/core/channel/channelz_test.cc"
+ ],
+ "third_party": false,
+ "type": "target"
+ },
+ {
+ "deps": [
+ "gpr",
"grpc"
],
"headers": [],
@@ -3961,26 +3999,6 @@
"gpr_test_util",
"grpc",
"grpc++",
- "grpc++_test_util",
- "grpc_test_util",
- "lb_load_data_store"
- ],
- "headers": [],
- "is_filegroup": false,
- "language": "c++",
- "name": "lb_load_data_store_test",
- "src": [
- "test/cpp/server/load_reporter/load_data_store_test.cc"
- ],
- "third_party": false,
- "type": "target"
- },
- {
- "deps": [
- "gpr",
- "gpr_test_util",
- "grpc",
- "grpc++",
"grpc++_test",
"grpc_test_util"
],
@@ -7619,23 +7637,6 @@
},
{
"deps": [
- "grpc++"
- ],
- "headers": [
- "src/cpp/server/load_reporter/load_data_store.h"
- ],
- "is_filegroup": false,
- "language": "c++",
- "name": "lb_load_data_store",
- "src": [
- "src/cpp/server/load_reporter/load_data_store.cc",
- "src/cpp/server/load_reporter/load_data_store.h"
- ],
- "third_party": false,
- "type": "lib"
- },
- {
- "deps": [
"grpc",
"grpc++",
"grpc++_core_stats",
@@ -8743,6 +8744,7 @@
"test/core/end2end/tests/cancel_in_a_vacuum.cc",
"test/core/end2end/tests/cancel_test_helpers.h",
"test/core/end2end/tests/cancel_with_status.cc",
+ "test/core/end2end/tests/channelz.cc",
"test/core/end2end/tests/compressed_payload.cc",
"test/core/end2end/tests/connectivity.cc",
"test/core/end2end/tests/default_host.cc",
@@ -8843,6 +8845,7 @@
"test/core/end2end/tests/cancel_in_a_vacuum.cc",
"test/core/end2end/tests/cancel_test_helpers.h",
"test/core/end2end/tests/cancel_with_status.cc",
+ "test/core/end2end/tests/channelz.cc",
"test/core/end2end/tests/compressed_payload.cc",
"test/core/end2end/tests/connectivity.cc",
"test/core/end2end/tests/default_host.cc",
@@ -9049,8 +9052,7 @@
{
"deps": [
"gpr",
- "grpc_base",
- "nanopb"
+ "grpc_base"
],
"headers": [
"include/grpc/census.h"
@@ -9060,7 +9062,7 @@
"name": "census",
"src": [
"include/grpc/census.h",
- "src/core/ext/census/grpc_context.cc"
+ "src/cpp/ext/filters/census/grpc_context.cc"
],
"third_party": false,
"type": "filegroup"
@@ -9316,6 +9318,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",
@@ -9487,6 +9490,7 @@
"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",
@@ -9636,6 +9640,7 @@
"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",
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index ba63352036..12eeb2b35f 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -1451,6 +1451,26 @@
"args": [],
"benchmark": false,
"ci_platforms": [
+ "linux"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "gtest": false,
+ "language": "c",
+ "name": "handshake_verify_peer_options",
+ "platforms": [
+ "linux"
+ ],
+ "uses_polling": true
+ },
+ {
+ "args": [],
+ "benchmark": false,
+ "ci_platforms": [
"linux",
"mac",
"posix",
@@ -3706,6 +3726,30 @@
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
+ "gtest": true,
+ "language": "c++",
+ "name": "channelz_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "uses_polling": true
+ },
+ {
+ "args": [],
+ "benchmark": false,
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
"gtest": false,
"language": "c++",
"name": "check_gcp_environment_linux_test",
@@ -4448,30 +4492,6 @@
"flaky": false,
"gtest": true,
"language": "c++",
- "name": "lb_load_data_store_test",
- "platforms": [
- "linux",
- "mac",
- "posix",
- "windows"
- ],
- "uses_polling": true
- },
- {
- "args": [],
- "benchmark": false,
- "ci_platforms": [
- "linux",
- "mac",
- "posix",
- "windows"
- ],
- "cpu_cost": 1.0,
- "exclude_configs": [],
- "exclude_iomgrs": [],
- "flaky": false,
- "gtest": true,
- "language": "c++",
"name": "memory_test",
"platforms": [
"linux",
@@ -7287,6 +7307,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_census_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -9062,6 +9105,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_compress_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -10801,6 +10867,28 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_fakesec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -12466,6 +12554,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_fd_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -13731,6 +13842,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_full_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -15454,6 +15588,25 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "linux"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_full+pipe_test",
+ "platforms": [
+ "linux"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -16969,6 +17122,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_full+trace_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -18698,6 +18874,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_full+workarounds_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -20486,6 +20685,30 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_http_proxy_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -22345,6 +22568,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_load_reporting_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -24133,6 +24379,30 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_oauth2_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -25957,6 +26227,30 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_proxy_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"default_host"
],
"ci_platforms": [
@@ -27109,6 +27403,30 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_sockpair_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -28381,6 +28699,30 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_sockpair+trace_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -29603,6 +29945,32 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [
+ "msan"
+ ],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_sockpair_1byte_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -30968,6 +31336,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_ssl_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -32732,6 +33123,30 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_ssl_proxy_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"default_host"
],
"ci_platforms": [
@@ -33896,6 +34311,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_uds_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -35575,6 +36013,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "inproc_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"empty_batch"
],
"ci_platforms": [
@@ -36587,6 +37048,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_census_nosec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -38339,6 +38823,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_compress_nosec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -40022,6 +40529,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_fd_nosec_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -41264,6 +41794,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_full_nosec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -42968,6 +43521,25 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "linux"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_full+pipe_nosec_test",
+ "platforms": [
+ "linux"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -44460,6 +45032,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_full+trace_nosec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -46166,6 +46761,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_full+workarounds_nosec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -47930,6 +48548,30 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_http_proxy_nosec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -49766,6 +50408,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_load_reporting_nosec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -51506,6 +52171,30 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_proxy_nosec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"default_host"
],
"ci_platforms": [
@@ -52634,6 +53323,30 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_sockpair_nosec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -53882,6 +54595,30 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_sockpair+trace_nosec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -55078,6 +55815,32 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [
+ "msan"
+ ],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_sockpair_1byte_nosec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -56397,6 +57160,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [
+ "uv"
+ ],
+ "flaky": false,
+ "language": "c",
+ "name": "h2_uds_nosec_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"compressed_payload"
],
"ci_platforms": [
@@ -58053,6 +58839,29 @@
},
{
"args": [
+ "channelz"
+ ],
+ "ci_platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "language": "c",
+ "name": "inproc_nosec_test",
+ "platforms": [
+ "windows",
+ "linux",
+ "mac",
+ "posix"
+ ]
+ },
+ {
+ "args": [
"empty_batch"
],
"ci_platforms": [
diff --git a/tools/run_tests/helper_scripts/build_ruby.sh b/tools/run_tests/helper_scripts/build_ruby.sh
index b15a8639d9..38f99d80ab 100755
--- a/tools/run_tests/helper_scripts/build_ruby.sh
+++ b/tools/run_tests/helper_scripts/build_ruby.sh
@@ -23,3 +23,6 @@ cd "$(dirname "$0")/../../.."
rm -rf ./tmp
rake compile
+
+# build grpc_ruby_plugin
+make grpc_ruby_plugin -j8
diff --git a/tools/run_tests/helper_scripts/run_ruby.sh b/tools/run_tests/helper_scripts/run_ruby.sh
index 03eaeb0ec7..4e9c212877 100755
--- a/tools/run_tests/helper_scripts/run_ruby.sh
+++ b/tools/run_tests/helper_scripts/run_ruby.sh
@@ -18,7 +18,4 @@ set -ex
# change to grpc repo root
cd "$(dirname "$0")/../../.."
-# build grpc_ruby_plugin
-make grpc_ruby_plugin -j8
-
rake
diff --git a/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh b/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
index 5784745bac..7ff877e830 100755
--- a/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
+++ b/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
@@ -19,14 +19,15 @@ set -ex
cd "$(dirname "$0")/../../.."
EXIT_CODE=0
-ruby src/ruby/end2end/sig_handling_driver.rb || EXIT_CODE=1
-ruby src/ruby/end2end/channel_state_driver.rb || EXIT_CODE=1
-ruby src/ruby/end2end/channel_closing_driver.rb || EXIT_CODE=1
-ruby src/ruby/end2end/sig_int_during_channel_watch_driver.rb || EXIT_CODE=1
-ruby src/ruby/end2end/killed_client_thread_driver.rb || EXIT_CODE=1
-ruby src/ruby/end2end/forking_client_driver.rb || EXIT_CODE=1
-ruby src/ruby/end2end/grpc_class_init_driver.rb || EXIT_CODE=1
-ruby src/ruby/end2end/multiple_killed_watching_threads_driver.rb || EXIT_CODE=1
-ruby src/ruby/end2end/load_grpc_with_gc_stress_driver.rb || EXIT_CODE=1
-ruby src/ruby/end2end/client_memory_usage_driver.rb || EXIT_CODE=1
+time ruby src/ruby/end2end/sig_handling_driver.rb || EXIT_CODE=1
+time ruby src/ruby/end2end/channel_state_driver.rb || EXIT_CODE=1
+time ruby src/ruby/end2end/channel_closing_driver.rb || EXIT_CODE=1
+time ruby src/ruby/end2end/sig_int_during_channel_watch_driver.rb || EXIT_CODE=1
+time ruby src/ruby/end2end/killed_client_thread_driver.rb || EXIT_CODE=1
+time ruby src/ruby/end2end/forking_client_driver.rb || EXIT_CODE=1
+time ruby src/ruby/end2end/grpc_class_init_driver.rb || EXIT_CODE=1
+time ruby src/ruby/end2end/multiple_killed_watching_threads_driver.rb || EXIT_CODE=1
+time ruby src/ruby/end2end/load_grpc_with_gc_stress_driver.rb || EXIT_CODE=1
+time ruby src/ruby/end2end/client_memory_usage_driver.rb || EXIT_CODE=1
+time ruby src/ruby/end2end/package_with_underscore_checker.rb || EXIT_CODE=1
exit $EXIT_CODE
diff --git a/tools/run_tests/python_utils/filter_pull_request_tests.py b/tools/run_tests/python_utils/filter_pull_request_tests.py
index 4c09b3414e..98a17fd1a7 100644
--- a/tools/run_tests/python_utils/filter_pull_request_tests.py
+++ b/tools/run_tests/python_utils/filter_pull_request_tests.py
@@ -96,7 +96,7 @@ _WHITELIST_DICT = {
'gRPC\-Core\.podspec$': [_OBJC_TEST_SUITE],
'gRPC\-ProtoRPC\.podspec$': [_OBJC_TEST_SUITE],
'gRPC\-RxLibrary\.podspec$': [_OBJC_TEST_SUITE],
- 'INSTALL\.md$': [],
+ 'BUILDING\.md$': [],
'LICENSE$': [],
'MANIFEST\.md$': [],
'package\.json$': [_PHP_TEST_SUITE],
diff --git a/tools/run_tests/python_utils/upload_rbe_results.py b/tools/run_tests/python_utils/upload_rbe_results.py
index 7236227f7c..cbeb1ad941 100644
--- a/tools/run_tests/python_utils/upload_rbe_results.py
+++ b/tools/run_tests/python_utils/upload_rbe_results.py
@@ -161,7 +161,7 @@ if __name__ == "__main__":
test_cases = action['testAction']['testSuite']['tests'][0][
'testSuite']['tests']
for test_case in test_cases:
- if 'errors' in test_case['testCase']:
+ if any(s in test_case['testCase'] for s in ['errors', 'failures']):
result = 'FAILED'
elif 'timedOut' in test_case['testCase']:
result = 'TIMEOUT'
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 67aa641e2d..e04b13b24c 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -883,7 +883,7 @@ class RubyLanguage(object):
tests.append(
self.config.job_spec(
['tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh'],
- timeout_seconds=10 * 60,
+ timeout_seconds=20 * 60,
environ=_FORCE_ENVIRON_FOR_WRAPPERS))
return tests
diff --git a/tools/run_tests/sanity/check_bazel_workspace.py b/tools/run_tests/sanity/check_bazel_workspace.py
index 673feb7558..d562fffc8a 100755
--- a/tools/run_tests/sanity/check_bazel_workspace.py
+++ b/tools/run_tests/sanity/check_bazel_workspace.py
@@ -51,6 +51,7 @@ _GRPC_DEP_NAMES = [
'com_github_google_benchmark',
'com_github_cares_cares',
'com_google_absl',
+ 'io_opencensus_cpp',
_BAZEL_TOOLCHAINS_DEP_NAME,
_TWISTED_TWISTED_DEP_NAME,
_YAML_PYYAML_DEP_NAME,
@@ -140,7 +141,6 @@ if len(workspace_git_hashes - git_submodule_hashes) > 0:
print(
"Found discrepancies between git submodules and Bazel WORKSPACE dependencies"
)
- sys.exit(1)
# Also check that we can override each dependency
for name in _GRPC_DEP_NAMES:
diff --git a/vsprojects/.gitignore b/vsprojects/.gitignore
deleted file mode 100644
index 8df1dcf0bf..0000000000
--- a/vsprojects/.gitignore
+++ /dev/null
@@ -1,12 +0,0 @@
-Debug
-Debug-DLL
-Release
-Release-DLL
-*.suo
-*.user
-test_bin
-*.opensdf
-*.sdf
-third_party/*.user
-/packages
-/IntDir
diff --git a/vsprojects/README.md b/vsprojects/README.md
deleted file mode 100644
index ee32ecab9a..0000000000
--- a/vsprojects/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Pre-generated MS Visual Studio project & solution files: DELETED
-
-**The pre-generated MS Visual Studio project & solution files are no longer available, please use cmake instead (it can generate Visual Studio projects for you).**
-
-**Pre-generated MS Visual Studio projects used to be the recommended way to build on Windows, but there were some limitations:**
-- **hard to build dependencies, expecially boringssl (deps usually support cmake quite well)**
-- **the nuget-based openssl & zlib dependencies are hard to maintain and update. We've received issues indicating that they are flawed.**
-- **.proto codegen is hard to support in Visual Studio directly (but we have a pretty decent support in cmake)**
-- **It's a LOT of generated files. We prefer not to have too much generated code in our github repo.**
-
-See [INSTALL.md](/INSTALL.md) for detailed instructions how to build using cmake on Windows.