aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Yuchen Zeng <zyc@google.com>2017-05-19 15:18:30 -0700
committerGravatar Yuchen Zeng <zyc@google.com>2017-05-19 15:18:30 -0700
commit01cc75087e723be3c67295d030285e2bbf66e87c (patch)
tree5a1d1d8bf7d9dc19d2045954564729fb10a3b3cf
parent72f70a5a5d3a438a00e3ac73a908344693c274e9 (diff)
parent04ac52bc3f30061a0609769cdcc82da143d6a292 (diff)
Merge remote-tracking branch 'upstream/master' into srv_record
-rw-r--r--BUILD14
-rw-r--r--CMakeLists.txt7
-rw-r--r--Makefile7
-rw-r--r--binding.gyp1
-rw-r--r--build.yaml3
-rw-r--r--composer.json7
-rw-r--r--config.m466
-rw-r--r--doc/PROTOCOL-WEB.md4
-rw-r--r--doc/compression.md4
-rw-r--r--doc/cpp-style-guide.md3
-rw-r--r--doc/fail_fast.md2
-rw-r--r--doc/service_config.md4
-rw-r--r--doc/stress_test_framework.md2
-rw-r--r--doc/workarounds.md19
-rw-r--r--examples/php/composer.json3
-rw-r--r--gRPC-Core.podspec1
-rwxr-xr-xgrpc.gemspec1
-rw-r--r--include/grpc++/ext/health_check_service_server_builder_option.h4
-rw-r--r--include/grpc++/ext/proto_server_reflection_plugin.h4
-rw-r--r--include/grpc++/generic/generic_stub.h10
-rw-r--r--include/grpc++/grpc++.h4
-rw-r--r--include/grpc++/health_check_service_interface.h19
-rw-r--r--include/grpc++/impl/codegen/async_stream.h285
-rw-r--r--include/grpc++/impl/codegen/async_unary_call.h78
-rw-r--r--include/grpc++/impl/codegen/call.h4
-rw-r--r--include/grpc++/impl/codegen/call_hook.h3
-rw-r--r--include/grpc++/impl/codegen/client_context.h40
-rw-r--r--include/grpc++/impl/codegen/client_unary_call.h2
-rw-r--r--include/grpc++/impl/codegen/completion_queue.h3
-rw-r--r--include/grpc++/impl/codegen/completion_queue_tag.h8
-rw-r--r--include/grpc++/impl/codegen/config.h6
-rw-r--r--include/grpc++/impl/codegen/method_handler_impl.h24
-rw-r--r--include/grpc++/impl/codegen/rpc_method.h1
-rw-r--r--include/grpc++/impl/codegen/rpc_service_method.h8
-rw-r--r--include/grpc++/impl/codegen/security/auth_context.h2
-rw-r--r--include/grpc++/impl/codegen/server_context.h120
-rw-r--r--include/grpc++/impl/codegen/service_type.h9
-rw-r--r--include/grpc++/impl/codegen/status_code_enum.h5
-rw-r--r--include/grpc++/impl/codegen/string_ref.h16
-rw-r--r--include/grpc++/impl/codegen/stub_options.h1
-rw-r--r--include/grpc++/impl/codegen/sync_stream.h243
-rw-r--r--include/grpc++/impl/codegen/time.h19
-rw-r--r--include/grpc++/impl/server_builder_plugin.h17
-rw-r--r--include/grpc++/resource_quota.h1
-rw-r--r--include/grpc++/security/auth_metadata_processor.h22
-rw-r--r--include/grpc++/security/credentials.h18
-rw-r--r--include/grpc++/security/server_credentials.h16
-rw-r--r--include/grpc++/server_builder.h6
-rw-r--r--include/grpc++/support/error_details.h16
-rw-r--r--include/grpc++/test/mock_stream.h40
-rw-r--r--include/grpc++/test/server_context_test_spouse.h8
-rw-r--r--include/grpc/census.h98
-rw-r--r--include/grpc/grpc.h2
-rw-r--r--include/grpc/grpc_security.h116
-rw-r--r--include/grpc/grpc_security_constants.h18
-rw-r--r--include/grpc/impl/codegen/atm.h2
-rw-r--r--include/grpc/impl/codegen/atm_windows.h8
-rw-r--r--include/grpc/impl/codegen/byte_buffer_reader.h4
-rw-r--r--include/grpc/impl/codegen/compression_types.h2
-rw-r--r--include/grpc/impl/codegen/gpr_slice.h10
-rw-r--r--include/grpc/impl/codegen/gpr_types.h12
-rw-r--r--include/grpc/impl/codegen/grpc_types.h118
-rw-r--r--include/grpc/impl/codegen/propagation_bits.h4
-rw-r--r--include/grpc/impl/codegen/slice.h22
-rw-r--r--include/grpc/impl/codegen/status.h41
-rw-r--r--include/grpc/impl/codegen/sync.h2
-rw-r--r--include/grpc/slice.h50
-rw-r--r--include/grpc/slice_buffer.h30
-rw-r--r--include/grpc/support/alloc.h14
-rw-r--r--include/grpc/support/cmdline.h20
-rw-r--r--include/grpc/support/cpu.h6
-rw-r--r--include/grpc/support/histogram.h2
-rw-r--r--include/grpc/support/host_port.h4
-rw-r--r--include/grpc/support/log.h16
-rw-r--r--include/grpc/support/log_windows.h2
-rw-r--r--include/grpc/support/string_util.h6
-rw-r--r--include/grpc/support/subprocess.h6
-rw-r--r--include/grpc/support/sync.h62
-rw-r--r--include/grpc/support/thd.h22
-rw-r--r--include/grpc/support/time.h24
-rw-r--r--include/grpc/support/tls.h2
-rw-r--r--include/grpc/support/tls_gcc.h4
-rw-r--r--include/grpc/support/tls_msvc.h2
-rw-r--r--include/grpc/support/tls_pthread.h2
-rw-r--r--include/grpc/support/useful.h4
-rw-r--r--include/grpc/support/workaround_list.h2
-rw-r--r--package.json2
-rw-r--r--package.xml97
-rw-r--r--src/core/ext/filters/client_channel/client_channel.c18
-rw-r--r--src/core/ext/filters/client_channel/lb_policy.h4
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c81
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c89
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h2
-rw-r--r--src/core/ext/filters/client_channel/parse_address.c129
-rw-r--r--src/core/ext/filters/client_channel/parse_address.h6
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c19
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c80
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h10
-rw-r--r--src/core/ext/filters/client_channel/subchannel.c2
-rw-r--r--src/core/ext/filters/client_channel/subchannel_index.c12
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.c41
-rw-r--r--src/core/lib/iomgr/ev_epollsig_linux.c23
-rw-r--r--src/core/lib/iomgr/ev_windows.c43
-rw-r--r--src/core/lib/iomgr/tcp_server_uv.c32
-rw-r--r--src/core/lib/iomgr/tcp_uv.c14
-rw-r--r--src/core/lib/support/cmdline.c6
-rw-r--r--src/core/lib/support/histogram.c4
-rw-r--r--src/core/lib/support/host_port.c2
-rw-r--r--src/core/lib/support/string.c24
-rw-r--r--src/core/lib/support/string_posix.c2
-rw-r--r--src/core/lib/support/subprocess_posix.c4
-rw-r--r--src/core/lib/support/thd_posix.c2
-rw-r--r--src/core/lib/surface/completion_queue.c4
-rw-r--r--src/core/lib/transport/bdp_estimator.c5
-rw-r--r--src/core/lib/transport/bdp_estimator.h2
-rw-r--r--src/cpp/server/server_builder.cc10
-rw-r--r--src/csharp/Grpc.Core/Internal/CallError.cs5
-rw-r--r--src/csharp/Grpc.Core/Internal/CallSafeHandle.cs4
-rw-r--r--src/csharp/Grpc.Core/Internal/NativeMethods.cs6
-rw-r--r--src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs2
-rwxr-xr-xsrc/csharp/build_packages_dotnetcli.bat10
-rwxr-xr-xsrc/csharp/build_packages_dotnetcli.sh10
-rw-r--r--src/node/index.js55
-rw-r--r--src/node/src/protobuf_js_5_common.js10
-rw-r--r--src/node/src/server.js8
-rw-r--r--src/node/test/common_test.js21
-rw-r--r--src/node/test/surface_test.js42
-rw-r--r--src/objective-c/tests/GRPCClientTests.m29
-rw-r--r--src/php/README.md22
-rw-r--r--src/php/ext/grpc/call.c26
-rw-r--r--src/php/ext/grpc/call_credentials.c28
-rw-r--r--src/php/ext/grpc/php_grpc.h6
-rw-r--r--src/php/ext/grpc/version.h40
-rw-r--r--src/php/tests/qps/composer.json3
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py1
-rw-r--r--templates/composer.json.template7
-rw-r--r--templates/config.m4.template15
-rw-r--r--templates/package.json.template2
-rw-r--r--templates/package.xml.template22
-rwxr-xr-xtemplates/src/csharp/build_packages_dotnetcli.bat.template10
-rwxr-xr-xtemplates/src/csharp/build_packages_dotnetcli.sh.template10
-rw-r--r--templates/src/php/ext/grpc/version.h.template42
-rwxr-xr-xtemplates/tools/dockerfile/go_build_interop.sh.include47
-rw-r--r--templates/tools/dockerfile/interoptest/grpc_interop_go1.7/build_interop.sh.template3
-rw-r--r--templates/tools/dockerfile/interoptest/grpc_interop_go1.8/build_interop.sh.template3
-rw-r--r--test/core/end2end/cq_verifier.c8
-rw-r--r--test/core/end2end/fixtures/h2_full+workarounds.c3
-rw-r--r--test/core/end2end/fixtures/http_proxy_fixture.c19
-rw-r--r--test/core/surface/concurrent_connectivity_test.c2
-rw-r--r--test/cpp/end2end/grpclb_end2end_test.cc207
-rw-r--r--test/cpp/microbenchmarks/bm_fullstack_trickle.cc5
m---------third_party/protobuf0
-rw-r--r--tools/README.md2
-rw-r--r--tools/dockerfile/grpc_artifact_linux_armv6/Dockerfile39
-rw-r--r--tools/dockerfile/grpc_artifact_linux_armv7/Dockerfile39
-rw-r--r--tools/dockerfile/interoptest/grpc_interop_go1.7/build_interop.sh48
-rw-r--r--tools/dockerfile/interoptest/grpc_interop_go1.8/build_interop.sh48
-rwxr-xr-xtools/dockerfile/push_testing_images.sh2
-rw-r--r--tools/doxygen/Doxyfile.c++1
-rw-r--r--tools/doxygen/Doxyfile.c++.internal2
-rw-r--r--tools/doxygen/Doxyfile.core1
-rw-r--r--tools/doxygen/Doxyfile.core.internal2
-rwxr-xr-xtools/gcp/utils/gcr_upload.py119
-rw-r--r--tools/internal_ci/helper_scripts/prepare_build_interop_rc43
-rw-r--r--tools/internal_ci/linux/grpc_interop_badserver_java.cfg3
-rwxr-xr-xtools/internal_ci/linux/grpc_interop_badserver_java.sh3
-rw-r--r--tools/internal_ci/linux/grpc_interop_badserver_python.cfg3
-rwxr-xr-xtools/internal_ci/linux/grpc_interop_badserver_python.sh3
-rwxr-xr-xtools/internal_ci/linux/grpc_interop_tocloud.sh1
-rw-r--r--tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg39
-rwxr-xr-xtools/internal_ci/linux/sanitizer/grpc_c_ubsan.sh38
-rw-r--r--tools/internal_ci/macos/grpc_interop.cfg40
-rwxr-xr-xtools/internal_ci/macos/grpc_interop.sh38
-rw-r--r--tools/interop_matrix/README.md40
-rw-r--r--tools/interop_matrix/client_matrix.py48
-rwxr-xr-xtools/interop_matrix/create_matrix_images.py272
-rwxr-xr-xtools/interop_matrix/create_testcases.sh81
-rwxr-xr-xtools/interop_matrix/testcases/go__master11
-rw-r--r--tools/profiling/microbenchmarks/bm_json.py4
-rw-r--r--tools/run_tests/artifacts/artifact_targets.py29
-rwxr-xr-xtools/run_tests/dockerize/build_and_run_docker.sh3
-rwxr-xr-xtools/run_tests/dockerize/build_interop_image.sh13
-rw-r--r--tools/run_tests/generated/sources_and_headers.json1
-rwxr-xr-xtools/run_tests/run_interop_tests.py16
-rwxr-xr-xtools/run_tests/run_tests.py8
-rw-r--r--tools/ubsan_suppressions.txt5
-rw-r--r--vsprojects/vcxproj/grpc++/grpc++.vcxproj2
-rw-r--r--vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters3
-rw-r--r--vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj2
-rw-r--r--vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters3
-rw-r--r--vsprojects/vcxproj/grpc/grpc.vcxproj2
-rw-r--r--vsprojects/vcxproj/grpc/grpc.vcxproj.filters3
-rw-r--r--vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj2
-rw-r--r--vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters3
-rw-r--r--vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj2
-rw-r--r--vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters3
196 files changed, 3222 insertions, 1299 deletions
diff --git a/BUILD b/BUILD
index ed3009d2cd..cc5fd3eb47 100644
--- a/BUILD
+++ b/BUILD
@@ -478,6 +478,7 @@ grpc_cc_library(
"src/core/lib/iomgr/ev_epollsig_linux.c",
"src/core/lib/iomgr/ev_poll_posix.c",
"src/core/lib/iomgr/ev_posix.c",
+ "src/core/lib/iomgr/ev_windows.c",
"src/core/lib/iomgr/exec_ctx.c",
"src/core/lib/iomgr/executor.c",
"src/core/lib/iomgr/iocp_windows.c",
@@ -744,7 +745,7 @@ grpc_cc_library(
"grpc_transport_chttp2_server_insecure",
"grpc_workaround_cronet_compression_filter",
"grpc_server_backward_compatibility",
- ]
+ ],
)
grpc_cc_library(
@@ -1399,22 +1400,22 @@ GRPCXX_PUBLIC_HDRS = [
grpc_cc_library(
name = "grpc++_base",
- hdrs = GRPCXX_HDRS,
srcs = GRPCXX_SRCS,
- public_hdrs = GRPCXX_PUBLIC_HDRS,
+ hdrs = GRPCXX_HDRS,
language = "c++",
+ public_hdrs = GRPCXX_PUBLIC_HDRS,
deps = [
- "grpc++_codegen_base",
"grpc",
+ "grpc++_codegen_base",
],
)
grpc_cc_library(
name = "grpc++_base_unsecure",
- hdrs = GRPCXX_HDRS,
srcs = GRPCXX_SRCS,
- public_hdrs = GRPCXX_PUBLIC_HDRS,
+ hdrs = GRPCXX_HDRS,
language = "c++",
+ public_hdrs = GRPCXX_PUBLIC_HDRS,
deps = [
"grpc++_codegen_base",
"grpc_unsecure",
@@ -1538,5 +1539,4 @@ grpc_cc_library(
],
)
-
grpc_generate_one_off_targets()
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 306b62df0a..d10c0409b6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -947,6 +947,7 @@ add_library(grpc
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
src/core/lib/iomgr/ev_posix.c
+ src/core/lib/iomgr/ev_windows.c
src/core/lib/iomgr/exec_ctx.c
src/core/lib/iomgr/executor.c
src/core/lib/iomgr/iocp_windows.c
@@ -1284,6 +1285,7 @@ add_library(grpc_cronet
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
src/core/lib/iomgr/ev_posix.c
+ src/core/lib/iomgr/ev_windows.c
src/core/lib/iomgr/exec_ctx.c
src/core/lib/iomgr/executor.c
src/core/lib/iomgr/iocp_windows.c
@@ -1602,6 +1604,7 @@ add_library(grpc_test_util
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
src/core/lib/iomgr/ev_posix.c
+ src/core/lib/iomgr/ev_windows.c
src/core/lib/iomgr/exec_ctx.c
src/core/lib/iomgr/executor.c
src/core/lib/iomgr/iocp_windows.c
@@ -1865,6 +1868,7 @@ add_library(grpc_unsecure
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
src/core/lib/iomgr/ev_posix.c
+ src/core/lib/iomgr/ev_windows.c
src/core/lib/iomgr/exec_ctx.c
src/core/lib/iomgr/executor.c
src/core/lib/iomgr/iocp_windows.c
@@ -2295,6 +2299,7 @@ add_library(grpc++
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
src/core/lib/iomgr/ev_posix.c
+ src/core/lib/iomgr/ev_windows.c
src/core/lib/iomgr/exec_ctx.c
src/core/lib/iomgr/executor.c
src/core/lib/iomgr/iocp_windows.c
@@ -2627,6 +2632,7 @@ add_library(grpc++_cronet
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
src/core/lib/iomgr/ev_posix.c
+ src/core/lib/iomgr/ev_windows.c
src/core/lib/iomgr/exec_ctx.c
src/core/lib/iomgr/executor.c
src/core/lib/iomgr/iocp_windows.c
@@ -3403,6 +3409,7 @@ add_library(grpc++_unsecure
src/core/lib/iomgr/ev_epollsig_linux.c
src/core/lib/iomgr/ev_poll_posix.c
src/core/lib/iomgr/ev_posix.c
+ src/core/lib/iomgr/ev_windows.c
src/core/lib/iomgr/exec_ctx.c
src/core/lib/iomgr/executor.c
src/core/lib/iomgr/iocp_windows.c
diff --git a/Makefile b/Makefile
index b007dc790f..e6dd66e12f 100644
--- a/Makefile
+++ b/Makefile
@@ -2924,6 +2924,7 @@ LIBGRPC_SRC = \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
+ src/core/lib/iomgr/ev_windows.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
src/core/lib/iomgr/iocp_windows.c \
@@ -3259,6 +3260,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
+ src/core/lib/iomgr/ev_windows.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
src/core/lib/iomgr/iocp_windows.c \
@@ -3576,6 +3578,7 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
+ src/core/lib/iomgr/ev_windows.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
src/core/lib/iomgr/iocp_windows.c \
@@ -3811,6 +3814,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
+ src/core/lib/iomgr/ev_windows.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
src/core/lib/iomgr/iocp_windows.c \
@@ -4218,6 +4222,7 @@ LIBGRPC++_SRC = \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
+ src/core/lib/iomgr/ev_windows.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
src/core/lib/iomgr/iocp_windows.c \
@@ -4558,6 +4563,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
+ src/core/lib/iomgr/ev_windows.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
src/core/lib/iomgr/iocp_windows.c \
@@ -5324,6 +5330,7 @@ LIBGRPC++_UNSECURE_SRC = \
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
+ src/core/lib/iomgr/ev_windows.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
src/core/lib/iomgr/iocp_windows.c \
diff --git a/binding.gyp b/binding.gyp
index 05ccec5fea..8aafdaa62b 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -680,6 +680,7 @@
'src/core/lib/iomgr/ev_epollsig_linux.c',
'src/core/lib/iomgr/ev_poll_posix.c',
'src/core/lib/iomgr/ev_posix.c',
+ 'src/core/lib/iomgr/ev_windows.c',
'src/core/lib/iomgr/exec_ctx.c',
'src/core/lib/iomgr/executor.c',
'src/core/lib/iomgr/iocp_windows.c',
diff --git a/build.yaml b/build.yaml
index eed0d8dd4d..ecd9ebe5b7 100644
--- a/build.yaml
+++ b/build.yaml
@@ -317,6 +317,7 @@ filegroups:
- src/core/lib/iomgr/ev_epollsig_linux.c
- src/core/lib/iomgr/ev_poll_posix.c
- src/core/lib/iomgr/ev_posix.c
+ - src/core/lib/iomgr/ev_windows.c
- src/core/lib/iomgr/exec_ctx.c
- src/core/lib/iomgr/executor.c
- src/core/lib/iomgr/iocp_windows.c
@@ -4627,7 +4628,6 @@ php_config_m4:
deps:
- grpc
- gpr
- - ares
- boringssl
headers:
- src/php/ext/grpc/byte_buffer.h
@@ -4641,6 +4641,7 @@ php_config_m4:
- src/php/ext/grpc/server.h
- src/php/ext/grpc/server_credentials.h
- src/php/ext/grpc/timeval.h
+ - src/php/ext/grpc/version.h
src:
- src/php/ext/grpc/byte_buffer.c
- src/php/ext/grpc/call.c
diff --git a/composer.json b/composer.json
index 284b57a809..2cf3f17221 100644
--- a/composer.json
+++ b/composer.json
@@ -6,12 +6,15 @@
"homepage": "http://grpc.io",
"license": "BSD-3-Clause",
"require": {
- "php": ">=5.5.0",
- "google/protobuf": "^v3.3.0"
+ "php": ">=5.5.0"
},
"require-dev": {
"google/auth": "v0.9"
},
+ "suggest": {
+ "ext-protobuf": "For better performance, install the protobuf C extension.",
+ "google/protobuf": "To get started using grpc quickly, install the native protobuf library."
+ },
"autoload": {
"psr-4": {
"Grpc\\": "src/php/lib/Grpc/"
diff --git a/config.m4 b/config.m4
index a70284594b..ec463b2243 100644
--- a/config.m4
+++ b/config.m4
@@ -8,23 +8,21 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
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/cares)
- PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/cares)
LIBS="-lpthread $LIBS"
+ CFLAGS="-Wall -Werror -Wno-parentheses-equality -Wno-unused-value -std=c11"
+ CXXFLAGS="-std=c++11"
GRPC_SHARED_LIBADD="-lpthread $GRPC_SHARED_LIBADD"
+ PHP_REQUIRE_CXX()
PHP_ADD_LIBRARY(pthread)
-
PHP_ADD_LIBRARY(dl,,GRPC_SHARED_LIBADD)
PHP_ADD_LIBRARY(dl)
case $host in
*darwin*)
- PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/config_darwin)
;;
*)
- PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/config_linux)
PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD)
PHP_ADD_LIBRARY(rt)
;;
@@ -114,6 +112,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/iomgr/ev_epollsig_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
+ src/core/lib/iomgr/ev_windows.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
src/core/lib/iomgr/iocp_windows.c \
@@ -638,59 +637,9 @@ if test "$PHP_GRPC" != "no"; then
third_party/boringssl/ssl/tls13_server.c \
third_party/boringssl/ssl/tls_method.c \
third_party/boringssl/ssl/tls_record.c \
- third_party/cares/cares/ares__close_sockets.c \
- third_party/cares/cares/ares__get_hostent.c \
- third_party/cares/cares/ares__read_line.c \
- third_party/cares/cares/ares__timeval.c \
- third_party/cares/cares/ares_cancel.c \
- third_party/cares/cares/ares_create_query.c \
- third_party/cares/cares/ares_data.c \
- third_party/cares/cares/ares_destroy.c \
- third_party/cares/cares/ares_expand_name.c \
- third_party/cares/cares/ares_expand_string.c \
- third_party/cares/cares/ares_fds.c \
- third_party/cares/cares/ares_free_hostent.c \
- third_party/cares/cares/ares_free_string.c \
- third_party/cares/cares/ares_getenv.c \
- third_party/cares/cares/ares_gethostbyaddr.c \
- third_party/cares/cares/ares_gethostbyname.c \
- third_party/cares/cares/ares_getnameinfo.c \
- third_party/cares/cares/ares_getopt.c \
- third_party/cares/cares/ares_getsock.c \
- third_party/cares/cares/ares_init.c \
- third_party/cares/cares/ares_library_init.c \
- third_party/cares/cares/ares_llist.c \
- third_party/cares/cares/ares_mkquery.c \
- third_party/cares/cares/ares_nowarn.c \
- third_party/cares/cares/ares_options.c \
- third_party/cares/cares/ares_parse_a_reply.c \
- third_party/cares/cares/ares_parse_aaaa_reply.c \
- third_party/cares/cares/ares_parse_mx_reply.c \
- third_party/cares/cares/ares_parse_naptr_reply.c \
- third_party/cares/cares/ares_parse_ns_reply.c \
- third_party/cares/cares/ares_parse_ptr_reply.c \
- third_party/cares/cares/ares_parse_soa_reply.c \
- third_party/cares/cares/ares_parse_srv_reply.c \
- third_party/cares/cares/ares_parse_txt_reply.c \
- third_party/cares/cares/ares_platform.c \
- third_party/cares/cares/ares_process.c \
- third_party/cares/cares/ares_query.c \
- third_party/cares/cares/ares_search.c \
- third_party/cares/cares/ares_send.c \
- third_party/cares/cares/ares_strcasecmp.c \
- third_party/cares/cares/ares_strdup.c \
- third_party/cares/cares/ares_strerror.c \
- third_party/cares/cares/ares_timeout.c \
- third_party/cares/cares/ares_version.c \
- third_party/cares/cares/ares_writev.c \
- third_party/cares/cares/bitncmp.c \
- third_party/cares/cares/inet_net_pton.c \
- third_party/cares/cares/inet_ntop.c \
- third_party/cares/cares/windows_port.c \
- , $ext_shared, , -Wall -Werror \
- -Wno-parentheses-equality -Wno-unused-value -std=c11 \
- -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN \
- -D_HAS_EXCEPTIONS=0 -DNOMINMAX)
+ , $ext_shared, , -fvisibility=hidden \
+ -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN \
+ -D_HAS_EXCEPTIONS=0 -DNOMINMAX -DGRPC_ARES=0)
PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
@@ -790,6 +739,5 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/x509)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/x509v3)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/ssl)
- PHP_ADD_BUILD_DIR($ext_builddir/third_party/cares/cares)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/nanopb)
fi
diff --git a/doc/PROTOCOL-WEB.md b/doc/PROTOCOL-WEB.md
index 6bb280894a..10998899c4 100644
--- a/doc/PROTOCOL-WEB.md
+++ b/doc/PROTOCOL-WEB.md
@@ -1,4 +1,4 @@
-# Overview
+# gRPC Web
gRPC-Web provides a JS client library that supports the same API
as gRPC-Node to access a gRPC service. Due to browser limitation,
@@ -37,6 +37,8 @@ Content-Type
1. application/grpc-web
* e.g. application/grpc-web+[proto, json, thrift]
+ * the sender should always specify the message format, e.g. +proto, +json
+ * the receiver should assume the default is "+proto" when the message format is missing in Content-Type (as "application/grpc-web")
2. application/grpc-web-text
* text-encoded streams of “application/grpc-web”
* e.g. application/grpc-web-text+[proto, thrift]
diff --git a/doc/compression.md b/doc/compression.md
index de245d90fe..ee22bc3f12 100644
--- a/doc/compression.md
+++ b/doc/compression.md
@@ -1,4 +1,4 @@
-## **gRPC Compression**
+## gRPC Compression
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
@@ -112,7 +112,7 @@ unsupported condition as well as the supported ones. The returned
1. An ill-constructed message with its [Compressed-Flag
bit](PROTOCOL-HTTP2.md#compressed-flag)
set but lacking a
-"[grpc-encoding](PROTOCOL-HTTP2.md#message-encoding)"
+[grpc-encoding](PROTOCOL-HTTP2.md#message-encoding)
entry different from _identity_ in its metadata MUST fail with `INTERNAL`
status, its associated description indicating the invalid Compressed-Flag
condition.
diff --git a/doc/cpp-style-guide.md b/doc/cpp-style-guide.md
index a1f91353fe..8211703d02 100644
--- a/doc/cpp-style-guide.md
+++ b/doc/cpp-style-guide.md
@@ -5,5 +5,4 @@ The majority of gRPC's C++ requirements are drawn from the [Google C++ style
guide] (https://google.github.io/styleguide/cppguide.html). Additionally,
as in C, layout rules are defined by clang-format, and all code
should be passed through clang-format. A (docker-based) script to do
-so is included in [tools/distrib/clang\_format\_code.sh]
-(../tools/distrib/clang_format_code.sh).
+so is included in [tools/distrib/clang_format_code.sh](../tools/distrib/clang_format_code.sh).
diff --git a/doc/fail_fast.md b/doc/fail_fast.md
index 2dd5561fc6..ff3d235397 100644
--- a/doc/fail_fast.md
+++ b/doc/fail_fast.md
@@ -1 +1 @@
-Moved to wait-for-ready.md
+Moved to [wait-for-ready.md](wait-for-ready.md)
diff --git a/doc/service_config.md b/doc/service_config.md
index 8039fcad09..99d985f3bf 100644
--- a/doc/service_config.md
+++ b/doc/service_config.md
@@ -131,8 +131,8 @@ functionality is introduced.
# Architecture
-A service config is associated with a server name. The [name
-resolver](naming.md) plugin, when asked to resolve a particular server
+A service config is associated with a server name. The [name resolver](naming.md)
+plugin, when asked to resolve a particular server
name, will return both the resolved addresses and the service config.
TODO(roth): Design how the service config will be encoded in DNS.
diff --git a/doc/stress_test_framework.md b/doc/stress_test_framework.md
index 18f545e090..2212d9842c 100644
--- a/doc/stress_test_framework.md
+++ b/doc/stress_test_framework.md
@@ -2,7 +2,7 @@
(Sree Kuchibhotla - sreek@)
-> Status: This is implemented. More details at [README.md](https://github.com/grpc/grpc/blob/master/tools/run_tests/stress_test/README.md)
+Status: This is implemented. More details at [README.md](https://github.com/grpc/grpc/blob/master/tools/run_tests/stress_test/README.md)
**I. GOALS**
diff --git a/doc/workarounds.md b/doc/workarounds.md
new file mode 100644
index 0000000000..bc511860f8
--- /dev/null
+++ b/doc/workarounds.md
@@ -0,0 +1,19 @@
+# gRPC Server Backward Compatibility Issues and Workarounds Manageent
+
+## Introduction
+This document lists the workarounds implemented on gRPC servers for record and reference when users need to enable a certain workaround.
+
+## Workaround List
+
+### Cronet Compression
+
+**Workaround ID:** WORKAROUND\_ID\_CRONET\_COMPRESSION
+
+**Date added:** May 06, 2017
+
+**Status:** Implemented in C core and C++
+
+**Issue:** Before version v1.3.0-dev, gRPC iOS client's Cronet transport did not implement compression. However the clients still claim to support compression. As a result, a client fails to parse received message when the message is compressed.
+The problem above was resolved in gRPC v1.3.0-dev. For backward compatibility, a server must forcingly disable compression for gRPC clients of version lower than or equal to v1.3.0-dev.
+
+**Workaround Description:** Implemented as a server channel filter in C core. The filter identifies the version of peer client with incoming `user-agent` header of each call. If the client's gRPC version is lower that or equal to v1.3.x, a flag GRPC_WRITE_NO_COMPRESS is marked for all send_message ops which prevents compression of the messages to be sent out.
diff --git a/examples/php/composer.json b/examples/php/composer.json
index f4b177c271..9d900ebec1 100644
--- a/examples/php/composer.json
+++ b/examples/php/composer.json
@@ -2,7 +2,8 @@
"name": "grpc/grpc-demo",
"description": "gRPC example for PHP",
"require": {
- "grpc/grpc": "^v1.1.0"
+ "grpc/grpc": "^v1.3.0",
+ "google/protobuf": "^v3.3.0"
},
"autoload": {
"psr-4": {
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 9aba44cd6b..1176a15f2b 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -503,6 +503,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/ev_epollsig_linux.c',
'src/core/lib/iomgr/ev_poll_posix.c',
'src/core/lib/iomgr/ev_posix.c',
+ 'src/core/lib/iomgr/ev_windows.c',
'src/core/lib/iomgr/exec_ctx.c',
'src/core/lib/iomgr/executor.c',
'src/core/lib/iomgr/iocp_windows.c',
diff --git a/grpc.gemspec b/grpc.gemspec
index 5ee48c3e24..32c1164456 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -419,6 +419,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/ev_epollsig_linux.c )
s.files += %w( src/core/lib/iomgr/ev_poll_posix.c )
s.files += %w( src/core/lib/iomgr/ev_posix.c )
+ s.files += %w( src/core/lib/iomgr/ev_windows.c )
s.files += %w( src/core/lib/iomgr/exec_ctx.c )
s.files += %w( src/core/lib/iomgr/executor.c )
s.files += %w( src/core/lib/iomgr/iocp_windows.c )
diff --git a/include/grpc++/ext/health_check_service_server_builder_option.h b/include/grpc++/ext/health_check_service_server_builder_option.h
index 4861daacd4..a27841af01 100644
--- a/include/grpc++/ext/health_check_service_server_builder_option.h
+++ b/include/grpc++/ext/health_check_service_server_builder_option.h
@@ -44,8 +44,8 @@ namespace grpc {
class HealthCheckServiceServerBuilderOption : public ServerBuilderOption {
public:
- // The ownership of hc will be taken and transferred to the grpc server.
- // To explicitly disable default service, pass in a nullptr.
+ /// The ownership of hc will be taken and transferred to the grpc server.
+ /// To explicitly disable default service, pass in a nullptr.
explicit HealthCheckServiceServerBuilderOption(
std::unique_ptr<HealthCheckServiceInterface> hc);
~HealthCheckServiceServerBuilderOption() override {}
diff --git a/include/grpc++/ext/proto_server_reflection_plugin.h b/include/grpc++/ext/proto_server_reflection_plugin.h
index 66f39eb876..6497bba905 100644
--- a/include/grpc++/ext/proto_server_reflection_plugin.h
+++ b/include/grpc++/ext/proto_server_reflection_plugin.h
@@ -59,8 +59,8 @@ class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin {
std::shared_ptr<grpc::ProtoServerReflection> reflection_service_;
};
-// Add proto reflection plugin to ServerBuilder. This function should be called
-// at the static initialization time.
+/// Add proto reflection plugin to ServerBuilder. This function should be called
+/// at the static initialization time.
void InitProtoReflectionServerBuilderPlugin();
} // namespace reflection
diff --git a/include/grpc++/generic/generic_stub.h b/include/grpc++/generic/generic_stub.h
index 02c00d0d45..1478846fc8 100644
--- a/include/grpc++/generic/generic_stub.h
+++ b/include/grpc++/generic/generic_stub.h
@@ -43,14 +43,18 @@ class CompletionQueue;
typedef ClientAsyncReaderWriter<ByteBuffer, ByteBuffer>
GenericClientAsyncReaderWriter;
-// Generic stubs provide a type-unsafe interface to call gRPC methods
-// by name.
+/// Generic stubs provide a type-unsafe interface to call gRPC methods
+/// by name.
class GenericStub final {
public:
explicit GenericStub(std::shared_ptr<ChannelInterface> channel)
: channel_(channel) {}
- // begin a call to a named method
+ /// Begin a call to a named method \a method using \a context.
+ /// A tag \a tag will be delivered to \a cq when the call has been started
+ /// (i.e, initial metadata has been sent).
+ /// The return value only indicates whether or not registration of the call
+ /// succeeded (i.e. the call won't proceed if the return value is nullptr).
std::unique_ptr<GenericClientAsyncReaderWriter> Call(
ClientContext* context, const grpc::string& method, CompletionQueue* cq,
void* tag);
diff --git a/include/grpc++/grpc++.h b/include/grpc++/grpc++.h
index daecfea406..978b172346 100644
--- a/include/grpc++/grpc++.h
+++ b/include/grpc++/grpc++.h
@@ -34,14 +34,18 @@
/// \mainpage gRPC C++ API
///
/// The gRPC C++ API mainly consists of the following classes:
+//
/// - grpc::Channel, which represents the connection to an endpoint. See [the
/// gRPC Concepts page](http://www.grpc.io/docs/guides/concepts.html) for more
/// details. Channels are created by the factory function grpc::CreateChannel.
+//
/// - grpc::CompletionQueue, the producer-consumer queue used for all
/// asynchronous communication with the gRPC runtime.
+//
/// - grpc::ClientContext and grpc::ServerContext, where optional configuration
/// for an RPC can be set, such as setting custom metadata to be conveyed to the
/// peer, compression settings, authentication, etc.
+//
/// - grpc::Server, representing a gRPC server, created by grpc::ServerBuilder.
///
/// Streaming calls are handled with the streaming classes in
diff --git a/include/grpc++/health_check_service_interface.h b/include/grpc++/health_check_service_interface.h
index 0eed702683..c1b43199a6 100644
--- a/include/grpc++/health_check_service_interface.h
+++ b/include/grpc++/health_check_service_interface.h
@@ -41,26 +41,27 @@ namespace grpc {
const char kHealthCheckServiceInterfaceArg[] =
"grpc.health_check_service_interface";
-// The gRPC server uses this interface to expose the health checking service
-// without depending on protobuf.
+/// The gRPC server uses this interface to expose the health checking service
+/// without depending on protobuf.
class HealthCheckServiceInterface {
public:
virtual ~HealthCheckServiceInterface() {}
- // Set or change the serving status of the given service_name.
+ /// Set or change the serving status of the given service_name.
virtual void SetServingStatus(const grpc::string& service_name,
bool serving) = 0;
- // Apply to all registered service names.
+ /// Apply to all registered service names.
virtual void SetServingStatus(bool serving) = 0;
};
-// Enable/disable the default health checking service. This applies to all C++
-// servers created afterwards. For each server, user can override the default
-// with a HealthCheckServiceServerBuilderOption.
-// NOT thread safe.
+/// Enable/disable the default health checking service. This applies to all C++
+/// servers created afterwards. For each server, user can override the default
+/// with a HealthCheckServiceServerBuilderOption.
+/// NOT thread safe.
void EnableDefaultHealthCheckService(bool enable);
-// NOT thread safe.
+/// Returns whether the default health checking service is enabled.
+/// NOT thread safe.
bool DefaultHealthCheckServiceEnabled();
} // namespace grpc
diff --git a/include/grpc++/impl/codegen/async_stream.h b/include/grpc++/impl/codegen/async_stream.h
index f97d824baf..04fc5241cb 100644
--- a/include/grpc++/impl/codegen/async_stream.h
+++ b/include/grpc++/impl/codegen/async_stream.h
@@ -53,16 +53,38 @@ class ClientAsyncStreamingInterface {
/// Request notification of the reading of the initial metadata. Completion
/// will be notified by \a tag on the associated completion queue.
/// This call is optional, but if it is used, it cannot be used concurrently
- /// with or after the \a Read method.
+ /// with or after the \a AsyncReaderInterface::Read method.
///
/// \param[in] tag Tag identifying this request.
virtual void ReadInitialMetadata(void* tag) = 0;
- /// Indicate that the stream is to be finished and request notification
- /// Should not be used concurrently with other operations
+ /// Indicate that the stream is to be finished and request notification for
+ /// when the call has been ended.
+ /// Should not be used concurrently with other operations.
+ ///
+ /// It is appropriate to call this method when both:
+ /// * the client side has no more message to send
+ /// (this can be declared implicitly by calling this method, or
+ /// explicitly through an earlier call to the <i>WritesDone</i> method
+ /// of the class in use, e.g. \a ClientAsyncWriterInterface::WritesDone or
+ /// \a ClientAsyncReaderWriterInterface::WritesDone).
+ /// * there are no more messages to be received from the server (this can
+ /// be known implicitly by the calling code, or explicitly from an
+ /// earlier call to \a AsyncReaderInterface::Read that yielded a failed
+ /// result, e.g. cq->Next(&read_tag, &ok) filled in 'ok' with 'false').
+ ///
+ /// This function will return when either:
+ /// - all incoming messages have been read and the server has returned
+ /// a status.
+ /// - the server has returned a non-OK status.
+ /// - the call failed for some reason and the library generated a
+ /// status.
+ ///
+ /// Note that implementations of this method attempt to receive initial
+ /// metadata from the server if initial metadata hasn't yet been received.
///
- /// \param[out] status To be updated with the operation status.
/// \param[in] tag Tag identifying this request.
+ /// \param[out] status To be updated with the operation status.
virtual void Finish(Status* status, void* tag) = 0;
};
@@ -77,11 +99,14 @@ class AsyncReaderInterface {
/// This is thread-safe with respect to \a Write or \a WritesDone methods. It
/// should not be called concurrently with other streaming APIs
/// on the same stream. It is not meaningful to call it concurrently
- /// with another \a Read on the same stream since reads on the same stream
- /// are delivered in order.
+ /// with another \a AsyncReaderInterface::Read on the same stream since reads
+ /// on the same stream are delivered in order.
///
/// \param[out] msg Where to eventually store the read message.
/// \param[in] tag The tag identifying the operation.
+ ///
+ /// Side effect: note that this method attempt to receive initial metadata for
+ /// a stream if it hasn't yet been received.
virtual void Read(R* msg, void* tag) = 0;
};
@@ -96,7 +121,7 @@ class AsyncWriterInterface {
/// Only one write may be outstanding at any given time. This means that
/// after calling Write, one must wait to receive \a tag from the completion
/// queue BEFORE calling Write again.
- /// This is thread-safe with respect to \a Read
+ /// This is thread-safe with respect to \a AsyncReaderInterface::Read
///
/// \param[in] msg The message to be written.
/// \param[in] tag The tag identifying the operation.
@@ -109,7 +134,7 @@ class AsyncWriterInterface {
/// after calling Write, one must wait to receive \a tag from the completion
/// queue BEFORE calling Write again.
/// WriteOptions \a options is used to set the write options of this message.
- /// This is thread-safe with respect to \a Read
+ /// This is thread-safe with respect to \a AsyncReaderInterface::Read
///
/// \param[in] msg The message to be written.
/// \param[in] options The WriteOptions to be used to write this message.
@@ -117,11 +142,11 @@ class AsyncWriterInterface {
virtual void Write(const W& msg, WriteOptions options, void* tag) = 0;
/// Request the writing of \a msg and coalesce it with the writing
- /// of trailing metadata, using WriteOptions \a options with identifying tag
- /// \a tag.
+ /// of trailing metadata, using WriteOptions \a options with
+ /// identifying tag \a tag.
///
- /// For client, WriteLast is equivalent of performing Write and WritesDone in
- /// a single step.
+ /// For client, WriteLast is equivalent of performing Write and
+ /// WritesDone in a single step.
/// For server, WriteLast buffers the \a msg. The writing of \a msg is held
/// until Finish is called, where \a msg and trailing metadata are coalesced
/// and write is initiated. Note that WriteLast can only buffer \a msg up to
@@ -140,10 +165,17 @@ template <class R>
class ClientAsyncReaderInterface : public ClientAsyncStreamingInterface,
public AsyncReaderInterface<R> {};
+/// Async client-side API for doing server-streaming RPCs,
+/// where the incoming message stream coming from the server has
+/// messages of type \a R.
template <class R>
class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
public:
/// Create a stream and write the first request out.
+ /// \a tag will be notified on \a cq when the call has been started and
+ /// \a request has been written out.
+ /// Note that \a context will be used to fill in custom initial metadata
+ /// used to send to the server when starting the call.
template <class W>
static ClientAsyncReader* Create(ChannelInterface* channel,
CompletionQueue* cq, const RpcMethod& method,
@@ -160,6 +192,14 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
assert(size == sizeof(ClientAsyncReader));
}
+ /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata
+ /// method for semantics.
+ ///
+ /// Side effect:
+ /// - upon receiving initial metadata from the server,
+ /// the \a ClientContext associated with this call is updated, and the
+ /// calling code can access the received metadata through the
+ /// \a ClientContext.
void ReadInitialMetadata(void* tag) override {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
@@ -177,6 +217,11 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
call_.PerformOps(&read_ops_);
}
+ /// See the \a ClientAsyncStreamingInterface.Finish method for semantics.
+ ///
+ /// Side effect:
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible initial and trailing metadata received from the server.
void Finish(Status* status, void* tag) override {
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
@@ -214,16 +259,27 @@ template <class W>
class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W> {
public:
- /// Signal the client is done with the writes.
- /// Thread-safe with respect to \a Read
+ /// Signal the client is done with the writes (half-close the client stream).
+ /// Thread-safe with respect to \a AsyncReaderInterface::Read
///
/// \param[in] tag The tag identifying the operation.
virtual void WritesDone(void* tag) = 0;
};
+/// Async API on the client side for doing client-streaming RPCs,
+/// where the outgoing message stream going to the server contains
+/// messages of type \a W.
template <class W>
class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
public:
+ /// Create a stream and write the first request out.
+ /// \a tag will be notified on \a cq when the call has been started (i.e.
+ /// intitial metadata sent) and \a request has been written out.
+ /// Note that \a context will be used to fill in custom initial metadata
+ /// used to send to the server when starting the call.
+ /// \a response will be filled in with the single expected response
+ /// message from the server upon a successful call to the \a Finish
+ /// method of this instance.
template <class R>
static ClientAsyncWriter* Create(ChannelInterface* channel,
CompletionQueue* cq, const RpcMethod& method,
@@ -240,6 +296,13 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
assert(size == sizeof(ClientAsyncWriter));
}
+ /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method for
+ /// semantics.
+ ///
+ /// Side effect:
+ /// - upon receiving initial metadata from the server, the \a ClientContext
+ /// associated with this call is updated, and the calling code can access
+ /// the received metadata through the \a ClientContext.
void ReadInitialMetadata(void* tag) override {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
@@ -272,6 +335,13 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
call_.PerformOps(&write_ops_);
}
+ /// See the \a ClientAsyncStreamingInterface.Finish method for semantics.
+ ///
+ /// Side effect:
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible initial and trailing metadata received from the server.
+ /// - attempts to fill in the \a response parameter passed to this class's
+ /// constructor with the server's response message.
void Finish(Status* status, void* tag) override {
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
@@ -310,23 +380,34 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
finish_ops_;
};
-/// Client-side interface for asynchronous bi-directional streaming.
+/// Async client-side interface for bi-directional streaming,
+/// where the client-to-server message stream has messages of type \a W,
+/// and the server-to-client message stream has messages of type \a R.
template <class W, class R>
class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> {
public:
- /// Signal the client is done with the writes.
- /// Thread-safe with respect to \a Read
+ /// Signal the client is done with the writes (half-close the client stream).
+ /// Thread-safe with respect to \a AsyncReaderInterface::Read
///
/// \param[in] tag The tag identifying the operation.
virtual void WritesDone(void* tag) = 0;
};
+/// Async client-side interface for bi-directional streaming,
+/// where the outgoing message stream going to the server
+/// has messages of type \a W, and the incoming message stream coming
+/// from the server has messages of type \a R.
template <class W, class R>
class ClientAsyncReaderWriter final
: public ClientAsyncReaderWriterInterface<W, R> {
public:
+ /// Create a stream and write the first request out.
+ /// \a tag will be notified on \a cq when the call has been started (i.e.
+ /// intitial metadata sent).
+ /// Note that \a context will be used to fill in custom initial metadata
+ /// used to send to the server when starting the call.
static ClientAsyncReaderWriter* Create(ChannelInterface* channel,
CompletionQueue* cq,
const RpcMethod& method,
@@ -343,6 +424,13 @@ class ClientAsyncReaderWriter final
assert(size == sizeof(ClientAsyncReaderWriter));
}
+ /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method
+ /// for semantics of this method.
+ ///
+ /// Side effect:
+ /// - upon receiving initial metadata from the server, the \a ClientContext
+ /// is updated with it, and then the receiving initial metadata can
+ /// be accessed through this \a ClientContext.
void ReadInitialMetadata(void* tag) override {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
@@ -384,6 +472,10 @@ class ClientAsyncReaderWriter final
call_.PerformOps(&write_ops_);
}
+ /// See the \a ClientAsyncStreamingInterface.Finish method for semantics.
+ /// Side effect
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible initial and trailing metadata sent from the server.
void Finish(Status* status, void* tag) override {
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
@@ -422,17 +514,62 @@ template <class W, class R>
class ServerAsyncReaderInterface : public ServerAsyncStreamingInterface,
public AsyncReaderInterface<R> {
public:
+ /// Indicate that the stream is to be finished with a certain status code
+ /// and also send out \a msg response to the client.
+ /// Request notification for when the server has sent the response and the
+ /// appropriate signals to the client to end the call.
+ /// Should not be used concurrently with other operations.
+ ///
+ /// It is appropriate to call this method when:
+ /// * all messages from the client have been received (either known
+ /// implictly, or explicitly because a previous
+ /// \a AsyncReaderInterface::Read operation with a non-ok result,
+ /// e.g., cq->Next(&read_tag, &ok) filled in 'ok' with 'false').
+ ///
+ /// This operation will end when the server has finished sending out initial
+ /// metadata (if not sent already), response message, and status, or if
+ /// some failure occurred when trying to do so.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[in] status To be sent to the client as the result of this call.
+ /// \param[in] msg To be sent to the client as the response for this call.
virtual void Finish(const W& msg, const Status& status, void* tag) = 0;
+ /// Indicate that the stream is to be finished with a certain
+ /// non-OK status code.
+ /// Request notification for when the server has sent the appropriate
+ /// signals to the client to end the call.
+ /// Should not be used concurrently with other operations.
+ ///
+ /// This call is meant to end the call with some error, and can be called at
+ /// any point that the server would like to "fail" the call (though note
+ /// this shouldn't be called concurrently with any other "sending" call, like
+ /// \a AsyncWriterInterface::Write).
+ ///
+ /// This operation will end when the server has finished sending out initial
+ /// metadata (if not sent already), and status, or if some failure occurred
+ /// when trying to do so.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[in] status To be sent to the client as the result of this call.
+ /// - Note: \a status must have a non-OK code.
virtual void FinishWithError(const Status& status, void* tag) = 0;
};
+/// Async server-side API for doing client-streaming RPCs,
+/// where the incoming message stream from the client has messages of type \a R,
+/// and the single response message sent from the server is type \a W.
template <class W, class R>
class ServerAsyncReader final : public ServerAsyncReaderInterface<W, R> {
public:
explicit ServerAsyncReader(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
+ /// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - The initial metadata that will be sent to the client from this op will
+ /// be taken from the \a ServerContext associated with the call.
void SendInitialMetadata(void* tag) override {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
@@ -452,6 +589,14 @@ class ServerAsyncReader final : public ServerAsyncReaderInterface<W, R> {
call_.PerformOps(&read_ops_);
}
+ /// See the \a ServerAsyncReaderInterface.Read method for semantics
+ ///
+ /// Side effect:
+ /// - also sends initial metadata if not alreay sent.
+ /// - uses the \a ServerContext associated with this call to send possible
+ /// initial and trailing metadata.
+ ///
+ /// Note: \a msg is not sent if \a status has a non-OK code.
void Finish(const W& msg, const Status& status, void* tag) override {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
@@ -472,6 +617,12 @@ class ServerAsyncReader final : public ServerAsyncReaderInterface<W, R> {
call_.PerformOps(&finish_ops_);
}
+ /// See the \a ServerAsyncReaderInterface.Read method for semantics
+ ///
+ /// Side effect:
+ /// - also sends initial metadata if not alreay sent.
+ /// - uses the \a ServerContext associated with this call to send possible
+ /// initial and trailing metadata.
void FinishWithError(const Status& status, void* tag) override {
GPR_CODEGEN_ASSERT(!status.ok());
finish_ops_.set_output_tag(tag);
@@ -503,14 +654,32 @@ template <class W>
class ServerAsyncWriterInterface : public ServerAsyncStreamingInterface,
public AsyncWriterInterface<W> {
public:
+ /// Indicate that the stream is to be finished with a certain status code.
+ /// Request notification for when the server has sent the appropriate
+ /// signals to the client to end the call.
+ /// Should not be used concurrently with other operations.
+ ///
+ /// It is appropriate to call this method when either:
+ /// * all messages from the client have been received (either known
+ /// implictly, or explicitly because a previous \a
+ /// AsyncReaderInterface::Read operation with a non-ok
+ /// result (e.g., cq->Next(&read_tag, &ok) filled in 'ok' with 'false'.
+ /// * it is desired to end the call early with some non-OK status code.
+ ///
+ /// This operation will end when the server has finished sending out initial
+ /// metadata (if not sent already), response message, and status, or if
+ /// some failure occurred when trying to do so.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[in] status To be sent to the client as the result of this call.
virtual void Finish(const Status& status, void* tag) = 0;
/// Request the writing of \a msg and coalesce it with trailing metadata which
- /// contains \a status, using WriteOptions options with identifying tag \a
- /// tag.
+ /// contains \a status, using WriteOptions options with
+ /// identifying tag \a tag.
///
- /// WriteAndFinish is equivalent of performing WriteLast and Finish in a
- /// single step.
+ /// WriteAndFinish is equivalent of performing WriteLast and Finish
+ /// in a single step.
///
/// \param[in] msg The message to be written.
/// \param[in] options The WriteOptions to be used to write this message.
@@ -520,12 +689,21 @@ class ServerAsyncWriterInterface : public ServerAsyncStreamingInterface,
const Status& status, void* tag) = 0;
};
+/// Async server-side API for doing server streaming RPCs,
+/// where the outgoing message stream from the server has messages of type \a W.
template <class W>
class ServerAsyncWriter final : public ServerAsyncWriterInterface<W> {
public:
explicit ServerAsyncWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
+ /// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - The initial metadata that will be sent to the client from this op will
+ /// be taken from the \a ServerContext associated with the call.
+ ///
+ /// \param[in] tag Tag identifying this request.
void SendInitialMetadata(void* tag) override {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
@@ -559,6 +737,13 @@ class ServerAsyncWriter final : public ServerAsyncWriterInterface<W> {
call_.PerformOps(&write_ops_);
}
+ /// See the \a ServerAsyncWriterInterface.WriteAndFinish method for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - the \a ServerContext associated with this call is used
+ /// for sending trailing (and initial) metadata to the client.
+ ///
+ /// Note: \a status must have an OK code.
void WriteAndFinish(const W& msg, WriteOptions options, const Status& status,
void* tag) override {
write_ops_.set_output_tag(tag);
@@ -569,6 +754,14 @@ class ServerAsyncWriter final : public ServerAsyncWriterInterface<W> {
call_.PerformOps(&write_ops_);
}
+ /// See the \a ServerAsyncWriterInterface.Finish method for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - the \a ServerContext associated with this call is used for sending
+ /// trailing (and initial if not already sent) metadata to the client.
+ ///
+ /// Note: there are no restrictions are the code of
+ /// \a status,it may be non-OK
void Finish(const Status& status, void* tag) override {
finish_ops_.set_output_tag(tag);
EnsureInitialMetadataSent(&finish_ops_);
@@ -606,11 +799,30 @@ class ServerAsyncReaderWriterInterface : public ServerAsyncStreamingInterface,
public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> {
public:
+ /// Indicate that the stream is to be finished with a certain status code.
+ /// Request notification for when the server has sent the appropriate
+ /// signals to the client to end the call.
+ /// Should not be used concurrently with other operations.
+ ///
+ /// It is appropriate to call this method when either:
+ /// * all messages from the client have been received (either known
+ /// implictly, or explicitly because a previous \a
+ /// AsyncReaderInterface::Read operation
+ /// with a non-ok result (e.g., cq->Next(&read_tag, &ok) filled in 'ok'
+ /// with 'false'.
+ /// * it is desired to end the call early with some non-OK status code.
+ ///
+ /// This operation will end when the server has finished sending out initial
+ /// metadata (if not sent already), response message, and status, or if some
+ /// failure occurred when trying to do so.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[in] status To be sent to the client as the result of this call.
virtual void Finish(const Status& status, void* tag) = 0;
/// Request the writing of \a msg and coalesce it with trailing metadata which
- /// contains \a status, using WriteOptions options with identifying tag \a
- /// tag.
+ /// contains \a status, using WriteOptions options with
+ /// identifying tag \a tag.
///
/// WriteAndFinish is equivalent of performing WriteLast and Finish in a
/// single step.
@@ -623,6 +835,10 @@ class ServerAsyncReaderWriterInterface : public ServerAsyncStreamingInterface,
const Status& status, void* tag) = 0;
};
+/// Async server-side API for doing bidirectional streaming RPCs,
+/// where the incoming message stream coming from the client has messages of
+/// type \a R, and the outgoing message stream coming from the server has
+/// messages of type \a W.
template <class W, class R>
class ServerAsyncReaderWriter final
: public ServerAsyncReaderWriterInterface<W, R> {
@@ -630,6 +846,13 @@ class ServerAsyncReaderWriter final
explicit ServerAsyncReaderWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
+ /// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - The initial metadata that will be sent to the client from this op will
+ /// be taken from the \a ServerContext associated with the call.
+ ///
+ /// \param[in] tag Tag identifying this request.
void SendInitialMetadata(void* tag) override {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
@@ -667,6 +890,14 @@ class ServerAsyncReaderWriter final
call_.PerformOps(&write_ops_);
}
+ /// See the \a ServerAsyncReaderWriterInterface.WriteAndFinish
+ /// method for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - the \a ServerContext associated with this call is used
+ /// for sending trailing (and initial) metadata to the client.
+ ///
+ /// Note: \a status must have an OK code.
void WriteAndFinish(const W& msg, WriteOptions options, const Status& status,
void* tag) override {
write_ops_.set_output_tag(tag);
@@ -677,6 +908,14 @@ class ServerAsyncReaderWriter final
call_.PerformOps(&write_ops_);
}
+ /// See the \a ServerAsyncReaderWriterInterface.Finish method for semantics.
+ ///
+ /// Implicit input parameter:
+ /// - the \a ServerContext associated with this call is used for sending
+ /// trailing (and initial if not already sent) metadata to the client.
+ ///
+ /// Note: there are no restrictions are the code of \a status,
+ /// it may be non-OK
void Finish(const Status& status, void* tag) override {
finish_ops_.set_output_tag(tag);
EnsureInitialMetadataSent(&finish_ops_);
diff --git a/include/grpc++/impl/codegen/async_unary_call.h b/include/grpc++/impl/codegen/async_unary_call.h
index a147a6acbf..aadf77d8a8 100644
--- a/include/grpc++/impl/codegen/async_unary_call.h
+++ b/include/grpc++/impl/codegen/async_unary_call.h
@@ -47,18 +47,49 @@ namespace grpc {
class CompletionQueue;
extern CoreCodegenInterface* g_core_codegen_interface;
+/// An interface relevant for async client side unary RPCS (which send
+/// one request message to a server and receive one response message).
template <class R>
class ClientAsyncResponseReaderInterface {
public:
virtual ~ClientAsyncResponseReaderInterface() {}
+
+ /// Request notification of the reading of initial metadata. Completion
+ /// will be notified by \a tag on the associated completion queue.
+ /// This call is optional, but if it is used, it cannot be used concurrently
+ /// with or after the \a Finish method.
+ ///
+ /// \param[in] tag Tag identifying this request.
virtual void ReadInitialMetadata(void* tag) = 0;
+
+ /// Request to receive the server's response \a msg and final \a status for
+ /// the call, and to notify \a tag on this call's completion queue when
+ /// finished.
+ ///
+ /// This function will return when either:
+ /// - when the server's response message and status have been received.
+ /// - when the server has returned a non-OK status (no message expected in
+ /// this case).
+ /// - when the call failed for some reason and the library generated a
+ /// non-OK status.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[out] status To be updated with the operation status.
+ /// \param[out] msg To be filled in with the server's response message.
virtual void Finish(R* msg, Status* status, void* tag) = 0;
};
+/// Async API for client-side unary RPCs, where the message response
+/// received from the server is of type \a R.
template <class R>
class ClientAsyncResponseReader final
: public ClientAsyncResponseReaderInterface<R> {
public:
+ /// Start a call and write the request out.
+ /// \a tag will be notified on \a cq when the call has been started (i.e.
+ /// intitial metadata sent) and \a request has been written out.
+ /// Note that \a context will be used to fill in custom initial metadata
+ /// used to send to the server when starting the call.
template <class W>
static ClientAsyncResponseReader* Create(ChannelInterface* channel,
CompletionQueue* cq,
@@ -76,6 +107,12 @@ class ClientAsyncResponseReader final
assert(size == sizeof(ClientAsyncResponseReader));
}
+ /// See \a ClientAsyncResponseReaderInterface::ReadInitialMetadata for
+ /// semantics.
+ ///
+ /// Side effect:
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible initial and trailing metadata sent from the serve.
void ReadInitialMetadata(void* tag) {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
@@ -84,6 +121,11 @@ class ClientAsyncResponseReader final
call_.PerformOps(&meta_buf_);
}
+ /// See \a ClientAysncResponseReaderInterface::Finish for semantics.
+ ///
+ /// Side effect:
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible initial and trailing metadata sent from the server.
void Finish(R* msg, Status* status, void* tag) {
finish_buf_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
@@ -123,12 +165,21 @@ class ClientAsyncResponseReader final
finish_buf_;
};
+/// Async server-side API for handling unary calls, where the single
+/// response message sent to the client is of type \a W.
template <class W>
class ServerAsyncResponseWriter final : public ServerAsyncStreamingInterface {
public:
explicit ServerAsyncResponseWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
+ /// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
+ ///
+ /// Side effect:
+ /// The initial metadata that will be sent to the client from this op will
+ /// be taken from the \a ServerContext associated with the call.
+ ///
+ /// \param[in] tag Tag identifying this request.
void SendInitialMetadata(void* tag) override {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
@@ -142,6 +193,21 @@ class ServerAsyncResponseWriter final : public ServerAsyncStreamingInterface {
call_.PerformOps(&meta_buf_);
}
+ /// Indicate that the stream is to be finished and request notification
+ /// when the server has sent the appropriate signals to the client to
+ /// end the call. Should not be used concurrently with other operations.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[in] status To be sent to the client as the result of the call.
+ /// \param[in] msg Message to be sent to the client.
+ ///
+ /// Side effect:
+ /// - also sends initial metadata if not already sent (using the
+ /// \a ServerContext associated with this call).
+ ///
+ /// Note: if \a status has a non-OK code, then \a msg will not be sent,
+ /// and the client will receive only the status with possible trailing
+ /// metadata.
void Finish(const W& msg, const Status& status, void* tag) {
finish_buf_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
@@ -162,6 +228,18 @@ class ServerAsyncResponseWriter final : public ServerAsyncStreamingInterface {
call_.PerformOps(&finish_buf_);
}
+ /// Indicate that the stream is to be finished with a non-OK status,
+ /// and request notification for when the server has finished sending the
+ /// appropriate signals to the client to end the call.
+ /// Should not be used concurrently with other operations.
+ ///
+ /// \param[in] tag Tag identifying this request.
+ /// \param[in] status To be sent to the client as the result of the call.
+ /// - Note: \a status must have a non-OK code.
+ ///
+ /// Side effect:
+ /// - also sends initial metadata if not already sent (using the
+ /// \a ServerContext associated with this call).
void FinishWithError(const Status& status, void* tag) {
GPR_CODEGEN_ASSERT(!status.ok());
finish_buf_.set_output_tag(tag);
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index 9fe2bbb75e..bbd0fc2dc8 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -634,10 +634,10 @@ class SneakyCallOpSet : public CallOpSet<Op1, Op2, Op3, Op4, Op5, Op6> {
}
};
-// Straightforward wrapping of the C call object
+/// Straightforward wrapping of the C call object
class Call final {
public:
- /* call is owned by the caller */
+ /** call is owned by the caller */
Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
: call_hook_(call_hook),
cq_(cq),
diff --git a/include/grpc++/impl/codegen/call_hook.h b/include/grpc++/impl/codegen/call_hook.h
index 6a8258233d..85a5f86ab7 100644
--- a/include/grpc++/impl/codegen/call_hook.h
+++ b/include/grpc++/impl/codegen/call_hook.h
@@ -39,7 +39,8 @@ namespace grpc {
class CallOpSetInterface;
class Call;
-/// Channel and Server implement this to allow them to hook performing ops
+/// This is an interface that Channel and Server implement to allow them to hook
+/// performing ops.
class CallHook {
public:
virtual ~CallHook() {}
diff --git a/include/grpc++/impl/codegen/client_context.h b/include/grpc++/impl/codegen/client_context.h
index 3c50e6ba9d..b1b9be0fe2 100644
--- a/include/grpc++/impl/codegen/client_context.h
+++ b/include/grpc++/impl/codegen/client_context.h
@@ -151,6 +151,20 @@ namespace testing {
class InteropClientContextInspector;
} // namespace testing
+/// A ClientContext allows the person implementing a service client to:
+///
+/// - Add custom metadata key-value pairs that will propagated to the server
+/// side.
+/// - Control call settings such as compression and authentication.
+/// - Initial and trailing metadata coming from the server.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call they are invoked with, that
+/// is to say, they aren't sticky. Some of these settings, such as the
+/// compression options, can be made persistant at channel construction time
+/// (see \a grpc::CreateCustomChannel).
+///
+/// \warning ClientContext instances should \em not be reused across rpcs.
class ClientContext {
public:
ClientContext();
@@ -178,9 +192,8 @@ class ClientContext {
///
/// \param meta_key The metadata key. If \a meta_value is binary data, it must
/// end in "-bin".
- /// \param meta_value The metadata value. If its value is binary, it must be
- /// base64-encoding (see https://tools.ietf.org/html/rfc4648#section-4) and \a
- /// meta_key must end in "-bin".
+ /// \param meta_value The metadata value. If its value is binary, the key name
+ /// must end in "-bin".
void AddMetadata(const grpc::string& meta_key,
const grpc::string& meta_value);
@@ -222,13 +235,24 @@ class ClientContext {
deadline_ = deadline_tp.raw_time();
}
- /// EXPERIMENTAL: Set this request to be idempotent
+ /// EXPERIMENTAL: Indicate that this request is idempotent.
+ /// By default, RPCs are assumed to <i>not</i> be idempotent.
+ ///
+ /// If true, the gRPC library assumes that it's safe to initiate
+ /// this RPC multiple times.
void set_idempotent(bool idempotent) { idempotent_ = idempotent; }
- /// EXPERIMENTAL: Set this request to be cacheable
+ /// EXPERIMENTAL: Set this request to be cacheable.
+ /// If set, grpc is free to use the HTTP GET verb for sending the request,
+ /// with the possibility of receiving a cached respone.
void set_cacheable(bool cacheable) { cacheable_ = cacheable; }
- /// EXPERIMENTAL: Trigger wait-for-ready or not on this request
+ /// EXPERIMENTAL: Trigger wait-for-ready or not on this request.
+ /// See https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md.
+ /// If set, if an RPC is made when a channel's connectivity state is
+ /// TRANSIENT_FAILURE or CONNECTING, the call will not "fail fast",
+ /// and the channel will wait until the channel is READY before making the
+ /// call.
void set_wait_for_ready(bool wait_for_ready) {
wait_for_ready_ = wait_for_ready;
wait_for_ready_explicitly_set_ = true;
@@ -325,8 +349,8 @@ class ClientContext {
};
static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
- // Should be used for framework-level extensions only.
- // Applications never need to call this method.
+ /// Should be used for framework-level extensions only.
+ /// Applications never need to call this method.
grpc_call* c_call() { return call_; }
private:
diff --git a/include/grpc++/impl/codegen/client_unary_call.h b/include/grpc++/impl/codegen/client_unary_call.h
index 4bf35ae778..b923498db8 100644
--- a/include/grpc++/impl/codegen/client_unary_call.h
+++ b/include/grpc++/impl/codegen/client_unary_call.h
@@ -47,7 +47,7 @@ class ClientContext;
class CompletionQueue;
class RpcMethod;
-// Wrapper that performs a blocking unary call
+/// Wrapper that performs a blocking unary call
template <class InputMessage, class OutputMessage>
Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context, const InputMessage& request,
diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h
index c8ab726b0f..57333d7158 100644
--- a/include/grpc++/impl/codegen/completion_queue.h
+++ b/include/grpc++/impl/codegen/completion_queue.h
@@ -159,7 +159,8 @@ class CompletionQueue : private GrpcLibraryCodegen {
/// will start to return false and \a AsyncNext will return \a
/// NextStatus::SHUTDOWN. Only once either one of these methods does that
/// (that is, once the queue has been \em drained) can an instance of this
- /// class be destroyed.
+ /// class be destroyed. Also note that applications must ensure that
+ /// no work is enqueued on this completion queue after this method is called.
void Shutdown();
/// Returns a \em raw pointer to the underlying \a grpc_completion_queue
diff --git a/include/grpc++/impl/codegen/completion_queue_tag.h b/include/grpc++/impl/codegen/completion_queue_tag.h
index 19a08500cf..0affc818e8 100644
--- a/include/grpc++/impl/codegen/completion_queue_tag.h
+++ b/include/grpc++/impl/codegen/completion_queue_tag.h
@@ -40,10 +40,10 @@ namespace grpc {
class CompletionQueueTag {
public:
virtual ~CompletionQueueTag() {}
- // Called prior to returning from Next(), return value is the status of the
- // operation (return status is the default thing to do). If this function
- // returns false, the tag is dropped and not returned from the completion
- // queue
+ /// Called prior to returning from Next(), return value is the status of the
+ /// operation (return status is the default thing to do). If this function
+ /// returns false, the tag is dropped and not returned from the completion
+ /// queue
virtual bool FinalizeResult(void** tag, bool* status) = 0;
};
diff --git a/include/grpc++/impl/codegen/config.h b/include/grpc++/impl/codegen/config.h
index a43bf65f91..79352eee3c 100644
--- a/include/grpc++/impl/codegen/config.h
+++ b/include/grpc++/impl/codegen/config.h
@@ -39,9 +39,9 @@
#define GRPC_CUSTOM_STRING std::string
#endif
-// The following macros are deprecated and appear only for users
-// with PB files generated using gRPC 1.0.x plugins. They should
-// not be used in new code
+/// The following macros are deprecated and appear only for users
+/// with PB files generated using gRPC 1.0.x plugins. They should
+/// not be used in new code
#define GRPC_OVERRIDE override // deprecated
#define GRPC_FINAL final // deprecated
diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h
index 83b569ce74..8dfaf5883c 100644
--- a/include/grpc++/impl/codegen/method_handler_impl.h
+++ b/include/grpc++/impl/codegen/method_handler_impl.h
@@ -40,7 +40,7 @@
namespace grpc {
-// A wrapper class of an application provided rpc method handler.
+/// A wrapper class of an application provided rpc method handler.
template <class ServiceType, class RequestType, class ResponseType>
class RpcMethodHandler : public MethodHandler {
public:
@@ -77,7 +77,7 @@ class RpcMethodHandler : public MethodHandler {
}
private:
- // Application provided rpc handler function.
+ /// Application provided rpc handler function.
std::function<Status(ServiceType*, ServerContext*, const RequestType*,
ResponseType*)>
func_;
@@ -85,7 +85,7 @@ class RpcMethodHandler : public MethodHandler {
ServiceType* service_;
};
-// A wrapper class of an application provided client streaming handler.
+/// A wrapper class of an application provided client streaming handler.
template <class ServiceType, class RequestType, class ResponseType>
class ClientStreamingHandler : public MethodHandler {
public:
@@ -125,7 +125,7 @@ class ClientStreamingHandler : public MethodHandler {
ServiceType* service_;
};
-// A wrapper class of an application provided server streaming handler.
+/// A wrapper class of an application provided server streaming handler.
template <class ServiceType, class RequestType, class ResponseType>
class ServerStreamingHandler : public MethodHandler {
public:
@@ -166,13 +166,13 @@ class ServerStreamingHandler : public MethodHandler {
ServiceType* service_;
};
-// A wrapper class of an application provided bidi-streaming handler.
-// This also applies to server-streamed implementation of a unary method
-// with the additional requirement that such methods must have done a
-// write for status to be ok
-// Since this is used by more than 1 class, the service is not passed in.
-// Instead, it is expected to be an implicitly-captured argument of func
-// (through bind or something along those lines)
+/// A wrapper class of an application provided bidi-streaming handler.
+/// This also applies to server-streamed implementation of a unary method
+/// with the additional requirement that such methods must have done a
+/// write for status to be ok
+/// Since this is used by more than 1 class, the service is not passed in.
+/// Instead, it is expected to be an implicitly-captured argument of func
+/// (through bind or something along those lines)
template <class Streamer, bool WriteNeeded>
class TemplatedBidiStreamingHandler : public MethodHandler {
public:
@@ -249,7 +249,7 @@ class SplitServerStreamingHandler
ServerSplitStreamer<RequestType, ResponseType>, false>(func) {}
};
-// Handle unknown method by returning UNIMPLEMENTED error.
+/// Handle unknown method by returning UNIMPLEMENTED error.
class UnknownMethodHandler : public MethodHandler {
public:
template <class T>
diff --git a/include/grpc++/impl/codegen/rpc_method.h b/include/grpc++/impl/codegen/rpc_method.h
index 4897428074..ca7527507c 100644
--- a/include/grpc++/impl/codegen/rpc_method.h
+++ b/include/grpc++/impl/codegen/rpc_method.h
@@ -40,6 +40,7 @@
namespace grpc {
+/// Descriptor of an RPC method
class RpcMethod {
public:
enum RpcType {
diff --git a/include/grpc++/impl/codegen/rpc_service_method.h b/include/grpc++/impl/codegen/rpc_service_method.h
index eb8f9a1096..96bb739c99 100644
--- a/include/grpc++/impl/codegen/rpc_service_method.h
+++ b/include/grpc++/impl/codegen/rpc_service_method.h
@@ -52,7 +52,7 @@ namespace grpc {
class ServerContext;
class StreamContextInterface;
-// Base class for running an RPC handler.
+/// Base class for running an RPC handler.
class MethodHandler {
public:
virtual ~MethodHandler() {}
@@ -67,17 +67,17 @@ class MethodHandler {
virtual void RunHandler(const HandlerParameter& param) = 0;
};
-// Server side rpc method class
+/// Server side rpc method class
class RpcServiceMethod : public RpcMethod {
public:
- // Takes ownership of the handler
+ /// Takes ownership of the handler
RpcServiceMethod(const char* name, RpcMethod::RpcType type,
MethodHandler* handler)
: RpcMethod(name, type), server_tag_(nullptr), handler_(handler) {}
void set_server_tag(void* tag) { server_tag_ = tag; }
void* server_tag() const { return server_tag_; }
- // if MethodHandler is nullptr, then this is an async method
+ /// if MethodHandler is nullptr, then this is an async method
MethodHandler* handler() const { return handler_.get(); }
void ResetHandler() { handler_.reset(); }
void SetHandler(MethodHandler* handler) { handler_.reset(handler); }
diff --git a/include/grpc++/impl/codegen/security/auth_context.h b/include/grpc++/impl/codegen/security/auth_context.h
index 75f2482346..e83877bcaf 100644
--- a/include/grpc++/impl/codegen/security/auth_context.h
+++ b/include/grpc++/impl/codegen/security/auth_context.h
@@ -99,7 +99,7 @@ class AuthContext {
virtual AuthPropertyIterator begin() const = 0;
virtual AuthPropertyIterator end() const = 0;
- // Mutation functions: should only be used by an AuthMetadataProcessor.
+ /// Mutation functions: should only be used by an AuthMetadataProcessor.
virtual void AddProperty(const grpc::string& key,
const grpc::string_ref& value) = 0;
virtual bool SetPeerIdentityPropertyName(const grpc::string& name) = 0;
diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h
index ada304d571..48967c2e68 100644
--- a/include/grpc++/impl/codegen/server_context.h
+++ b/include/grpc++/impl/codegen/server_context.h
@@ -91,63 +91,128 @@ class InteropServerContextInspector;
class ServerContextTestSpouse;
} // namespace testing
-// Interface of server side rpc context.
+/// A ServerContext allows the person implementing a service handler to:
+///
+/// - Add custom initial and trailing metadata key-value pairs that will
+/// propagated to the client side.
+/// - Control call settings such as compression and authentication.
+/// - Access metadata coming from the client.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call handler they are supplied to,
+/// that is to say, they aren't sticky across multiple calls. Some of these
+/// settings, such as the compression options, can be made persistant at server
+/// construction time by specifying the approriate \a ChannelArguments
+/// to a \a grpc::ServerBuilder, via \a ServerBuilder::AddChannelArgument.
+///
+/// \warning ServerContext instances should \em not be reused across rpcs.
class ServerContext {
public:
ServerContext(); // for async calls
~ServerContext();
+ /// Return the deadline for the server call.
std::chrono::system_clock::time_point deadline() const {
return Timespec2Timepoint(deadline_);
}
+ /// Return a \a gpr_timespec representation of the server call's deadline.
gpr_timespec raw_deadline() const { return deadline_; }
+ /// Add the (\a meta_key, \a meta_value) pair to the initial metadata
+ /// associated with a server call. These are made available at the client side
+ /// by the \a grpc::ClientContext::GetServerInitialMetadata() method.
+ ///
+ /// \warning This method should only be called before sending initial metadata
+ /// to the client (which can happen explicitly, or implicitly when sending a
+ /// a response message or status to the client).
+ ///
+ /// \param meta_key The metadata key. If \a meta_value is binary data, it must
+ /// end in "-bin".
+ /// \param meta_value The metadata value. If its value is binary, the key name
+ /// must end in "-bin".
void AddInitialMetadata(const grpc::string& key, const grpc::string& value);
+
+ /// Add the (\a meta_key, \a meta_value) pair to the initial metadata
+ /// associated with a server call. These are made available at the client
+ /// side by the \a grpc::ClientContext::GetServerTrailingMetadata() method.
+ ///
+ /// \warning This method should only be called before sending trailing
+ /// metadata to the client (which happens when the call is finished and a
+ /// status is sent to the client).
+ ///
+ /// \param meta_key The metadata key. If \a meta_value is binary data,
+ /// it must end in "-bin".
+ /// \param meta_value The metadata value. If its value is binary, the key name
+ /// must end in "-bin".
void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
- // IsCancelled is always safe to call when using sync API
- // When using async API, it is only safe to call IsCancelled after
- // the AsyncNotifyWhenDone tag has been delivered
+ /// IsCancelled is always safe to call when using sync API.
+ /// When using async API, it is only safe to call IsCancelled after
+ /// the AsyncNotifyWhenDone tag has been delivered.
bool IsCancelled() const;
- // Cancel the Call from the server. This is a best-effort API and depending on
- // when it is called, the RPC may still appear successful to the client.
- // For example, if TryCancel() is called on a separate thread, it might race
- // with the server handler which might return success to the client before
- // TryCancel() was even started by the thread.
- //
- // It is the caller's responsibility to prevent such races and ensure that if
- // TryCancel() is called, the serverhandler must return Status::CANCELLED. The
- // only exception is that if the serverhandler is already returning an error
- // status code, it is ok to not return Status::CANCELLED even if TryCancel()
- // was called.
+ /// Cancel the Call from the server. This is a best-effort API and
+ /// depending on when it is called, the RPC may still appear successful to
+ /// the client.
+ /// For example, if TryCancel() is called on a separate thread, it might race
+ /// with the server handler which might return success to the client before
+ /// TryCancel() was even started by the thread.
+ ///
+ /// It is the caller's responsibility to prevent such races and ensure that if
+ /// TryCancel() is called, the serverhandler must return Status::CANCELLED.
+ /// The only exception is that if the serverhandler is already returning an
+ /// error status code, it is ok to not return Status::CANCELLED even if
+ /// TryCancel() was called.
void TryCancel() const;
+ /// Return a collection of initial metadata key-value pairs sent from the
+ /// client. Note that keys may happen more than
+ /// once (ie, a \a std::multimap is returned).
+ ///
+ /// It is safe to use this method after initial metadata has been received,
+ /// Calls always begin with the client sending initial metadata, so this is
+ /// safe to access as soon as the call has begun on the server side.
+ ///
+ /// \return A multimap of initial metadata key-value pairs from the server.
const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata()
const {
return *client_metadata_.map();
}
+ /// Return the compression algorithm to be used by the server call.
grpc_compression_level compression_level() const {
return compression_level_;
}
+ /// Set \a algorithm to be the compression algorithm used for the server call.
+ ///
+ /// \param algorithm The compression algorithm used for the server call.
void set_compression_level(grpc_compression_level level) {
compression_level_set_ = true;
compression_level_ = level;
}
+ /// Return a bool indicating whether the compression level for this call
+ /// has been set (either implicitly or through a previous call to
+ /// \a set_compression_level.
bool compression_level_set() const { return compression_level_set_; }
+ /// Return the compression algorithm to be used by the server call.
grpc_compression_algorithm compression_algorithm() const {
return compression_algorithm_;
}
+ /// Set \a algorithm to be the compression algorithm used for the server call.
+ ///
+ /// \param algorithm The compression algorithm used for the server call.
void set_compression_algorithm(grpc_compression_algorithm algorithm);
- // Set the load reporting costs in \a cost_data for the call.
+ /// Set the load reporting costs in \a cost_data for the call.
void SetLoadReportingCosts(const std::vector<grpc::string>& cost_data);
+ /// Return the authentication context for this server call.
+ ///
+ /// \see grpc::AuthContext.
std::shared_ptr<const AuthContext> auth_context() const {
if (auth_context_.get() == nullptr) {
auth_context_ = CreateAuthContext(call_);
@@ -155,24 +220,25 @@ class ServerContext {
return auth_context_;
}
- // Return the peer uri in a string.
- // WARNING: this value is never authenticated or subject to any security
- // related code. It must not be used for any authentication related
- // functionality. Instead, use auth_context.
+ /// Return the peer uri in a string.
+ /// WARNING: this value is never authenticated or subject to any security
+ /// related code. It must not be used for any authentication related
+ /// functionality. Instead, use auth_context.
grpc::string peer() const;
+ /// Get the census context associated with this server call.
const struct census_context* census_context() const;
- // Async only. Has to be called before the rpc starts.
- // Returns the tag in completion queue when the rpc finishes.
- // IsCancelled() can then be called to check whether the rpc was cancelled.
+ /// Async only. Has to be called before the rpc starts.
+ /// Returns the tag in completion queue when the rpc finishes.
+ /// IsCancelled() can then be called to check whether the rpc was cancelled.
void AsyncNotifyWhenDone(void* tag) {
has_notify_when_done_tag_ = true;
async_notify_when_done_tag_ = tag;
}
- // Should be used for framework-level extensions only.
- // Applications never need to call this method.
+ /// Should be used for framework-level extensions only.
+ /// Applications never need to call this method.
grpc_call* c_call() { return call_; }
private:
@@ -205,14 +271,14 @@ class ServerContext {
friend class UnknownMethodHandler;
friend class ::grpc::ClientContext;
- // Prevent copying.
+ /// Prevent copying.
ServerContext(const ServerContext&);
ServerContext& operator=(const ServerContext&);
class CompletionOp;
void BeginCompletionOp(Call* call);
- // Return the tag queued by BeginCompletionOp()
+ /// Return the tag queued by BeginCompletionOp()
CompletionQueueTag* GetCompletionOpTag();
ServerContext(gpr_timespec deadline, grpc_metadata_array* arr);
diff --git a/include/grpc++/impl/codegen/service_type.h b/include/grpc++/impl/codegen/service_type.h
index bd65ea009e..b88019164d 100644
--- a/include/grpc++/impl/codegen/service_type.h
+++ b/include/grpc++/impl/codegen/service_type.h
@@ -54,6 +54,12 @@ class ServerAsyncStreamingInterface {
public:
virtual ~ServerAsyncStreamingInterface() {}
+ /// Request notification of the sending of initial metadata to the client.
+ /// Completion will be notified by \a tag on the associated completion
+ /// queue. This call is optional, but if it is used, it cannot be used
+ /// concurrently with or after the \a Finish method.
+ ///
+ /// \param[in] tag Tag identifying this request.
virtual void SendInitialMetadata(void* tag) = 0;
private:
@@ -61,6 +67,7 @@ class ServerAsyncStreamingInterface {
virtual void BindCall(Call* call) = 0;
};
+/// Desriptor of an RPC service and its various RPC methods
class Service {
public:
Service() : server_(nullptr) {}
@@ -155,7 +162,7 @@ class Service {
// From the server's point of view, streamed unary is a special
// case of BIDI_STREAMING that has 1 read and 1 write, in that order,
// and split server-side streaming is BIDI_STREAMING with 1 read and
- // any number of writes, in that order
+ // any number of writes, in that order.
methods_[index]->SetMethodType(::grpc::RpcMethod::BIDI_STREAMING);
}
diff --git a/include/grpc++/impl/codegen/status_code_enum.h b/include/grpc++/impl/codegen/status_code_enum.h
index 9a90a18e2a..c3d27fa3b0 100644
--- a/include/grpc++/impl/codegen/status_code_enum.h
+++ b/include/grpc++/impl/codegen/status_code_enum.h
@@ -136,6 +136,11 @@ enum StatusCode {
/// The service is currently unavailable. This is a most likely a transient
/// condition and may be corrected by retrying with a backoff.
///
+ /// \warning Although data MIGHT not have been transmitted when this
+ /// status occurs, there is NOT A GUARANTEE that the server has not seen
+ /// anything. So in general it is unsafe to retry on this status code
+ /// if the call is non-idempotent.
+ ///
/// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
/// and UNAVAILABLE.
UNAVAILABLE = 14,
diff --git a/include/grpc++/impl/codegen/string_ref.h b/include/grpc++/impl/codegen/string_ref.h
index 003793823c..4ed11b1b6c 100644
--- a/include/grpc++/impl/codegen/string_ref.h
+++ b/include/grpc++/impl/codegen/string_ref.h
@@ -55,14 +55,14 @@ namespace grpc {
/// compatibility.
class string_ref {
public:
- // types
+ /// types
typedef const char* const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- // constants
+ /// constants
const static size_t npos;
- // construct/copy.
+ /// construct/copy.
string_ref() : data_(nullptr), length_(0) {}
string_ref(const string_ref& other)
: data_(other.data_), length_(other.length_) {}
@@ -76,7 +76,7 @@ class string_ref {
string_ref(const char* s, size_t l) : data_(s), length_(l) {}
string_ref(const grpc::string& s) : data_(s.data()), length_(s.length()) {}
- // iterators
+ /// iterators
const_iterator begin() const { return data_; }
const_iterator end() const { return data_ + length_; }
const_iterator cbegin() const { return data_; }
@@ -94,16 +94,16 @@ class string_ref {
return const_reverse_iterator(begin());
}
- // capacity
+ /// capacity
size_t size() const { return length_; }
size_t length() const { return length_; }
size_t max_size() const { return length_; }
bool empty() const { return length_ == 0; }
- // element access
+ /// element access
const char* data() const { return data_; }
- // string operations
+ /// string operations
int compare(string_ref x) const {
size_t min_size = length_ < x.length_ ? length_ : x.length_;
int r = memcmp(data_, x.data_, min_size);
@@ -144,7 +144,7 @@ class string_ref {
size_t length_;
};
-// Comparison operators
+/// Comparison operators
inline bool operator==(string_ref x, string_ref y) { return x.compare(y) == 0; }
inline bool operator!=(string_ref x, string_ref y) { return x.compare(y) != 0; }
inline bool operator<(string_ref x, string_ref y) { return x.compare(y) < 0; }
diff --git a/include/grpc++/impl/codegen/stub_options.h b/include/grpc++/impl/codegen/stub_options.h
index 8e966a8dbf..41aef19ab0 100644
--- a/include/grpc++/impl/codegen/stub_options.h
+++ b/include/grpc++/impl/codegen/stub_options.h
@@ -36,6 +36,7 @@
namespace grpc {
+/// Useful interface for generated stubs
class StubOptions {};
} // namespace grpc
diff --git a/include/grpc++/impl/codegen/sync_stream.h b/include/grpc++/impl/codegen/sync_stream.h
index a010924cef..db9048d7e5 100644
--- a/include/grpc++/impl/codegen/sync_stream.h
+++ b/include/grpc++/impl/codegen/sync_stream.h
@@ -50,16 +50,30 @@ class ClientStreamingInterface {
public:
virtual ~ClientStreamingInterface() {}
- /// Wait until the stream finishes, and return the final status. When the
- /// client side declares it has no more message to send, either implicitly or
- /// by calling \a WritesDone(), it needs to make sure there is no more message
- /// to be received from the server, either implicitly or by getting a false
- /// from a \a Read().
+ /// Block waiting until the stream finishes and a final status of the call is
+ /// available.
+ ///
+ /// It is appropriate to call this method when both:
+ /// * the calling code (client-side) has no more message to send
+ /// (this can be declared implicitly by calling this method, or
+ /// explicitly through an earlier call to <i>WritesDone</i> method of the
+ /// class in use, e.g. \a ClientWriterInterface::WritesDone or
+ /// \a ClientReaderWriterInterface::WritesDone).
+ /// * there are no more messages to be received from the server (which can
+ /// be known implicitly, or explicitly from an earlier call to \a
+ /// ReaderInterface::Read that returned "false").
///
/// This function will return either:
- /// - when all incoming messages have been read and the server has returned
+ /// - when all incoming messages have been read and the server has
+ /// returned status.
+ /// - when the server has returned a non-OK status.
+ /// - OR when the call failed for some reason and the library generated a
/// status.
- /// - OR when the server has returned a non-OK status.
+ ///
+ /// Return values:
+ /// - \a Status contains the status code, message and details for the call
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible trailing metadata sent from the server.
virtual Status Finish() = 0;
};
@@ -68,7 +82,12 @@ class ServerStreamingInterface {
public:
virtual ~ServerStreamingInterface() {}
- /// Blocking send initial metadata to client.
+ /// Block to send initial metadata to client.
+ /// This call is optional, but if it is used, it cannot be used concurrently
+ /// with or after the \a Finish method.
+ ///
+ /// The initial metadata that will be sent to the client will be
+ /// taken from the \a ServerContext associated with the call.
virtual void SendInitialMetadata() = 0;
};
@@ -78,10 +97,11 @@ class ReaderInterface {
public:
virtual ~ReaderInterface() {}
- /// Upper bound on the next message size available for reading on this stream
+ /// Get an upper bound on the next message size available for reading on this
+ /// stream.
virtual bool NextMessageSize(uint32_t* sz) = 0;
- /// Blocking read a message and parse to \a msg. Returns \a true on success.
+ /// Block to read a message and parse to \a msg. Returns \a true on success.
/// This is thread-safe with respect to \a Write or \WritesDone methods on
/// the same stream. It should not be called concurrently with another \a
/// Read on the same stream as the order of delivery will not be defined.
@@ -100,8 +120,8 @@ class WriterInterface {
public:
virtual ~WriterInterface() {}
- /// Blocking write \a msg to the stream with WriteOptions \a options.
- /// This is thread-safe with respect to \a Read
+ /// Block to write \a msg to the stream with WriteOptions \a options.
+ /// This is thread-safe with respect to \a ReaderInterface::Read
///
/// \param msg The message to be written to the stream.
/// \param options The WriteOptions affecting the write operation.
@@ -109,8 +129,8 @@ class WriterInterface {
/// \return \a true on success, \a false when the stream has been closed.
virtual bool Write(const W& msg, WriteOptions options) = 0;
- /// Blocking write \a msg to the stream with default write options.
- /// This is thread-safe with respect to \a Read
+ /// Block to write \a msg to the stream with default write options.
+ /// This is thread-safe with respect to \a ReaderInterface::Read
///
/// \param msg The message to be written to the stream.
///
@@ -122,12 +142,12 @@ class WriterInterface {
///
/// For client, WriteLast is equivalent of performing Write and WritesDone in
/// a single step. \a msg and trailing metadata are coalesced and sent on wire
- /// by calling this function.
- /// For server, WriteLast buffers the \a msg. The writing of \a msg is held
- /// until the service handler returns, where \a msg and trailing metadata are
- /// coalesced and sent on wire. Note that WriteLast can only buffer \a msg up
- /// to the flow control window size. If \a msg size is larger than the window
- /// size, it will be sent on wire without buffering.
+ /// by calling this function. For server, WriteLast buffers the \a msg.
+ /// The writing of \a msg is held until the service handler returns,
+ /// where \a msg and trailing metadata are coalesced and sent on wire.
+ /// Note that WriteLast can only buffer \a msg up to the flow control window
+ /// size. If \a msg size is larger than the window size, it will be sent on
+ /// wire without buffering.
///
/// \param[in] msg The message to be written to the stream.
/// \param[in] options The WriteOptions to be used to write this message.
@@ -141,17 +161,22 @@ template <class R>
class ClientReaderInterface : public ClientStreamingInterface,
public ReaderInterface<R> {
public:
- /// Blocking wait for initial metadata from server. The received metadata
+ /// Block to wait for initial metadata from server. The received metadata
/// can only be accessed after this call returns. Should only be called before
/// the first read. Calling this method is optional, and if it is not called
/// the metadata will be available in ClientContext after the first read.
virtual void WaitForInitialMetadata() = 0;
};
+/// Synchronous (blocking) client-side API for doing server-streaming RPCs,
+/// where the stream of messages coming from the server has messages
+/// of type \a R.
template <class R>
class ClientReader final : public ClientReaderInterface<R> {
public:
- /// Blocking create a stream and write the first request out.
+ /// Block to create a stream and write the initial metadata and \a request
+ /// out. Note that \a context will be used to fill in custom initial
+ /// metadata used to send to the server when starting the call.
template <class W>
ClientReader(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context, const W& request)
@@ -172,6 +197,13 @@ class ClientReader final : public ClientReaderInterface<R> {
cq_.Pluck(&ops);
}
+ /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
+ /// semantics.
+ ///
+ // Side effect:
+ /// Once complete, the initial metadata read from
+ /// the server will be accessable through the \a ClientContext used to
+ /// construct this object.
void WaitForInitialMetadata() override {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
@@ -186,6 +218,11 @@ class ClientReader final : public ClientReaderInterface<R> {
return true;
}
+ /// See the \a ReaderInterface.Read method for semantics.
+ /// Side effect:
+ /// This also receives initial metadata from the server, if not
+ /// already received (if initial metadata is received, it can be then
+ /// accessed through the \a ClientContext associated with this call).
bool Read(R* msg) override {
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> ops;
if (!context_->initial_metadata_received_) {
@@ -196,6 +233,11 @@ class ClientReader final : public ClientReaderInterface<R> {
return cq_.Pluck(&ops) && ops.got_message;
}
+ /// See the \a ClientStreamingInterface.Finish method for semantics.
+ ///
+ /// Side effect:
+ /// The \a ClientContext associated with this call is updated with
+ /// possible metadata received from the server.
Status Finish() override {
CallOpSet<CallOpClientRecvStatus> ops;
Status status;
@@ -211,23 +253,31 @@ class ClientReader final : public ClientReaderInterface<R> {
Call call_;
};
-/// Client-side interface for streaming writes of message of type \a W.
+/// Client-side interface for streaming writes of message type \a W.
template <class W>
class ClientWriterInterface : public ClientStreamingInterface,
public WriterInterface<W> {
public:
- /// Half close writing from the client.
- /// Block until currently-pending writes are completed.
- /// Thread safe with respect to \a Read operations only
+ /// Half close writing from the client. (signal that the stream of messages
+ /// coming from the clinet is complete).
+ /// Blocks until currently-pending writes are completed.
+ /// Thread safe with respect to \a ReaderInterface::Read operations only
///
/// \return Whether the writes were successful.
virtual bool WritesDone() = 0;
};
+/// Synchronous (blocking) client-side API for doing client-streaming RPCs,
+/// where the outgoing message stream coming from the client has messages of
+/// type \a W.
template <class W>
class ClientWriter : public ClientWriterInterface<W> {
public:
- /// Blocking create a stream.
+ /// Block to create a stream (i.e. send request headers and other initial
+ /// metadata to the server). Note that \a context will be used to fill
+ /// in custom initial metadata. \a response will be filled in with the
+ /// single expected response message from the server upon a successful
+ /// call to the \a Finish method of this instance.
template <class R>
ClientWriter(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context, R* response)
@@ -248,6 +298,12 @@ class ClientWriter : public ClientWriterInterface<W> {
}
}
+ /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
+ /// semantics.
+ ///
+ // Side effect:
+ /// Once complete, the initial metadata read from the server will be
+ /// accessable through the \a ClientContext used to construct this object.
void WaitForInitialMetadata() {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
@@ -257,6 +313,12 @@ class ClientWriter : public ClientWriterInterface<W> {
cq_.Pluck(&ops); // status ignored
}
+ /// See the WriterInterface.Write(const W& msg, WriteOptions options) method
+ /// for semantics.
+ ///
+ /// Side effect:
+ /// Also sends initial metadata if not already sent (using the
+ /// \a ClientContext associated with this call).
using WriterInterface<W>::Write;
bool Write(const W& msg, WriteOptions options) override {
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
@@ -287,7 +349,12 @@ class ClientWriter : public ClientWriterInterface<W> {
return cq_.Pluck(&ops);
}
- /// Read the final response and wait for the final status.
+ /// See the ClientStreamingInterface.Finish method for semantics.
+ /// Side effects:
+ /// - Also receives initial metadata if not already received.
+ /// - Attempts to fill in the \a response parameter passed
+ /// to the constructor of this instance with the response
+ /// message from the server.
Status Finish() override {
Status status;
if (!context_->initial_metadata_received_) {
@@ -308,29 +375,39 @@ class ClientWriter : public ClientWriterInterface<W> {
Call call_;
};
-/// Client-side interface for bi-directional streaming.
+/// Client-side interface for bi-directional streaming with
+/// client-to-server stream messages of type \a W and
+/// server-to-client stream messages of type \a R.
template <class W, class R>
class ClientReaderWriterInterface : public ClientStreamingInterface,
public WriterInterface<W>,
public ReaderInterface<R> {
public:
- /// Blocking wait for initial metadata from server. The received metadata
+ /// Block to wait for initial metadata from server. The received metadata
/// can only be accessed after this call returns. Should only be called before
/// the first read. Calling this method is optional, and if it is not called
/// the metadata will be available in ClientContext after the first read.
virtual void WaitForInitialMetadata() = 0;
- /// Block until currently-pending writes are completed.
- /// Thread-safe with respect to \a Read
+ /// Half close writing from the client. (signal that the stream of messages
+ /// coming from the clinet is complete).
+ /// Blocks until currently-pending writes are completed.
+ /// Thread-safe with respect to \a ReaderInterface::Read
///
/// \return Whether the writes were successful.
virtual bool WritesDone() = 0;
};
+/// Synchronous (blocking) client-side API for bi-directional streaming RPCs,
+/// where the outgoing message stream coming from the client has messages of
+/// type \a W, and the incoming messages stream coming from the server has
+/// messages of type \a R.
template <class W, class R>
class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
public:
- /// Blocking create a stream.
+ /// Block to create a stream and write the initial metadata and \a request
+ /// out. Note that \a context will be used to fill in custom initial metadata
+ /// used to send to the server when starting the call.
ClientReaderWriter(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context)
: context_(context),
@@ -347,6 +424,12 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
}
}
+ /// Block waiting to read initial metadata from the server.
+ /// This call is optional, but if it is used, it cannot be used concurrently
+ /// with or after the \a Finish method.
+ ///
+ /// Once complete, the initial metadata read from the server will be
+ /// accessable through the \a ClientContext used to construct this object.
void WaitForInitialMetadata() override {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
@@ -361,6 +444,10 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
return true;
}
+ /// See the \a ReaderInterface.Read method for semantics.
+ /// Side effect:
+ /// Also receives initial metadata if not already received (updates the \a
+ /// ClientContext associated with this call in that case).
bool Read(R* msg) override {
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> ops;
if (!context_->initial_metadata_received_) {
@@ -371,6 +458,11 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
return cq_.Pluck(&ops) && ops.got_message;
}
+ /// See the \a WriterInterface.Write method for semantics.
+ ///
+ /// Side effect:
+ /// Also sends initial metadata if not already sent (using the
+ /// \a ClientContext associated with this call to fill in values).
using WriterInterface<W>::Write;
bool Write(const W& msg, WriteOptions options) override {
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
@@ -401,6 +493,11 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
return cq_.Pluck(&ops);
}
+ /// See the ClientStreamingInterface.Finish method for semantics.
+ ///
+ /// Side effect:
+ /// - the \a ClientContext associated with this call is updated with
+ /// possible trailing metadata sent from the server.
Status Finish() override {
CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> ops;
if (!context_->initial_metadata_received_) {
@@ -424,11 +521,17 @@ template <class R>
class ServerReaderInterface : public ServerStreamingInterface,
public ReaderInterface<R> {};
+/// Synchronous (blocking) server-side API for doing client-streaming RPCs,
+/// where the incoming message stream coming from the client has messages of
+/// type \a R.
template <class R>
class ServerReader final : public ServerReaderInterface<R> {
public:
ServerReader(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
+ /// See the \a ServerStreamingInterface.SendInitialMetadata method
+ /// for semantics. Note that initial metadata will be affected by the
+ /// \a ServerContext associated with this call.
void SendInitialMetadata() override {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
@@ -465,11 +568,18 @@ template <class W>
class ServerWriterInterface : public ServerStreamingInterface,
public WriterInterface<W> {};
+/// Synchronous (blocking) server-side API for doing for doing a
+/// server-streaming RPCs, where the outgoing message stream coming from the
+/// server has messages of type \a W.
template <class W>
class ServerWriter final : public ServerWriterInterface<W> {
public:
ServerWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
+ /// See the \a ServerStreamingInterface.SendInitialMetadata method
+ /// for semantics.
+ /// Note that initial metadata will be affected by the
+ /// \a ServerContext associated with this call.
void SendInitialMetadata() override {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
@@ -484,6 +594,11 @@ class ServerWriter final : public ServerWriterInterface<W> {
call_->cq()->Pluck(&ops);
}
+ /// See the \a WriterInterface.Write method for semantics.
+ ///
+ /// Side effect:
+ /// Also sends initial metadata if not already sent (using the
+ /// \a ClientContext associated with this call to fill in values).
using WriterInterface<W>::Write;
bool Write(const W& msg, WriteOptions options) override {
if (options.is_last_message()) {
@@ -516,7 +631,7 @@ class ServerReaderWriterInterface : public ServerStreamingInterface,
public WriterInterface<W>,
public ReaderInterface<R> {};
-// Actual implementation of bi-directional streaming
+/// Actual implementation of bi-directional streaming
namespace internal {
template <class W, class R>
class ServerReaderWriterBody final {
@@ -576,12 +691,18 @@ class ServerReaderWriterBody final {
};
} // namespace internal
-// class to represent the user API for a bidirectional streaming call
+/// Synchronous (blocking) server-side API for a bidirectional
+/// streaming call, where the incoming message stream coming from the client has
+/// messages of type \a R, and the outgoing message streaming coming from
+/// the server has messages of type \a W.
template <class W, class R>
class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> {
public:
ServerReaderWriter(Call* call, ServerContext* ctx) : body_(call, ctx) {}
+ /// See the \a ServerStreamingInterface.SendInitialMetadata method
+ /// for semantics. Note that initial metadata will be affected by the
+ /// \a ServerContext associated with this call.
void SendInitialMetadata() override { body_.SendInitialMetadata(); }
bool NextMessageSize(uint32_t* sz) override {
@@ -590,6 +711,11 @@ class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> {
bool Read(R* msg) override { return body_.Read(msg); }
+ /// See the \a WriterInterface.Write(const W& msg, WriteOptions options)
+ /// method for semantics.
+ /// Side effect:
+ /// Also sends initial metadata if not already sent (using the \a
+ /// ServerContext associated with this call).
using WriterInterface<W>::Write;
bool Write(const W& msg, WriteOptions options) override {
return body_.Write(msg, options);
@@ -604,8 +730,7 @@ class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> {
/// through a unary call on the client side, but the server responds to it
/// as though it were a single-ping-pong streaming call. The server can use
/// the \a NextMessageSize method to determine an upper-bound on the size of
-/// the message.
-/// A key difference relative to streaming: ServerUnaryStreamer
+/// the message. A key difference relative to streaming: ServerUnaryStreamer
/// must have exactly 1 Read and exactly 1 Write, in that order, to function
/// correctly. Otherwise, the RPC is in error.
template <class RequestType, class ResponseType>
@@ -615,12 +740,27 @@ class ServerUnaryStreamer final
ServerUnaryStreamer(Call* call, ServerContext* ctx)
: body_(call, ctx), read_done_(false), write_done_(false) {}
+ /// Block to send initial metadata to client.
+ /// Implicit input parameter:
+ /// - the \a ServerContext associated with this call will be used for
+ /// sending initial metadata.
void SendInitialMetadata() override { body_.SendInitialMetadata(); }
+ /// Get an upper bound on the request message size from the client.
bool NextMessageSize(uint32_t* sz) override {
return body_.NextMessageSize(sz);
}
+ /// Read a message of type \a R into \a msg. Completion will be notified by \a
+ /// tag on the associated completion queue.
+ /// This is thread-safe with respect to \a Write or \a WritesDone methods. It
+ /// should not be called concurrently with other streaming APIs
+ /// on the same stream. It is not meaningful to call it concurrently
+ /// with another \a ReaderInterface::Read on the same stream since reads on
+ /// the same stream are delivered in order.
+ ///
+ /// \param[out] msg Where to eventually store the read message.
+ /// \param[in] tag The tag identifying the operation.
bool Read(RequestType* request) override {
if (read_done_) {
return false;
@@ -629,6 +769,13 @@ class ServerUnaryStreamer final
return body_.Read(request);
}
+ /// Block to write \a msg to the stream with WriteOptions \a options.
+ /// This is thread-safe with respect to \a ReaderInterface::Read
+ ///
+ /// \param msg The message to be written to the stream.
+ /// \param options The WriteOptions affecting the write operation.
+ ///
+ /// \return \a true on success, \a false when the stream has been closed.
using WriterInterface<ResponseType>::Write;
bool Write(const ResponseType& response, WriteOptions options) override {
if (write_done_ || !read_done_) {
@@ -656,12 +803,27 @@ class ServerSplitStreamer final
ServerSplitStreamer(Call* call, ServerContext* ctx)
: body_(call, ctx), read_done_(false) {}
+ /// Block to send initial metadata to client.
+ /// Implicit input parameter:
+ /// - the \a ServerContext associated with this call will be used for
+ /// sending initial metadata.
void SendInitialMetadata() override { body_.SendInitialMetadata(); }
+ /// Get an upper bound on the request message size from the client.
bool NextMessageSize(uint32_t* sz) override {
return body_.NextMessageSize(sz);
}
+ /// Read a message of type \a R into \a msg. Completion will be notified by \a
+ /// tag on the associated completion queue.
+ /// This is thread-safe with respect to \a Write or \a WritesDone methods. It
+ /// should not be called concurrently with other streaming APIs
+ /// on the same stream. It is not meaningful to call it concurrently
+ /// with another \a ReaderInterface::Read on the same stream since reads on
+ /// the same stream are delivered in order.
+ ///
+ /// \param[out] msg Where to eventually store the read message.
+ /// \param[in] tag The tag identifying the operation.
bool Read(RequestType* request) override {
if (read_done_) {
return false;
@@ -670,6 +832,13 @@ class ServerSplitStreamer final
return body_.Read(request);
}
+ /// Block to write \a msg to the stream with WriteOptions \a options.
+ /// This is thread-safe with respect to \a ReaderInterface::Read
+ ///
+ /// \param msg The message to be written to the stream.
+ /// \param options The WriteOptions affecting the write operation.
+ ///
+ /// \return \a true on success, \a false when the stream has been closed.
using WriterInterface<ResponseType>::Write;
bool Write(const ResponseType& response, WriteOptions options) override {
return read_done_ && body_.Write(response, options);
diff --git a/include/grpc++/impl/codegen/time.h b/include/grpc++/impl/codegen/time.h
index e090ece756..81ca7bb3de 100644
--- a/include/grpc++/impl/codegen/time.h
+++ b/include/grpc++/impl/codegen/time.h
@@ -39,17 +39,16 @@
namespace grpc {
-/* If you are trying to use CompletionQueue::AsyncNext with a time class that
- isn't either gpr_timespec or std::chrono::system_clock::time_point, you
- will most likely be looking at this comment as your compiler will have
- fired an error below. In order to fix this issue, you have two potential
- solutions:
-
- 1. Use gpr_timespec or std::chrono::system_clock::time_point instead
- 2. Specialize the TimePoint class with whichever time class that you
- want to use here. See below for two examples of how to do this.
+/** If you are trying to use CompletionQueue::AsyncNext with a time class that
+ isn't either gpr_timespec or std::chrono::system_clock::time_point, you
+ will most likely be looking at this comment as your compiler will have
+ fired an error below. In order to fix this issue, you have two potential
+ solutions:
+
+ 1. Use gpr_timespec or std::chrono::system_clock::time_point instead
+ 2. Specialize the TimePoint class with whichever time class that you
+ want to use here. See below for two examples of how to do this.
*/
-
template <typename T>
class TimePoint {
public:
diff --git a/include/grpc++/impl/server_builder_plugin.h b/include/grpc++/impl/server_builder_plugin.h
index 61632e32fa..8f2bce54d7 100644
--- a/include/grpc++/impl/server_builder_plugin.h
+++ b/include/grpc++/impl/server_builder_plugin.h
@@ -43,24 +43,27 @@ namespace grpc {
class ServerInitializer;
class ChannelArguments;
+/// This interface is meant for internal usage only. Implementations of this
+/// interface should add themselves to a \a ServerBuilder instance through the
+/// \a InternalAddPluginFactory method.
class ServerBuilderPlugin {
public:
virtual ~ServerBuilderPlugin() {}
virtual grpc::string name() = 0;
- // InitServer will be called in ServerBuilder::BuildAndStart(), after the
- // Server instance is created.
+ /// InitServer will be called in ServerBuilder::BuildAndStart(), after the
+ /// Server instance is created.
virtual void InitServer(ServerInitializer* si) = 0;
- // Finish will be called at the end of ServerBuilder::BuildAndStart().
+ /// Finish will be called at the end of ServerBuilder::BuildAndStart().
virtual void Finish(ServerInitializer* si) = 0;
- // ChangeArguments is an interface that can be used in
- // ServerBuilderOption::UpdatePlugins
+ /// ChangeArguments is an interface that can be used in
+ /// ServerBuilderOption::UpdatePlugins
virtual void ChangeArguments(const grpc::string& name, void* value) = 0;
- // UpdateChannelArguments will be called in ServerBuilder::BuildAndStart(),
- // before the Server instance is created.
+ /// UpdateChannelArguments will be called in ServerBuilder::BuildAndStart(),
+ /// before the Server instance is created.
virtual void UpdateChannelArguments(ChannelArguments* args) {}
virtual bool has_sync_methods() const { return false; }
diff --git a/include/grpc++/resource_quota.h b/include/grpc++/resource_quota.h
index 68a514658d..1199ae9381 100644
--- a/include/grpc++/resource_quota.h
+++ b/include/grpc++/resource_quota.h
@@ -47,6 +47,7 @@ namespace grpc {
/// all attached entities below the ResourceQuota bound.
class ResourceQuota final : private GrpcLibraryCodegen {
public:
+ /// \param name - a unique name for this ResourceQuota.
explicit ResourceQuota(const grpc::string& name);
ResourceQuota();
~ResourceQuota();
diff --git a/include/grpc++/security/auth_metadata_processor.h b/include/grpc++/security/auth_metadata_processor.h
index 1ae32d0f6c..3536923146 100644
--- a/include/grpc++/security/auth_metadata_processor.h
+++ b/include/grpc++/security/auth_metadata_processor.h
@@ -49,19 +49,19 @@ class AuthMetadataProcessor {
virtual ~AuthMetadataProcessor() {}
- // If this method returns true, the Process function will be scheduled in
- // a different thread from the one processing the call.
+ /// If this method returns true, the Process function will be scheduled in
+ /// a different thread from the one processing the call.
virtual bool IsBlocking() const { return true; }
- // context is read/write: it contains the properties of the channel peer and
- // it is the job of the Process method to augment it with properties derived
- // from the passed-in auth_metadata.
- // consumed_auth_metadata needs to be filled with metadata that has been
- // consumed by the processor and will be removed from the call.
- // response_metadata is the metadata that will be sent as part of the
- // response.
- // If the return value is not Status::OK, the rpc call will be aborted with
- // the error code and error message sent back to the client.
+ /// context is read/write: it contains the properties of the channel peer and
+ /// it is the job of the Process method to augment it with properties derived
+ /// from the passed-in auth_metadata.
+ /// consumed_auth_metadata needs to be filled with metadata that has been
+ /// consumed by the processor and will be removed from the call.
+ /// response_metadata is the metadata that will be sent as part of the
+ /// response.
+ /// If the return value is not Status::OK, the rpc call will be aborted with
+ /// the error code and error message sent back to the client.
virtual Status Process(const InputMetadata& auth_metadata,
AuthContext* context,
OutputMetadata* consumed_auth_metadata,
diff --git a/include/grpc++/security/credentials.h b/include/grpc++/security/credentials.h
index 59861b78d8..8d9d181fde 100644
--- a/include/grpc++/security/credentials.h
+++ b/include/grpc++/security/credentials.h
@@ -204,23 +204,23 @@ std::shared_ptr<ChannelCredentials> InsecureChannelCredentials();
/// Credentials for a channel using Cronet.
std::shared_ptr<ChannelCredentials> CronetChannelCredentials(void* engine);
-// User defined metadata credentials.
+/// User defined metadata credentials.
class MetadataCredentialsPlugin {
public:
virtual ~MetadataCredentialsPlugin() {}
- // If this method returns true, the Process function will be scheduled in
- // a different thread from the one processing the call.
+ /// If this method returns true, the Process function will be scheduled in
+ /// a different thread from the one processing the call.
virtual bool IsBlocking() const { return true; }
- // Type of credentials this plugin is implementing.
+ /// Type of credentials this plugin is implementing.
virtual const char* GetType() const { return ""; }
- // Gets the auth metatada produced by this plugin.
- // The fully qualified method name is:
- // service_url + "/" + method_name.
- // The channel_auth_context contains (among other things), the identity of
- // the server.
+ /// Gets the auth metatada produced by this plugin.
+ /// The fully qualified method name is:
+ /// service_url + "/" + method_name.
+ /// The channel_auth_context contains (among other things), the identity of
+ /// the server.
virtual Status GetMetadata(
grpc::string_ref service_url, grpc::string_ref method_name,
const AuthContext& channel_auth_context,
diff --git a/include/grpc++/security/server_credentials.h b/include/grpc++/security/server_credentials.h
index 229bab8d84..4676b04c5d 100644
--- a/include/grpc++/security/server_credentials.h
+++ b/include/grpc++/security/server_credentials.h
@@ -46,13 +46,13 @@ struct grpc_server;
namespace grpc {
class Server;
-// Wrapper around \a grpc_server_credentials, a way to authenticate a server.
+/// Wrapper around \a grpc_server_credentials, a way to authenticate a server.
class ServerCredentials {
public:
virtual ~ServerCredentials();
- // This method is not thread-safe and has to be called before the server is
- // started. The last call to this function wins.
+ /// This method is not thread-safe and has to be called before the server is
+ /// started. The last call to this function wins.
virtual void SetAuthMetadataProcessor(
const std::shared_ptr<AuthMetadataProcessor>& processor) = 0;
@@ -70,7 +70,7 @@ class ServerCredentials {
/// Options to create ServerCredentials with SSL
struct SslServerCredentialsOptions {
- // Deprecated
+ /// Deprecated
SslServerCredentialsOptions()
: force_client_auth(false),
client_certificate_request(GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {}
@@ -84,12 +84,12 @@ struct SslServerCredentialsOptions {
};
grpc::string pem_root_certs;
std::vector<PemKeyCertPair> pem_key_cert_pairs;
- // Deprecated
+ /// Deprecated
bool force_client_auth;
- // If both force_client_auth and client_certificate_request fields are set,
- // force_client_auth takes effect i.e
- // REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY will be enforced.
+ /// If both force_client_auth and client_certificate_request fields are set,
+ /// force_client_auth takes effect i.e
+ /// REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY will be enforced.
grpc_ssl_client_certificate_request_type client_certificate_request;
};
diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h
index 5a8577659a..2185b283ac 100644
--- a/include/grpc++/server_builder.h
+++ b/include/grpc++/server_builder.h
@@ -46,6 +46,7 @@
#include <grpc/compression.h>
#include <grpc/support/cpu.h>
#include <grpc/support/useful.h>
+#include <grpc/support/workaround_list.h>
struct grpc_resource_quota;
@@ -184,6 +185,11 @@ class ServerBuilder {
static void InternalAddPluginFactory(
std::unique_ptr<ServerBuilderPlugin> (*CreatePlugin)());
+ /// Enable a server workaround. Do not use unless you know what the workaround
+ /// does. For explanation and detailed descriptions of workarounds, see
+ /// doc/workarounds.md.
+ ServerBuilder& EnableWorkaround(grpc_workaround_list id);
+
private:
friend class ::grpc::testing::ServerBuilderPluginTest;
diff --git a/include/grpc++/support/error_details.h b/include/grpc++/support/error_details.h
index 411175fb46..d4324d35cf 100644
--- a/include/grpc++/support/error_details.h
+++ b/include/grpc++/support/error_details.h
@@ -44,16 +44,16 @@ class Status;
namespace grpc {
-// Maps a grpc::Status to a google::rpc::Status.
-// The given \a to object will be cleared.
-// On success, returns status with OK.
-// Returns status with INVALID_ARGUMENT, if failed to deserialize.
-// Returns status with FAILED_PRECONDITION, if \a to is nullptr.
+/// Maps a grpc::Status to a google::rpc::Status.
+/// The given \a to object will be cleared.
+/// On success, returns status with OK.
+/// Returns status with INVALID_ARGUMENT, if failed to deserialize.
+/// Returns status with FAILED_PRECONDITION, if \a to is nullptr.
Status ExtractErrorDetails(const Status& from, ::google::rpc::Status* to);
-// Maps google::rpc::Status to a grpc::Status.
-// Returns OK on success.
-// Returns status with FAILED_PRECONDITION if \a to is nullptr.
+/// Maps google::rpc::Status to a grpc::Status.
+/// Returns OK on success.
+/// Returns status with FAILED_PRECONDITION if \a to is nullptr.
Status SetErrorDetails(const ::google::rpc::Status& from, Status* to);
} // namespace grpc
diff --git a/include/grpc++/test/mock_stream.h b/include/grpc++/test/mock_stream.h
index f2de9472d6..f6e94a48b3 100644
--- a/include/grpc++/test/mock_stream.h
+++ b/include/grpc++/test/mock_stream.h
@@ -50,14 +50,14 @@ class MockClientReader : public ClientReaderInterface<R> {
public:
MockClientReader() = default;
- // ClientStreamingInterface
+ /// ClientStreamingInterface
MOCK_METHOD0_T(Finish, Status());
- // ReaderInterface
+ /// ReaderInterface
MOCK_METHOD1_T(NextMessageSize, bool(uint32_t*));
MOCK_METHOD1_T(Read, bool(R*));
- // ClientReaderInterface
+ /// ClientReaderInterface
MOCK_METHOD0_T(WaitForInitialMetadata, void());
};
@@ -66,13 +66,13 @@ class MockClientWriter : public ClientWriterInterface<W> {
public:
MockClientWriter() = default;
- // ClientStreamingInterface
+ /// ClientStreamingInterface
MOCK_METHOD0_T(Finish, Status());
- // WriterInterface
+ /// WriterInterface
MOCK_METHOD2_T(Write, bool(const W&, const WriteOptions));
- // ClientWriterInterface
+ /// ClientWriterInterface
MOCK_METHOD0_T(WritesDone, bool());
};
@@ -81,22 +81,22 @@ class MockClientReaderWriter : public ClientReaderWriterInterface<W, R> {
public:
MockClientReaderWriter() = default;
- // ClientStreamingInterface
+ /// ClientStreamingInterface
MOCK_METHOD0_T(Finish, Status());
- // ReaderInterface
+ /// ReaderInterface
MOCK_METHOD1_T(NextMessageSize, bool(uint32_t*));
MOCK_METHOD1_T(Read, bool(R*));
- // WriterInterface
+ /// WriterInterface
MOCK_METHOD2_T(Write, bool(const W&, const WriteOptions));
- // ClientReaderWriterInterface
+ /// ClientReaderWriterInterface
MOCK_METHOD0_T(WaitForInitialMetadata, void());
MOCK_METHOD0_T(WritesDone, bool());
};
-// TODO: We do not support mocking an async RPC for now.
+/// TODO: We do not support mocking an async RPC for now.
template <class R>
class MockClientAsyncResponseReader
@@ -113,11 +113,11 @@ class MockClientAsyncReader : public ClientAsyncReaderInterface<R> {
public:
MockClientAsyncReader() = default;
- // ClientAsyncStreamingInterface
+ /// ClientAsyncStreamingInterface
MOCK_METHOD1_T(ReadInitialMetadata, void(void*));
MOCK_METHOD2_T(Finish, void(Status*, void*));
- // AsyncReaderInterface
+ /// AsyncReaderInterface
MOCK_METHOD2_T(Read, void(R*, void*));
};
@@ -126,14 +126,14 @@ class MockClientAsyncWriter : public ClientAsyncWriterInterface<W> {
public:
MockClientAsyncWriter() = default;
- // ClientAsyncStreamingInterface
+ /// ClientAsyncStreamingInterface
MOCK_METHOD1_T(ReadInitialMetadata, void(void*));
MOCK_METHOD2_T(Finish, void(Status*, void*));
- // AsyncWriterInterface
+ /// AsyncWriterInterface
MOCK_METHOD2_T(Write, void(const W&, void*));
- // ClientAsyncWriterInterface
+ /// ClientAsyncWriterInterface
MOCK_METHOD1_T(WritesDone, void(void*));
};
@@ -143,17 +143,17 @@ class MockClientAsyncReaderWriter
public:
MockClientAsyncReaderWriter() = default;
- // ClientAsyncStreamingInterface
+ /// ClientAsyncStreamingInterface
MOCK_METHOD1_T(ReadInitialMetadata, void(void*));
MOCK_METHOD2_T(Finish, void(Status*, void*));
- // AsyncWriterInterface
+ /// AsyncWriterInterface
MOCK_METHOD2_T(Write, void(const W&, void*));
- // AsyncReaderInterface
+ /// AsyncReaderInterface
MOCK_METHOD2_T(Read, void(R*, void*));
- // ClientAsyncReaderWriterInterface
+ /// ClientAsyncReaderWriterInterface
MOCK_METHOD1_T(WritesDone, void(void*));
};
diff --git a/include/grpc++/test/server_context_test_spouse.h b/include/grpc++/test/server_context_test_spouse.h
index bac0db7bdc..5bd07e7aec 100644
--- a/include/grpc++/test/server_context_test_spouse.h
+++ b/include/grpc++/test/server_context_test_spouse.h
@@ -41,13 +41,13 @@
namespace grpc {
namespace testing {
-// A test-only class to access private members and methods of ServerContext.
+/// A test-only class to access private members and methods of ServerContext.
class ServerContextTestSpouse {
public:
explicit ServerContextTestSpouse(ServerContext* ctx) : ctx_(ctx) {}
- // Inject client metadata to the ServerContext for the test. The test spouse
- // must be alive when ServerContext::client_metadata is called.
+ /// Inject client metadata to the ServerContext for the test. The test spouse
+ /// must be alive when ServerContext::client_metadata is called.
void AddClientMetadata(const grpc::string& key, const grpc::string& value) {
client_metadata_storage_.insert(
std::pair<grpc::string, grpc::string>(key, value));
@@ -70,7 +70,7 @@ class ServerContextTestSpouse {
}
private:
- ServerContext* ctx_; // not owned
+ ServerContext* ctx_; /// not owned
std::multimap<grpc::string, grpc::string> client_metadata_storage_;
};
diff --git a/include/grpc/census.h b/include/grpc/census.h
index 822c42c0a4..68cefd86a1 100644
--- a/include/grpc/census.h
+++ b/include/grpc/census.h
@@ -31,7 +31,7 @@
*
*/
-/* RPC-internal Census API's. These are designed to be generic enough that
+/** RPC-internal Census API's. These are designed to be generic enough that
* they can (ultimately) be used in many different RPC systems (with differing
* implementations). */
@@ -44,12 +44,12 @@
extern "C" {
#endif
-/* Identify census features that can be enabled via census_initialize(). */
+/** Identify census features that can be enabled via census_initialize(). */
enum census_features {
- CENSUS_FEATURE_NONE = 0, /* Do not enable census. */
- CENSUS_FEATURE_TRACING = 1, /* Enable census tracing. */
- CENSUS_FEATURE_STATS = 2, /* Enable Census stats collection. */
- CENSUS_FEATURE_CPU = 4, /* Enable Census CPU usage collection. */
+ CENSUS_FEATURE_NONE = 0, /** Do not enable census. */
+ CENSUS_FEATURE_TRACING = 1, /** Enable census tracing. */
+ CENSUS_FEATURE_STATS = 2, /** Enable Census stats collection. */
+ CENSUS_FEATURE_CPU = 4, /** Enable Census CPU usage collection. */
CENSUS_FEATURE_ALL =
CENSUS_FEATURE_TRACING | CENSUS_FEATURE_STATS | CENSUS_FEATURE_CPU
};
@@ -82,7 +82,7 @@ CENSUSAPI int census_enabled(void);
metrics will be recorded. Keys are unique within a context. */
typedef struct census_context census_context;
-/* A tag is a key:value pair. Both keys and values are nil-terminated strings,
+/** A tag is a key:value pair. Both keys and values are nil-terminated strings,
containing printable ASCII characters (decimal 32-126). Keys must be at
least one character in length. Both keys and values can have at most
CENSUS_MAX_TAG_KB_LEN characters (including the terminating nil). The
@@ -97,36 +97,36 @@ typedef struct {
uint8_t flags;
} census_tag;
-/* Maximum length of a tag's key or value. */
+/** Maximum length of a tag's key or value. */
#define CENSUS_MAX_TAG_KV_LEN 255
-/* Maximum number of propagatable tags. */
+/** Maximum number of propagatable tags. */
#define CENSUS_MAX_PROPAGATED_TAGS 255
-/* Tag flags. */
-#define CENSUS_TAG_PROPAGATE 1 /* Tag should be propagated over RPC */
-#define CENSUS_TAG_STATS 2 /* Tag will be used for statistics aggregation */
-#define CENSUS_TAG_RESERVED 4 /* Reserved for internal use. */
-/* Flag values 4,8,16,32,64,128 are reserved for future/internal use. Clients
+/** Tag flags. */
+#define CENSUS_TAG_PROPAGATE 1 /** Tag should be propagated over RPC */
+#define CENSUS_TAG_STATS 2 /** Tag will be used for statistics aggregation */
+#define CENSUS_TAG_RESERVED 4 /** Reserved for internal use. */
+/** Flag values 4,8,16,32,64,128 are reserved for future/internal use. Clients
should not use or rely on their values. */
#define CENSUS_TAG_IS_PROPAGATED(flags) (flags & CENSUS_TAG_PROPAGATE)
#define CENSUS_TAG_IS_STATS(flags) (flags & CENSUS_TAG_STATS)
-/* An instance of this structure is kept by every context, and records the
+/** An instance of this structure is kept by every context, and records the
basic information associated with the creation of that context. */
typedef struct {
- int n_propagated_tags; /* number of propagated tags */
- int n_local_tags; /* number of non-propagated (local) tags */
- int n_deleted_tags; /* number of tags that were deleted */
- int n_added_tags; /* number of tags that were added */
- int n_modified_tags; /* number of tags that were modified */
- int n_invalid_tags; /* number of tags with bad keys or values (e.g.
+ int n_propagated_tags; /** number of propagated tags */
+ int n_local_tags; /** number of non-propagated (local) tags */
+ int n_deleted_tags; /** number of tags that were deleted */
+ int n_added_tags; /** number of tags that were added */
+ int n_modified_tags; /** number of tags that were modified */
+ int n_invalid_tags; /** number of tags with bad keys or values (e.g.
longer than CENSUS_MAX_TAG_KV_LEN) */
- int n_ignored_tags; /* number of tags ignored because of
+ int n_ignored_tags; /** number of tags ignored because of
CENSUS_MAX_PROPAGATED_TAGS limit. */
} census_context_status;
-/* Create a new context, adding and removing tags from an existing context.
+/** Create a new context, adding and removing tags from an existing context.
This will copy all tags from the 'tags' input, so it is recommended
to add as many tags in a single operation as is practical for the client.
@param base Base context to build upon. Can be NULL.
@@ -148,15 +148,15 @@ CENSUSAPI census_context *census_context_create(
const census_context *base, const census_tag *tags, int ntags,
census_context_status const **status);
-/* Destroy a context. Once this function has been called, the context cannot
+/** Destroy a context. Once this function has been called, the context cannot
be reused. */
CENSUSAPI void census_context_destroy(census_context *context);
-/* Get a pointer to the original status from the context creation. */
+/** Get a pointer to the original status from the context creation. */
CENSUSAPI const census_context_status *census_context_get_status(
const census_context *context);
-/* Structure used for iterating over the tags in a context. API clients should
+/** Structure used for iterating over the tags in a context. API clients should
not use or reference internal fields - neither their contents or
presence/absence are guaranteed. */
typedef struct {
@@ -166,25 +166,25 @@ typedef struct {
char *kvm;
} census_context_iterator;
-/* Initialize a census_tag_iterator. Must be called before first use. */
+/** Initialize a census_tag_iterator. Must be called before first use. */
CENSUSAPI void census_context_initialize_iterator(
const census_context *context, census_context_iterator *iterator);
-/* Get the contents of the "next" tag in the context. If there are no more
+/** Get the contents of the "next" tag in the context. If there are no more
tags, returns 0 (and 'tag' contents will be unchanged), otherwise returns 1.
*/
CENSUSAPI int census_context_next_tag(census_context_iterator *iterator,
census_tag *tag);
-/* Get a context tag by key. Returns 0 if the key is not present. */
+/** Get a context tag by key. Returns 0 if the key is not present. */
CENSUSAPI int census_context_get_tag(const census_context *context,
const char *key, census_tag *tag);
-/* Tag set encode/decode functionality. These functions are intended
+/** Tag set encode/decode functionality. These functions are intended
for use by RPC systems only, for purposes of transmitting/receiving contexts.
*/
-/* Encode a context into a buffer.
+/** Encode a context into a buffer.
@param context context to be encoded
@param buffer buffer into which the context will be encoded.
@param buf_size number of available bytes in buffer.
@@ -193,15 +193,15 @@ CENSUSAPI int census_context_get_tag(const census_context *context,
CENSUSAPI size_t census_context_encode(const census_context *context,
char *buffer, size_t buf_size);
-/* Decode context buffer encoded with census_context_encode(). Returns NULL
+/** Decode context buffer encoded with census_context_encode(). Returns NULL
if there is an error in parsing either buffer. */
CENSUSAPI census_context *census_context_decode(const char *buffer,
size_t size);
-/* Distributed traces can have a number of options. */
+/** Distributed traces can have a number of options. */
enum census_trace_mask_values {
- CENSUS_TRACE_MASK_NONE = 0, /* Default, empty flags */
- CENSUS_TRACE_MASK_IS_SAMPLED = 1 /* RPC tracing enabled for this context. */
+ CENSUS_TRACE_MASK_NONE = 0, /** Default, empty flags */
+ CENSUS_TRACE_MASK_IS_SAMPLED = 1 /** RPC tracing enabled for this context. */
};
/** Get the current trace mask associated with this context. The value returned
@@ -211,7 +211,7 @@ CENSUSAPI int census_trace_mask(const census_context *context);
/** Set the trace mask associated with a context. */
CENSUSAPI void census_set_trace_mask(int trace_mask);
-/* The concept of "operation" is a fundamental concept for Census. In an RPC
+/** The concept of "operation" is a fundamental concept for Census. In an RPC
system, an operation typically represents a single RPC, or a significant
sub-part thereof (e.g. a single logical "read" RPC to a distributed storage
system might do several other actions in parallel, from looking up metadata
@@ -238,7 +238,7 @@ CENSUSAPI void census_set_trace_mask(int trace_mask);
at which an operation begins.
*/
typedef struct {
- /* Use gpr_timespec for default implementation. High performance
+ /** Use gpr_timespec for default implementation. High performance
* implementations should use a cycle-counter based timestamp. */
gpr_timespec ts;
} census_timestamp;
@@ -398,12 +398,12 @@ CENSUSAPI void census_trace_print(census_context *context, uint32_t type,
/** Trace record. */
typedef struct {
- census_timestamp timestamp; /* Time of record creation */
- uint64_t trace_id; /* Trace ID associated with record */
- uint64_t op_id; /* Operation ID associated with record */
- uint32_t type; /* Type (as used in census_trace_print() */
- const char *buffer; /* Buffer (from census_trace_print() */
- size_t buf_size; /* Number of bytes inside buffer */
+ census_timestamp timestamp; /** Time of record creation */
+ uint64_t trace_id; /** Trace ID associated with record */
+ uint64_t op_id; /** Operation ID associated with record */
+ uint32_t type; /** Type (as used in census_trace_print() */
+ const char *buffer; /** Buffer (from census_trace_print() */
+ size_t buf_size; /** Number of bytes inside buffer */
} census_trace_record;
/** Start a scan of existing trace records. While a scan is ongoing, addition
@@ -431,7 +431,7 @@ CENSUSAPI int census_get_trace_record(census_trace_record *trace_record);
/** End a scan previously started by census_trace_scan_start() */
CENSUSAPI void census_trace_scan_end();
-/* Core stats collection API's. The following concepts are used:
+/** Core stats collection API's. The following concepts are used:
* Resource: Users record measurements for a single resource. Examples
include RPC latency, CPU seconds consumed, and bytes transmitted.
* Aggregation: An aggregation of a set of measurements. Census supports the
@@ -450,7 +450,7 @@ CENSUSAPI void census_trace_scan_end();
implementations. The proto definitions can be found in src/proto/census.
*/
-/* Define a new resource. `resource_pb` should contain an encoded Resource
+/** Define a new resource. `resource_pb` should contain an encoded Resource
protobuf, `resource_pb_size` being the size of the buffer. Returns a -ve
value on error, or a positive (>= 0) resource id (for use in
census_delete_resource() and census_record_values()). In order to be valid, a
@@ -459,21 +459,21 @@ CENSUSAPI void census_trace_scan_end();
CENSUSAPI int32_t census_define_resource(const uint8_t *resource_pb,
size_t resource_pb_size);
-/* Delete a resource created by census_define_resource(). */
+/** Delete a resource created by census_define_resource(). */
CENSUSAPI void census_delete_resource(int32_t resource_id);
-/* Determine the id of a resource, given its name. returns -1 if the resource
+/** Determine the id of a resource, given its name. returns -1 if the resource
does not exist. */
CENSUSAPI int32_t census_resource_id(const char *name);
-/* A single value to be recorded comprises two parts: an ID for the particular
+/** A single value to be recorded comprises two parts: an ID for the particular
* resource and the value to be recorded against it. */
typedef struct {
int32_t resource_id;
double value;
} census_value;
-/* Record new usage values against the given context. */
+/** Record new usage values against the given context. */
CENSUSAPI void census_record_values(census_context *context,
census_value *values, size_t nvalues);
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 1eeb075927..a36367fa8f 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -287,7 +287,7 @@ GRPCAPI grpc_channel *grpc_lame_client_channel_create(
/** Close and destroy a grpc channel */
GRPCAPI void grpc_channel_destroy(grpc_channel *channel);
-/* Error handling for grpc_call
+/** 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.
If a grpc_call fails, it's guaranteed that no change to the call state
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 5d3cc4fd67..4f35506882 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -42,7 +42,7 @@
extern "C" {
#endif
-/* --- Authentication Context. --- */
+/** --- Authentication Context. --- */
typedef struct grpc_auth_context grpc_auth_context;
@@ -52,84 +52,84 @@ typedef struct grpc_auth_property_iterator {
const char *name;
} grpc_auth_property_iterator;
-/* value, if not NULL, is guaranteed to be NULL terminated. */
+/** value, if not NULL, is guaranteed to be NULL terminated. */
typedef struct grpc_auth_property {
char *name;
char *value;
size_t value_length;
} grpc_auth_property;
-/* Returns NULL when the iterator is at the end. */
+/** Returns NULL when the iterator is at the end. */
GRPCAPI const grpc_auth_property *grpc_auth_property_iterator_next(
grpc_auth_property_iterator *it);
-/* Iterates over the auth context. */
+/** Iterates over the auth context. */
GRPCAPI grpc_auth_property_iterator
grpc_auth_context_property_iterator(const grpc_auth_context *ctx);
-/* Gets the peer identity. Returns an empty iterator (first _next will return
+/** Gets the peer identity. Returns an empty iterator (first _next will return
NULL) if the peer is not authenticated. */
GRPCAPI grpc_auth_property_iterator
grpc_auth_context_peer_identity(const grpc_auth_context *ctx);
-/* Finds a property in the context. May return an empty iterator (first _next
+/** Finds a property in the context. May return an empty iterator (first _next
will return NULL) if no property with this name was found in the context. */
GRPCAPI grpc_auth_property_iterator grpc_auth_context_find_properties_by_name(
const grpc_auth_context *ctx, const char *name);
-/* Gets the name of the property that indicates the peer identity. Will return
+/** Gets the name of the property that indicates the peer identity. Will return
NULL if the peer is not authenticated. */
GRPCAPI const char *grpc_auth_context_peer_identity_property_name(
const grpc_auth_context *ctx);
-/* Returns 1 if the peer is authenticated, 0 otherwise. */
+/** Returns 1 if the peer is authenticated, 0 otherwise. */
GRPCAPI int grpc_auth_context_peer_is_authenticated(
const grpc_auth_context *ctx);
-/* Gets the auth context from the call. Caller needs to call
+/** Gets the auth context from the call. Caller needs to call
grpc_auth_context_release on the returned context. */
GRPCAPI grpc_auth_context *grpc_call_auth_context(grpc_call *call);
-/* Releases the auth context returned from grpc_call_auth_context. */
+/** Releases the auth context returned from grpc_call_auth_context. */
GRPCAPI void grpc_auth_context_release(grpc_auth_context *context);
-/* --
+/** --
The following auth context methods should only be called by a server metadata
processor to set properties extracted from auth metadata.
-- */
-/* Add a property. */
+/** Add a property. */
GRPCAPI void grpc_auth_context_add_property(grpc_auth_context *ctx,
const char *name, const char *value,
size_t value_length);
-/* Add a C string property. */
+/** Add a C string property. */
GRPCAPI void grpc_auth_context_add_cstring_property(grpc_auth_context *ctx,
const char *name,
const char *value);
-/* Sets the property name. Returns 1 if successful or 0 in case of failure
+/** Sets the property name. Returns 1 if successful or 0 in case of failure
(which means that no property with this name exists). */
GRPCAPI int grpc_auth_context_set_peer_identity_property_name(
grpc_auth_context *ctx, const char *name);
-/* --- grpc_channel_credentials object. ---
+/** --- grpc_channel_credentials object. ---
A channel credentials object represents a way to authenticate a client on a
channel. */
typedef struct grpc_channel_credentials grpc_channel_credentials;
-/* Releases a channel credentials object.
+/** Releases a channel credentials object.
The creator of the credentials object is responsible for its release. */
GRPCAPI void grpc_channel_credentials_release(grpc_channel_credentials *creds);
-/* Creates default credentials to connect to a google gRPC service.
+/** Creates default credentials to connect to a google gRPC service.
WARNING: Do NOT use this credentials to connect to a non-google service as
this could result in an oauth2 token leak. */
GRPCAPI grpc_channel_credentials *grpc_google_default_credentials_create(void);
-/* Callback for getting the SSL roots override from the application.
+/** Callback for getting the SSL roots override from the application.
In case of success, *pem_roots_certs must be set to a NULL terminated string
containing the list of PEM encoded root certificates. The ownership is passed
to the core and freed (laster by the core) with gpr_free.
@@ -138,7 +138,7 @@ GRPCAPI grpc_channel_credentials *grpc_google_default_credentials_create(void);
typedef grpc_ssl_roots_override_result (*grpc_ssl_roots_override_callback)(
char **pem_root_certs);
-/* Setup a callback to override the default TLS/SSL roots.
+/** Setup a callback to override the default TLS/SSL roots.
This function is not thread-safe and must be called at initialization time
before any ssl credentials are created to have the desired side effect.
If GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment is set to a valid path, the
@@ -146,18 +146,18 @@ typedef grpc_ssl_roots_override_result (*grpc_ssl_roots_override_callback)(
GRPCAPI void grpc_set_ssl_roots_override_callback(
grpc_ssl_roots_override_callback cb);
-/* Object that holds a private key / certificate chain pair in PEM format. */
+/** Object that holds a private key / certificate chain pair in PEM format. */
typedef struct {
- /* private_key is the NULL-terminated string containing the PEM encoding of
+ /** private_key is the NULL-terminated string containing the PEM encoding of
the client's private key. */
const char *private_key;
- /* cert_chain is the NULL-terminated string containing the PEM encoding of
+ /** cert_chain is the NULL-terminated string containing the PEM encoding of
the client's certificate chain. */
const char *cert_chain;
} grpc_ssl_pem_key_cert_pair;
-/* Creates an SSL credentials object.
+/** 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
implementation will first try to dereference the file pointed by the
@@ -172,7 +172,7 @@ 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);
-/* --- grpc_call_credentials object.
+/** --- grpc_call_credentials object.
A call credentials object represents a way to authenticate on a particular
call. These credentials can be composed with a channel credentials object
@@ -180,21 +180,21 @@ GRPCAPI grpc_channel_credentials *grpc_ssl_credentials_create(
typedef struct grpc_call_credentials grpc_call_credentials;
-/* Releases a call credentials object.
+/** Releases a call credentials object.
The creator of the credentials object is responsible for its release. */
GRPCAPI void grpc_call_credentials_release(grpc_call_credentials *creds);
-/* Creates a composite channel credentials object. */
+/** Creates a composite channel credentials object. */
GRPCAPI grpc_channel_credentials *grpc_composite_channel_credentials_create(
grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds,
void *reserved);
-/* Creates a composite call credentials object. */
+/** Creates a composite call credentials object. */
GRPCAPI grpc_call_credentials *grpc_composite_call_credentials_create(
grpc_call_credentials *creds1, grpc_call_credentials *creds2,
void *reserved);
-/* Creates a compute engine credentials object for connecting to Google.
+/** Creates a compute engine credentials object for connecting to Google.
WARNING: Do NOT use this credentials to connect to a non-google service as
this could result in an oauth2 token leak. */
GRPCAPI grpc_call_credentials *grpc_google_compute_engine_credentials_create(
@@ -202,7 +202,7 @@ GRPCAPI grpc_call_credentials *grpc_google_compute_engine_credentials_create(
GRPCAPI gpr_timespec grpc_max_auth_token_lifetime();
-/* Creates a JWT credentials object. May return NULL if the input is invalid.
+/** Creates a JWT credentials object. May return NULL if the input is invalid.
- json_key is the JSON key string containing the client's private key.
- token_lifetime is the lifetime of each Json Web Token (JWT) created with
this credentials. It should not exceed grpc_max_auth_token_lifetime or
@@ -212,7 +212,7 @@ grpc_service_account_jwt_access_credentials_create(const char *json_key,
gpr_timespec token_lifetime,
void *reserved);
-/* Creates an Oauth2 Refresh Token credentials object for connecting to Google.
+/** Creates an Oauth2 Refresh Token credentials object for connecting to Google.
May return NULL if the input is invalid.
WARNING: Do NOT use this credentials to connect to a non-google service as
this could result in an oauth2 token leak.
@@ -221,17 +221,17 @@ grpc_service_account_jwt_access_credentials_create(const char *json_key,
GRPCAPI grpc_call_credentials *grpc_google_refresh_token_credentials_create(
const char *json_refresh_token, void *reserved);
-/* Creates an Oauth2 Access Token credentials with an access token that was
+/** Creates an Oauth2 Access Token credentials with an access token that was
aquired by an out of band mechanism. */
GRPCAPI grpc_call_credentials *grpc_access_token_credentials_create(
const char *access_token, void *reserved);
-/* Creates an IAM credentials object for connecting to Google. */
+/** Creates an IAM credentials object for connecting to Google. */
GRPCAPI grpc_call_credentials *grpc_google_iam_credentials_create(
const char *authorization_token, const char *authority_selector,
void *reserved);
-/* Callback function to be called by the metadata credentials plugin
+/** Callback function to be called by the metadata credentials plugin
implementation when the metadata is ready.
- user_data is the opaque pointer that was passed in the get_metadata method
of the grpc_metadata_credentials_plugin (see below).
@@ -246,31 +246,31 @@ typedef void (*grpc_credentials_plugin_metadata_cb)(
void *user_data, const grpc_metadata *creds_md, size_t num_creds_md,
grpc_status_code status, const char *error_details);
-/* Context that can be used by metadata credentials plugin in order to create
+/** Context that can be used by metadata credentials plugin in order to create
auth related metadata. */
typedef struct {
- /* The fully qualifed service url. */
+ /** The fully qualifed service url. */
const char *service_url;
- /* The method name of the RPC being called (not fully qualified).
+ /** The method name of the RPC being called (not fully qualified).
The fully qualified method name can be built from the service_url:
full_qualified_method_name = ctx->service_url + '/' + ctx->method_name. */
const char *method_name;
- /* The auth_context of the channel which gives the server's identity. */
+ /** The auth_context of the channel which gives the server's identity. */
const grpc_auth_context *channel_auth_context;
- /* Reserved for future use. */
+ /** Reserved for future use. */
void *reserved;
} grpc_auth_metadata_context;
-/* grpc_metadata_credentials plugin is an API user provided structure used to
+/** grpc_metadata_credentials plugin is an API user provided structure used to
create grpc_credentials objects that can be set on a channel (composed) or
a call. See grpc_credentials_metadata_create_from_plugin below.
The grpc client stack will call the get_metadata method of the plugin for
every call in scope for the credentials created from it. */
typedef struct {
- /* The implementation of this method has to be non-blocking.
+ /** The implementation of this method has to be non-blocking.
- context is the information that can be used by the plugin to create auth
metadata.
- cb is the callback that needs to be called when the metadata is ready.
@@ -278,39 +278,39 @@ typedef struct {
void (*get_metadata)(void *state, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb, void *user_data);
- /* Destroys the plugin state. */
+ /** Destroys the plugin state. */
void (*destroy)(void *state);
- /* State that will be set as the first parameter of the methods above. */
+ /** State that will be set as the first parameter of the methods above. */
void *state;
- /* Type of credentials that this plugin is implementing. */
+ /** Type of credentials that this plugin is implementing. */
const char *type;
} grpc_metadata_credentials_plugin;
-/* Creates a credentials object from a plugin. */
+/** Creates a credentials object from a plugin. */
GRPCAPI grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
grpc_metadata_credentials_plugin plugin, void *reserved);
-/* --- Secure channel creation. --- */
+/** --- Secure channel creation. --- */
-/* Creates a secure channel using the passed-in credentials. */
+/** Creates a secure channel using the passed-in credentials. */
GRPCAPI grpc_channel *grpc_secure_channel_create(
grpc_channel_credentials *creds, const char *target,
const grpc_channel_args *args, void *reserved);
-/* --- grpc_server_credentials object. ---
+/** --- grpc_server_credentials object. ---
A server credentials object represents a way to authenticate a server. */
typedef struct grpc_server_credentials grpc_server_credentials;
-/* Releases a server_credentials object.
+/** Releases a server_credentials object.
The creator of the server_credentials object is responsible for its release.
*/
GRPCAPI void grpc_server_credentials_release(grpc_server_credentials *creds);
-/* Deprecated in favor of grpc_ssl_server_credentials_create_ex.
+/** Deprecated in favor of grpc_ssl_server_credentials_create_ex.
Creates an SSL server_credentials object.
- pem_roots_cert is the NULL-terminated string containing the PEM encoding of
the client root certificates. This parameter may be NULL if the server does
@@ -326,7 +326,7 @@ GRPCAPI grpc_server_credentials *grpc_ssl_server_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
size_t num_key_cert_pairs, int force_client_auth, void *reserved);
-/* Same as grpc_ssl_server_credentials_create method except uses
+/** Same as grpc_ssl_server_credentials_create method except uses
grpc_ssl_client_certificate_request_type enum to support more ways to
authenticate client cerificates.*/
GRPCAPI grpc_server_credentials *grpc_ssl_server_credentials_create_ex(
@@ -335,25 +335,25 @@ GRPCAPI grpc_server_credentials *grpc_ssl_server_credentials_create_ex(
grpc_ssl_client_certificate_request_type client_certificate_request,
void *reserved);
-/* --- Server-side secure ports. --- */
+/** --- Server-side secure ports. --- */
-/* Add a HTTP2 over an encrypted link over tcp listener.
+/** Add a HTTP2 over an encrypted link over tcp listener.
Returns bound port number on success, 0 on failure.
REQUIRES: server not started */
GRPCAPI int grpc_server_add_secure_http2_port(grpc_server *server,
const char *addr,
grpc_server_credentials *creds);
-/* --- Call specific credentials. --- */
+/** --- Call specific credentials. --- */
-/* Sets a credentials to a call. Can only be called on the client side before
+/** Sets a credentials to a call. Can only be called on the client side before
grpc_call_start_batch. */
GRPCAPI grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_call_credentials *creds);
-/* --- Auth Metadata Processing --- */
+/** --- Auth Metadata Processing --- */
-/* Callback function that is called when the metadata processing is done.
+/** Callback function that is called when the metadata processing is done.
- Consumed metadata will be removed from the set of metadata available on the
call. consumed_md may be NULL if no metadata has been consumed.
- Response metadata will be set on the response. response_md may be NULL.
@@ -367,9 +367,9 @@ typedef void (*grpc_process_auth_metadata_done_cb)(
const grpc_metadata *response_md, size_t num_response_md,
grpc_status_code status, const char *error_details);
-/* Pluggable server-side metadata processor object. */
+/** Pluggable server-side metadata processor object. */
typedef struct {
- /* The context object is read/write: it contains the properties of the
+ /** The context object is read/write: it contains the properties of the
channel peer and it is the job of the process function to augment it with
properties derived from the passed-in metadata.
The lifetime of these objects is guaranteed until cb is invoked. */
diff --git a/include/grpc/grpc_security_constants.h b/include/grpc/grpc_security_constants.h
index da05c5a97b..d7ac0b2745 100644
--- a/include/grpc/grpc_security_constants.h
+++ b/include/grpc/grpc_security_constants.h
@@ -45,30 +45,30 @@ extern "C" {
#define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name"
#define GRPC_X509_PEM_CERT_PROPERTY_NAME "x509_pem_cert"
-/* Environment variable that points to the default SSL roots file. This file
+/** Environment variable that points to the default SSL roots file. This file
must be a PEM encoded file with all the roots such as the one that can be
downloaded from https://pki.google.com/roots.pem. */
#define GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR \
"GRPC_DEFAULT_SSL_ROOTS_FILE_PATH"
-/* Environment variable that points to the google default application
+/** Environment variable that points to the google default application
credentials json key or refresh token. Used in the
grpc_google_default_credentials_create function. */
#define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS"
-/* Results for the SSL roots override callback. */
+/** Results for the SSL roots override callback. */
typedef enum {
GRPC_SSL_ROOTS_OVERRIDE_OK,
- GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY, /* Do not try fallback options. */
+ GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY, /** Do not try fallback options. */
GRPC_SSL_ROOTS_OVERRIDE_FAIL
} grpc_ssl_roots_override_result;
typedef enum {
- /* Server does not request client certificate. A client can present a self
+ /** Server does not request client certificate. A client can present a self
signed or signed certificates if it wishes to do so and they would be
accepted. */
GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
- /* Server requests client certificate but does not enforce that the client
+ /** Server requests client certificate but does not enforce that the client
presents a certificate.
If the client presents a certificate, the client authentication is left to
@@ -77,7 +77,7 @@ typedef enum {
The key cert pair should still be valid for the SSL connection to be
established. */
GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY,
- /* Server requests client certificate but does not enforce that the client
+ /** Server requests client certificate but does not enforce that the client
presents a certificate.
If the client presents a certificate, the client authentication is done by
@@ -87,7 +87,7 @@ typedef enum {
The key cert pair should still be valid for the SSL connection to be
established. */
GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY,
- /* Server requests client certificate but enforces that the client presents a
+ /** Server requests client certificate but enforces that the client presents a
certificate.
If the client presents a certificate, the client authentication is left to
@@ -96,7 +96,7 @@ typedef enum {
The key cert pair should still be valid for the SSL connection to be
established. */
GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY,
- /* Server requests client certificate but enforces that the client presents a
+ /** Server requests client certificate but enforces that the client presents a
certificate.
The cerificate presented by the client is verified by grpc framework (The
diff --git a/include/grpc/impl/codegen/atm.h b/include/grpc/impl/codegen/atm.h
index 4bd572d6d1..d348f32f67 100644
--- a/include/grpc/impl/codegen/atm.h
+++ b/include/grpc/impl/codegen/atm.h
@@ -34,7 +34,7 @@
#ifndef GRPC_IMPL_CODEGEN_ATM_H
#define GRPC_IMPL_CODEGEN_ATM_H
-/* This interface provides atomic operations and barriers.
+/** This interface provides atomic operations and barriers.
It is internal to gpr support code and should not be used outside it.
If an operation with acquire semantics precedes another memory access by the
diff --git a/include/grpc/impl/codegen/atm_windows.h b/include/grpc/impl/codegen/atm_windows.h
index a533651f6f..fa842a3048 100644
--- a/include/grpc/impl/codegen/atm_windows.h
+++ b/include/grpc/impl/codegen/atm_windows.h
@@ -34,7 +34,7 @@
#ifndef GRPC_IMPL_CODEGEN_ATM_WINDOWS_H
#define GRPC_IMPL_CODEGEN_ATM_WINDOWS_H
-/* Win32 variant of atm_platform.h */
+/** Win32 variant of atm_platform.h */
#include <grpc/impl/codegen/port_platform.h>
typedef intptr_t gpr_atm;
@@ -64,7 +64,7 @@ static __inline void gpr_atm_no_barrier_store(gpr_atm *p, gpr_atm value) {
}
static __inline int gpr_atm_no_barrier_cas(gpr_atm *p, gpr_atm o, gpr_atm n) {
-/* InterlockedCompareExchangePointerNoFence() not available on vista or
+/** InterlockedCompareExchangePointerNoFence() not available on vista or
windows7 */
#ifdef GPR_ARCH_64
return o == (gpr_atm)InterlockedCompareExchangeAcquire64(
@@ -107,7 +107,7 @@ static __inline int gpr_atm_full_cas(gpr_atm *p, gpr_atm o, gpr_atm n) {
static __inline gpr_atm gpr_atm_no_barrier_fetch_add(gpr_atm *p,
gpr_atm delta) {
- /* Use the CAS operation to get pointer-sized fetch and add */
+ /** Use the CAS operation to get pointer-sized fetch and add */
gpr_atm old;
do {
old = *p;
@@ -116,7 +116,7 @@ static __inline gpr_atm gpr_atm_no_barrier_fetch_add(gpr_atm *p,
}
static __inline gpr_atm gpr_atm_full_fetch_add(gpr_atm *p, gpr_atm delta) {
- /* Use a CAS operation to get pointer-sized fetch and add */
+ /** Use a CAS operation to get pointer-sized fetch and add */
gpr_atm old;
#ifdef GPR_ARCH_64
do {
diff --git a/include/grpc/impl/codegen/byte_buffer_reader.h b/include/grpc/impl/codegen/byte_buffer_reader.h
index 85a4864140..354a28a14e 100644
--- a/include/grpc/impl/codegen/byte_buffer_reader.h
+++ b/include/grpc/impl/codegen/byte_buffer_reader.h
@@ -43,9 +43,9 @@ struct grpc_byte_buffer;
struct grpc_byte_buffer_reader {
struct grpc_byte_buffer *buffer_in;
struct grpc_byte_buffer *buffer_out;
- /* Different current objects correspond to different types of byte buffers */
+ /** Different current objects correspond to different types of byte buffers */
union {
- /* Index into a slice buffer's array of slices */
+ /** Index into a slice buffer's array of slices */
unsigned index;
} current;
};
diff --git a/include/grpc/impl/codegen/compression_types.h b/include/grpc/impl/codegen/compression_types.h
index a563711e32..953b51d9c4 100644
--- a/include/grpc/impl/codegen/compression_types.h
+++ b/include/grpc/impl/codegen/compression_types.h
@@ -67,7 +67,7 @@ extern "C" {
"grpc.compression_enabled_algorithms_bitset"
/** \} */
-/* The various compression algorithms supported by gRPC */
+/** The various compression algorithms supported by gRPC */
typedef enum {
GRPC_COMPRESS_NONE = 0,
GRPC_COMPRESS_DEFLATE,
diff --git a/include/grpc/impl/codegen/gpr_slice.h b/include/grpc/impl/codegen/gpr_slice.h
index c62e976b8f..ead0b7db95 100644
--- a/include/grpc/impl/codegen/gpr_slice.h
+++ b/include/grpc/impl/codegen/gpr_slice.h
@@ -33,11 +33,11 @@
#ifndef GRPC_IMPL_CODEGEN_GPR_SLICE_H
#define GRPC_IMPL_CODEGEN_GPR_SLICE_H
-/* WARNING: Please do not use this header. This was added as a temporary measure
- * to not break some of the external projects that depend on gpr_slice_*
- * functions. We are actively working on moving all the gpr_slice_* references
- * to grpc_slice_* and this file will be removed
- * */
+/** WARNING: Please do not use this header. This was added as a temporary
+ * measure to not break some of the external projects that depend on
+ * gpr_slice_* functions. We are actively working on moving all the
+ * gpr_slice_* references to grpc_slice_* and this file will be removed
+ */
/* TODO (sreek) - Allowed by default but will be very soon turned off */
#define GRPC_ALLOW_GPR_SLICE_FUNCTIONS 1
diff --git a/include/grpc/impl/codegen/gpr_types.h b/include/grpc/impl/codegen/gpr_types.h
index 34d8156b61..ee4425233d 100644
--- a/include/grpc/impl/codegen/gpr_types.h
+++ b/include/grpc/impl/codegen/gpr_types.h
@@ -42,22 +42,22 @@
extern "C" {
#endif
-/* The clocks we support. */
+/** The clocks we support. */
typedef enum {
- /* Monotonic clock. Epoch undefined. Always moves forwards. */
+ /** Monotonic clock. Epoch undefined. Always moves forwards. */
GPR_CLOCK_MONOTONIC = 0,
- /* Realtime clock. May jump forwards or backwards. Settable by
+ /** Realtime clock. May jump forwards or backwards. Settable by
the system administrator. Has its epoch at 0:00:00 UTC 1 Jan 1970. */
GPR_CLOCK_REALTIME,
- /* CPU cycle time obtained by rdtsc instruction on x86 platforms. Epoch
+ /** CPU cycle time obtained by rdtsc instruction on x86 platforms. Epoch
undefined. Degrades to GPR_CLOCK_REALTIME on other platforms. */
GPR_CLOCK_PRECISE,
- /* Unmeasurable clock type: no base, created by taking the difference
+ /** Unmeasurable clock type: no base, created by taking the difference
between two times */
GPR_TIMESPAN
} gpr_clock_type;
-/* Analogous to struct timespec. On some machines, absolute times may be in
+/** Analogous to struct timespec. On some machines, absolute times may be in
* local time. */
typedef struct gpr_timespec {
int64_t tv_sec;
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index ffb5a77d79..072452cec3 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -50,7 +50,7 @@ extern "C" {
typedef enum {
GRPC_BB_RAW
- /* Future types may include GRPC_BB_PROTOBUF, etc. */
+ /** Future types may include GRPC_BB_PROTOBUF, etc. */
} grpc_byte_buffer_type;
typedef struct grpc_byte_buffer {
@@ -67,8 +67,8 @@ typedef struct grpc_byte_buffer {
} data;
} grpc_byte_buffer;
-/** Completion Queues enable notification of the completion of asynchronous
- actions. */
+/** Completion Queues enable notification of the completion of
+ * asynchronous actions. */
typedef struct grpc_completion_queue grpc_completion_queue;
/** An alarm associated with a completion queue. */
@@ -134,9 +134,9 @@ typedef struct {
Used to set optional channel-level configuration.
These configuration options are modelled as key-value pairs as defined
by grpc_arg; keys are strings to allow easy backwards-compatible extension
- by arbitrary parties.
- All evaluation is performed at channel creation time (i.e. the values in
- this structure need only live through the creation invocation).
+ by arbitrary parties. All evaluation is performed at channel creation
+ time (i.e. the values in this structure need only live through the
+ creation invocation).
See the description of the \ref grpc_arg_keys "available args" for more
details. */
@@ -162,7 +162,8 @@ typedef struct {
/** Maximum message length that the channel can receive. Int valued, bytes.
-1 means unlimited. */
#define GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH "grpc.max_receive_message_length"
-/** \deprecated For backward compatibility. */
+/** \deprecated For backward compatibility.
+ * Use GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH instead. */
#define GRPC_ARG_MAX_MESSAGE_LENGTH GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH
/** Maximum message length that the channel can send. Int valued, bytes.
-1 means unlimited. */
@@ -170,8 +171,8 @@ typedef struct {
/** Maximum time that a channel may have no outstanding rpcs. Int valued,
milliseconds. INT_MAX means unlimited. */
#define GRPC_ARG_MAX_CONNECTION_IDLE_MS "grpc.max_connection_idle_ms"
-/** Maximum time that a channel may exist. Int valued, milliseconds. INT_MAX
- means unlimited. */
+/** Maximum time that a channel may exist. Int valued, milliseconds.
+ * INT_MAX means unlimited. */
#define GRPC_ARG_MAX_CONNECTION_AGE_MS "grpc.max_connection_age_ms"
/** Grace period after the chennel reaches its max age. Int valued,
milliseconds. INT_MAX means unlimited. */
@@ -182,7 +183,7 @@ typedef struct {
/** Enable/disable support for deadline checking. Defaults to 1, unless
GRPC_ARG_MINIMAL_STACK is enabled, in which case it defaults to 0 */
#define GRPC_ARG_ENABLE_DEADLINE_CHECKS "grpc.enable_deadline_checking"
-/** Initial sequence number for http2 transports. Int valued. */
+/** Initial stream ID for http2 transports. Int valued. */
#define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \
"grpc.http2.initial_sequence_number"
/** Amount to read ahead on individual streams. Defaults to 64kb, larger
@@ -197,27 +198,24 @@ typedef struct {
#define GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER \
"grpc.http2.hpack_table_size.encoder"
/** How big a frame are we willing to receive via HTTP2.
- Min 16384, max 16777215.
- Larger values give lower CPU usage for large messages, but more head of line
- blocking for small messages. */
+ Min 16384, max 16777215. Larger values give lower CPU usage for large
+ messages, but more head of line blocking for small messages. */
#define GRPC_ARG_HTTP2_MAX_FRAME_SIZE "grpc.http2.max_frame_size"
/** Should BDP probing be performed? */
#define GRPC_ARG_HTTP2_BDP_PROBE "grpc.http2.bdp_probe"
/** Minimum time (in milliseconds) between successive ping frames being sent */
#define GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS \
"grpc.http2.min_time_between_pings_ms"
-/* Channel arg to override the http2 :scheme header */
+/** Channel arg to override the http2 :scheme header */
#define GRPC_ARG_HTTP2_SCHEME "grpc.http2_scheme"
/** How many pings can we send before needing to send a data frame or header
- frame?
- (0 indicates that an infinite number of pings can be sent without sending
- a data frame or header frame) */
+ frame? (0 indicates that an infinite number of pings can be sent without
+ sending a data frame or header frame) */
#define GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA \
"grpc.http2.max_pings_without_data"
/** How many misbehaving pings the server can bear before sending goaway and
- closing the transport?
- (0 indicates that the server can bear an infinite number of misbehaving
- pings) */
+ closing the transport? (0 indicates that the server can bear an infinite
+ number of misbehaving pings) */
#define GRPC_ARG_HTTP2_MAX_PING_STRIKES "grpc.http2.max_ping_strikes"
/** Minimum allowed time between two pings without sending any data frame. Int
valued, seconds */
@@ -256,20 +254,22 @@ typedef struct {
/** The time between the first and second connection attempts, in ms */
#define GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS \
"grpc.initial_reconnect_backoff_ms"
-/* The caller of the secure_channel_create functions may override the target
- name used for SSL host name checking using this channel argument which is of
- type \a GRPC_ARG_STRING. This *should* be used for testing only.
- If this argument is not specified, the name used for SSL host name checking
- will be the target parameter (assuming that the secure channel is an SSL
- channel). If this parameter is specified and the underlying is not an SSL
- channel, it will just be ignored. */
+/** This *should* be used for testing only.
+ The caller of the secure_channel_create functions may override the target
+ name used for SSL host name checking using this channel argument which is of
+ type \a GRPC_ARG_STRING. If this argument is not specified, the name used
+ for SSL host name checking will be the target parameter (assuming that the
+ secure channel is an SSL channel). If this parameter is specified and the
+ underlying is not an SSL channel, it will just be ignored. */
#define GRPC_SSL_TARGET_NAME_OVERRIDE_ARG "grpc.ssl_target_name_override"
-/* Maximum metadata size, in bytes. */
+/** Maximum metadata size, in bytes. Note this limit applies to the max sum of
+ all metadata key-value entries in a batch of headers. */
#define GRPC_ARG_MAX_METADATA_SIZE "grpc.max_metadata_size"
/** If non-zero, allow the use of SO_REUSEPORT if it's available (default 1) */
#define GRPC_ARG_ALLOW_REUSEPORT "grpc.so_reuseport"
-/** If non-zero, a pointer to a buffer pool (use grpc_resource_quota_arg_vtable
- to fetch an appropriate pointer arg vtable) */
+/** If non-zero, a pointer to a buffer pool (a pointer of type
+ * grpc_resource_quota*). (use grpc_resource_quota_arg_vtable() to fetch an
+ * appropriate pointer arg vtable) */
#define GRPC_ARG_RESOURCE_QUOTA "grpc.resource_quota"
/** If non-zero, expand wildcard addresses to a list of local addresses. */
#define GRPC_ARG_EXPAND_WILDCARD_ADDRS "grpc.expand_wildcard_addrs"
@@ -281,13 +281,16 @@ typedef struct {
#define GRPC_ARG_SOCKET_MUTATOR "grpc.socket_mutator"
/** The grpc_socket_factory instance to create and bind sockets. A pointer. */
#define GRPC_ARG_SOCKET_FACTORY "grpc.socket_factory"
-/** If non-zero, Cronet transport will coalesce packets to fewer frames when
- * possible. */
+/** If non-zero, Cronet transport will coalesce packets to fewer frames
+ * when possible. */
#define GRPC_ARG_USE_CRONET_PACKET_COALESCING \
"grpc.use_cronet_packet_coalescing"
-/* Channel arg (integer) setting how large a slice to try and read from the wire
-each time recvmsg (or equivalent) is called */
+/** Channel arg (integer) setting how large a slice to try and read from the
+ wire each time recvmsg (or equivalent) is called **/
#define GRPC_ARG_TCP_READ_CHUNK_SIZE "grpc.experimental.tcp_read_chunk_size"
+/** Note this is not a "channel arg" key. This is the default slice size to use
+ * when trying to read from the wire if the GRPC_ARG_TCP_READ_CHUNK_SIZE
+ * channel arg is unspecified. */
#define GRPC_TCP_DEFAULT_READ_SLICE_SIZE 8192
#define GRPC_ARG_TCP_MIN_READ_CHUNK_SIZE \
"grpc.experimental.tcp_min_read_chunk_size"
@@ -331,8 +334,8 @@ typedef enum grpc_call_error {
GRPC_CALL_ERROR_INVALID_METADATA,
/** invalid message was passed to this call */
GRPC_CALL_ERROR_INVALID_MESSAGE,
- /** completion queue for notification has not been registered with the
- server */
+ /** completion queue for notification has not been registered
+ * with the server */
GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE,
/** this batch of operations leads to more operations than allowed */
GRPC_CALL_ERROR_BATCH_TOO_BIG,
@@ -340,12 +343,12 @@ typedef enum grpc_call_error {
GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH
} grpc_call_error;
-/* Default send/receive message size limits in bytes. -1 for unlimited. */
-/* TODO(roth) Make this match the default receive limit after next release */
+/** Default send/receive message size limits in bytes. -1 for unlimited. */
+/** TODO(roth) Make this match the default receive limit after next release */
#define GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH -1
#define GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH (4 * 1024 * 1024)
-/* Write Flags: */
+/** Write Flags: */
/** Hint that the write may be buffered and need not go out on the wire
immediately. GRPC is free to buffer the message until the next non-buffered
write, or until writes_done, but it need not buffer completely or at all. */
@@ -356,7 +359,7 @@ typedef enum grpc_call_error {
/** Mask of all valid flags. */
#define GRPC_WRITE_USED_MASK (GRPC_WRITE_BUFFER_HINT | GRPC_WRITE_NO_COMPRESS)
-/* Initial metadata flags */
+/** Initial metadata flags */
/** Signal that the call is idempotent */
#define GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST (0x00000010u)
/** Signal that the call should not return UNAVAILABLE before it has started */
@@ -379,8 +382,8 @@ typedef enum grpc_call_error {
/** A single metadata element */
typedef struct grpc_metadata {
- /* the key, value values are expected to line up with grpc_mdelem: if changing
- them, update metadata.h at the same time. */
+ /** the key, value values are expected to line up with grpc_mdelem: if
+ changing them, update metadata.h at the same time. */
grpc_slice key;
grpc_slice value;
@@ -447,15 +450,13 @@ typedef enum {
GRPC_OP_SEND_MESSAGE,
/** Send a close from the client: one and only one instance MUST be sent from
the client, unless the call was cancelled - in which case this can be
- skipped.
- This op completes after all bytes for the call (including the close)
- have passed outgoing flow control. */
+ skipped. This op completes after all bytes for the call
+ (including the close) have passed outgoing flow control. */
GRPC_OP_SEND_CLOSE_FROM_CLIENT,
/** Send status from the server: one and only one instance MUST be sent from
the server unless the call was cancelled - in which case this can be
- skipped.
- This op completes after all bytes for the call (including the status)
- have passed outgoing flow control. */
+ skipped. This op completes after all bytes for the call
+ (including the status) have passed outgoing flow control. */
GRPC_OP_SEND_STATUS_FROM_SERVER,
/** Receive initial metadata: one and only one MUST be made on the client,
must not be made on the server.
@@ -473,10 +474,10 @@ typedef enum {
This op completes after all activity on the call has completed. */
GRPC_OP_RECV_STATUS_ON_CLIENT,
/** Receive close on the server: one and only one must be made on the
- server.
- This op completes after the close has been received by the server.
- This operation always succeeds, meaning ops paired with this operation
- will also appear to succeed, even though they may not have. */
+ server. This op completes after the close has been received by the
+ server. This operation always succeeds, meaning ops paired with
+ this operation will also appear to succeed, even though they may not
+ have. */
GRPC_OP_RECV_CLOSE_ON_SERVER
} grpc_op_type;
@@ -513,7 +514,7 @@ typedef struct grpc_op {
size_t trailing_metadata_count;
grpc_metadata *trailing_metadata;
grpc_status_code status;
- /* optional: set to NULL if no details need sending, non-NULL if they do
+ /** optional: set to NULL if no details need sending, non-NULL if they do
* pointer will not be retained past the start_batch call
*/
grpc_slice *status_details;
@@ -537,8 +538,7 @@ typedef struct grpc_op {
elements stays with the call object (ie key, value members are owned
by the call object, trailing_metadata->array is owned by the caller).
After the operation completes, call grpc_metadata_array_destroy on
- this
- value, or reuse it in a future op. */
+ this value, or reuse it in a future op. */
grpc_metadata_array *trailing_metadata;
grpc_status_code *status;
grpc_slice *status_details;
@@ -553,10 +553,10 @@ typedef struct grpc_op {
/** Information requested from the channel. */
typedef struct {
- /* If non-NULL, will be set to point to a string indicating the LB
+ /** If non-NULL, will be set to point to a string indicating the LB
* policy name. Caller takes ownership. */
char **lb_policy_name;
- /* If non-NULL, will be set to point to a string containing the
+ /** If non-NULL, will be set to point to a string containing the
* service config used by the channel in JSON form. */
char **service_config_json;
} grpc_channel_info;
@@ -600,9 +600,9 @@ typedef enum {
#define GRPC_CQ_CURRENT_VERSION 1
typedef struct grpc_completion_queue_attributes {
- /* The version number of this structure. More fields might be added to this
+ /** The version number of this structure. More fields might be added to this
structure in future. */
- int version; /* Set to GRPC_CQ_CURRENT_VERSION */
+ int version; /** Set to GRPC_CQ_CURRENT_VERSION */
grpc_cq_completion_type cq_completion_type;
diff --git a/include/grpc/impl/codegen/propagation_bits.h b/include/grpc/impl/codegen/propagation_bits.h
index 4b64558764..f58edb0e8b 100644
--- a/include/grpc/impl/codegen/propagation_bits.h
+++ b/include/grpc/impl/codegen/propagation_bits.h
@@ -40,7 +40,7 @@
extern "C" {
#endif
-/* Propagation bits: this can be bitwise or-ed to form propagation_mask for
+/** Propagation bits: this can be bitwise or-ed to form propagation_mask for
* grpc_call */
/** Propagate deadline */
#define GRPC_PROPAGATE_DEADLINE ((uint32_t)1)
@@ -50,7 +50,7 @@ extern "C" {
/** Propagate cancellation */
#define GRPC_PROPAGATE_CANCELLATION ((uint32_t)8)
-/* Default propagation mask: clients of the core API are encouraged to encode
+/** Default propagation mask: clients of the core API are encouraged to encode
deltas from this in their implementations... ie write:
GRPC_PROPAGATE_DEFAULTS & ~GRPC_PROPAGATE_DEADLINE to disable deadline
propagation. Doing so gives flexibility in the future to define new
diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h
index b89a3f7910..5c01c87cb8 100644
--- a/include/grpc/impl/codegen/slice.h
+++ b/include/grpc/impl/codegen/slice.h
@@ -43,7 +43,7 @@
typedef struct grpc_slice grpc_slice;
-/* Slice API
+/** Slice API
A slice represents a contiguous reference counted array of bytes.
It is cheap to take references to a slice, and it is cheap to create a
@@ -63,14 +63,14 @@ typedef struct grpc_slice_refcount_vtable {
uint32_t (*hash)(grpc_slice slice);
} grpc_slice_refcount_vtable;
-/* Reference count container for grpc_slice. Contains function pointers to
+/** Reference count container for grpc_slice. Contains function pointers to
increment and decrement reference counts. Implementations should cleanup
when the reference count drops to zero.
Typically client code should not touch this, and use grpc_slice_malloc,
grpc_slice_new, or grpc_slice_new_with_len instead. */
typedef struct grpc_slice_refcount {
const grpc_slice_refcount_vtable *vtable;
- /* If a subset of this slice is taken, use this pointer for the refcount.
+ /** If a subset of this slice is taken, use this pointer for the refcount.
Typically points back to the refcount itself, however iterning
implementations can use this to avoid a verification step on each hash
or equality check */
@@ -79,7 +79,7 @@ typedef struct grpc_slice_refcount {
#define GRPC_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1)
-/* A grpc_slice s, if initialized, represents the byte range
+/** A grpc_slice s, if initialized, represents the byte range
s.bytes[0..s.length-1].
It can have an associated ref count which has a destruction routine to be run
@@ -104,23 +104,23 @@ struct grpc_slice {
#define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8
-/* Represents an expandable array of slices, to be interpreted as a
+/** Represents an expandable array of slices, to be interpreted as a
single item. */
typedef struct {
- /* This is for internal use only. External users (i.e any code outside grpc
+ /** This is for internal use only. External users (i.e any code outside grpc
* core) MUST NOT use this field */
grpc_slice *base_slices;
- /* slices in the array (Points to the first valid grpc_slice in the array) */
+ /** slices in the array (Points to the first valid grpc_slice in the array) */
grpc_slice *slices;
- /* the number of slices in the array */
+ /** the number of slices in the array */
size_t count;
- /* the number of slices allocated in the array. External users (i.e any code
+ /** the number of slices allocated in the array. External users (i.e any code
* outside grpc core) MUST NOT use this field */
size_t capacity;
- /* the combined length of all slices in the array */
+ /** the combined length of all slices in the array */
size_t length;
- /* inlined elements to avoid allocations */
+ /** inlined elements to avoid allocations */
grpc_slice inlined[GRPC_SLICE_BUFFER_INLINE_ELEMENTS];
} grpc_slice_buffer;
diff --git a/include/grpc/impl/codegen/status.h b/include/grpc/impl/codegen/status.h
index 29e4570f7c..a2ad6b19e6 100644
--- a/include/grpc/impl/codegen/status.h
+++ b/include/grpc/impl/codegen/status.h
@@ -39,40 +39,40 @@ extern "C" {
#endif
typedef enum {
- /* Not an error; returned on success */
+ /** Not an error; returned on success */
GRPC_STATUS_OK = 0,
- /* The operation was cancelled (typically by the caller). */
+ /** The operation was cancelled (typically by the caller). */
GRPC_STATUS_CANCELLED = 1,
- /* Unknown error. An example of where this error may be returned is
+ /** Unknown error. An example of where this error may be returned is
if a Status value received from another address space belongs to
an error-space that is not known in this address space. Also
errors raised by APIs that do not return enough error information
may be converted to this error. */
GRPC_STATUS_UNKNOWN = 2,
- /* Client specified an invalid argument. Note that this differs
+ /** Client specified an invalid argument. Note that this differs
from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments
that are problematic regardless of the state of the system
(e.g., a malformed file name). */
GRPC_STATUS_INVALID_ARGUMENT = 3,
- /* Deadline expired before operation could complete. For operations
+ /** Deadline expired before operation could complete. For operations
that change the state of the system, this error may be returned
even if the operation has completed successfully. For example, a
successful response from a server could have been delayed long
enough for the deadline to expire. */
GRPC_STATUS_DEADLINE_EXCEEDED = 4,
- /* Some requested entity (e.g., file or directory) was not found. */
+ /** Some requested entity (e.g., file or directory) was not found. */
GRPC_STATUS_NOT_FOUND = 5,
- /* Some entity that we attempted to create (e.g., file or directory)
+ /** Some entity that we attempted to create (e.g., file or directory)
already exists. */
GRPC_STATUS_ALREADY_EXISTS = 6,
- /* The caller does not have permission to execute the specified
+ /** The caller does not have permission to execute the specified
operation. PERMISSION_DENIED must not be used for rejections
caused by exhausting some resource (use RESOURCE_EXHAUSTED
instead for those errors). PERMISSION_DENIED must not be
@@ -80,15 +80,15 @@ typedef enum {
instead for those errors). */
GRPC_STATUS_PERMISSION_DENIED = 7,
- /* The request does not have valid authentication credentials for the
+ /** The request does not have valid authentication credentials for the
operation. */
GRPC_STATUS_UNAUTHENTICATED = 16,
- /* Some resource has been exhausted, perhaps a per-user quota, or
+ /** Some resource has been exhausted, perhaps a per-user quota, or
perhaps the entire file system is out of space. */
GRPC_STATUS_RESOURCE_EXHAUSTED = 8,
- /* Operation was rejected because the system is not in a state
+ /** Operation was rejected because the system is not in a state
required for the operation's execution. For example, directory
to be deleted may be non-empty, an rmdir operation is applied to
a non-directory, etc.
@@ -109,14 +109,14 @@ typedef enum {
read-modify-write on the same resource. */
GRPC_STATUS_FAILED_PRECONDITION = 9,
- /* The operation was aborted, typically due to a concurrency issue
+ /** The operation was aborted, typically due to a concurrency issue
like sequencer check failures, transaction aborts, etc.
See litmus test above for deciding between FAILED_PRECONDITION,
ABORTED, and UNAVAILABLE. */
GRPC_STATUS_ABORTED = 10,
- /* Operation was attempted past the valid range. E.g., seeking or
+ /** Operation was attempted past the valid range. E.g., seeking or
reading past end of file.
Unlike INVALID_ARGUMENT, this error indicates a problem that may
@@ -133,26 +133,31 @@ typedef enum {
they are done. */
GRPC_STATUS_OUT_OF_RANGE = 11,
- /* Operation is not implemented or not supported/enabled in this service. */
+ /** Operation is not implemented or not supported/enabled in this service. */
GRPC_STATUS_UNIMPLEMENTED = 12,
- /* Internal errors. Means some invariants expected by underlying
+ /** Internal errors. Means some invariants expected by underlying
system has been broken. If you see one of these errors,
something is very broken. */
GRPC_STATUS_INTERNAL = 13,
- /* The service is currently unavailable. This is a most likely a
+ /** The service is currently unavailable. This is a most likely a
transient condition and may be corrected by retrying with
a backoff.
+ WARNING: Although data MIGHT not have been transmitted when this
+ status occurs, there is NOT A GUARANTEE that the server has not seen
+ anything. So in general it is unsafe to retry on this status code
+ if the call is non-idempotent.
+
See litmus test above for deciding between FAILED_PRECONDITION,
ABORTED, and UNAVAILABLE. */
GRPC_STATUS_UNAVAILABLE = 14,
- /* Unrecoverable data loss or corruption. */
+ /** Unrecoverable data loss or corruption. */
GRPC_STATUS_DATA_LOSS = 15,
- /* Force users to include a default branch: */
+ /** Force users to include a default branch: */
GRPC_STATUS__DO_NOT_USE = -1
} grpc_status_code;
diff --git a/include/grpc/impl/codegen/sync.h b/include/grpc/impl/codegen/sync.h
index 6a8e8a644f..5a135fab4c 100644
--- a/include/grpc/impl/codegen/sync.h
+++ b/include/grpc/impl/codegen/sync.h
@@ -33,7 +33,7 @@
#ifndef GRPC_IMPL_CODEGEN_SYNC_H
#define GRPC_IMPL_CODEGEN_SYNC_H
-/* Synchronization primitives for GPR.
+/** Synchronization primitives for GPR.
The type gpr_mu provides a non-reentrant mutex (lock).
diff --git a/include/grpc/slice.h b/include/grpc/slice.h
index 9c4b158ae8..19f546afb6 100644
--- a/include/grpc/slice.h
+++ b/include/grpc/slice.h
@@ -41,11 +41,11 @@
extern "C" {
#endif
-/* Increment the refcount of s. Requires slice is initialized.
+/** Increment the refcount of s. Requires slice is initialized.
Returns s. */
GPRAPI grpc_slice grpc_slice_ref(grpc_slice s);
-/* Decrement the ref count of s. If the ref count of s reaches zero, all
+/** Decrement the ref count of s. If the ref count of s reaches zero, all
slices sharing the ref count are destroyed, and considered no longer
initialized. If s is ultimately derived from a call to grpc_slice_new(start,
len, dest) where dest!=NULL , then (*dest)(start) is called, else if s is
@@ -53,15 +53,15 @@ GPRAPI grpc_slice grpc_slice_ref(grpc_slice s);
where dest!=NULL , then (*dest)(start, len). Requires s initialized. */
GPRAPI void grpc_slice_unref(grpc_slice s);
-/* Copy slice - create a new slice that contains the same data as s */
+/** Copy slice - create a new slice that contains the same data as s */
GPRAPI grpc_slice grpc_slice_copy(grpc_slice s);
-/* Create a slice pointing at some data. Calls malloc to allocate a refcount
+/** Create a slice pointing at some data. Calls malloc to allocate a refcount
for the object, and arranges that destroy will be called with the pointer
passed in at destruction. */
GPRAPI grpc_slice grpc_slice_new(void *p, size_t len, void (*destroy)(void *));
-/* Equivalent to grpc_slice_new, but with a separate pointer that is
+/** Equivalent to grpc_slice_new, but with a separate pointer that is
passed to the destroy function. This function can be useful when
the data is part of a larger structure that must be destroyed when
the data is no longer needed. */
@@ -69,12 +69,12 @@ GPRAPI grpc_slice grpc_slice_new_with_user_data(void *p, size_t len,
void (*destroy)(void *),
void *user_data);
-/* Equivalent to grpc_slice_new, but with a two argument destroy function that
+/** Equivalent to grpc_slice_new, but with a two argument destroy function that
also takes the slice length. */
GPRAPI grpc_slice grpc_slice_new_with_len(void *p, size_t len,
void (*destroy)(void *, size_t));
-/* Equivalent to grpc_slice_new(malloc(len), len, free), but saves one malloc()
+/** Equivalent to grpc_slice_new(malloc(len), len, free), but saves one malloc()
call.
Aborts if malloc() fails. */
GPRAPI grpc_slice grpc_slice_malloc(size_t length);
@@ -86,13 +86,13 @@ GPRAPI grpc_slice grpc_slice_malloc_large(size_t length);
.data.inlined = {.length = (uint8_t)(len)}} \
: grpc_slice_malloc_large((len)))
-/* Intern a slice:
+/** Intern a slice:
The return value for two invocations of this function with the same sequence
of bytes is a slice which points to the same memory. */
GPRAPI grpc_slice grpc_slice_intern(grpc_slice slice);
-/* Create a slice by copying a string.
+/** Create a slice by copying a string.
Does not preserve null terminators.
Equivalent to:
size_t len = strlen(source);
@@ -100,29 +100,29 @@ GPRAPI grpc_slice grpc_slice_intern(grpc_slice slice);
memcpy(slice->data, source, len); */
GPRAPI grpc_slice grpc_slice_from_copied_string(const char *source);
-/* Create a slice by copying a buffer.
+/** Create a slice by copying a buffer.
Equivalent to:
grpc_slice slice = grpc_slice_malloc(len);
memcpy(slice->data, source, len); */
GPRAPI grpc_slice grpc_slice_from_copied_buffer(const char *source, size_t len);
-/* Create a slice pointing to constant memory */
+/** Create a slice pointing to constant memory */
GPRAPI grpc_slice grpc_slice_from_static_string(const char *source);
-/* Create a slice pointing to constant memory */
+/** Create a slice pointing to constant memory */
GPRAPI grpc_slice grpc_slice_from_static_buffer(const void *source, size_t len);
-/* Return a result slice derived from s, which shares a ref count with \a s,
+/** Return a result slice derived from s, which shares a ref count with \a s,
where result.data==s.data+begin, and result.length==end-begin. The ref count
of \a s is increased by one. Do not assign result back to \a s.
Requires s initialized, begin <= end, begin <= s.length, and
end <= source->length. */
GPRAPI grpc_slice grpc_slice_sub(grpc_slice s, size_t begin, size_t end);
-/* The same as grpc_slice_sub, but without altering the ref count */
+/** The same as grpc_slice_sub, but without altering the ref count */
GPRAPI grpc_slice grpc_slice_sub_no_ref(grpc_slice s, size_t begin, size_t end);
-/* Splits s into two: modifies s to be s[0:split], and returns a new slice,
+/** Splits s into two: modifies s to be s[0:split], and returns a new slice,
sharing a refcount with s, that contains s[split:s.length].
Requires s intialized, split <= s.length */
GPRAPI grpc_slice grpc_slice_split_tail(grpc_slice *s, size_t split);
@@ -133,13 +133,13 @@ typedef enum {
GRPC_SLICE_REF_BOTH = 1 + 2
} grpc_slice_ref_whom;
-/* The same as grpc_slice_split_tail, but with an option to skip altering
+/** The same as grpc_slice_split_tail, but with an option to skip altering
* refcounts (grpc_slice_split_tail_maybe_ref(..., true) is equivalent to
* grpc_slice_split_tail(...)) */
GPRAPI grpc_slice grpc_slice_split_tail_maybe_ref(grpc_slice *s, size_t split,
grpc_slice_ref_whom ref_whom);
-/* Splits s into two: modifies s to be s[split:s.length], and returns a new
+/** Splits s into two: modifies s to be s[split:s.length], and returns a new
slice, sharing a refcount with s, that contains s[0:split].
Requires s intialized, split <= s.length */
GPRAPI grpc_slice grpc_slice_split_head(grpc_slice *s, size_t split);
@@ -151,35 +151,35 @@ GPRAPI int grpc_slice_default_eq_impl(grpc_slice a, grpc_slice b);
GPRAPI int grpc_slice_eq(grpc_slice a, grpc_slice b);
-/* Returns <0 if a < b, ==0 if a == b, >0 if a > b
+/** Returns <0 if a < b, ==0 if a == b, >0 if a > b
The order is arbitrary, and is not guaranteed to be stable across different
versions of the API. */
GPRAPI int grpc_slice_cmp(grpc_slice a, grpc_slice b);
GPRAPI int grpc_slice_str_cmp(grpc_slice a, const char *b);
GPRAPI int grpc_slice_buf_cmp(grpc_slice a, const void *b, size_t blen);
-/* return non-zero if the first blen bytes of a are equal to b */
+/** return non-zero if the first blen bytes of a are equal to b */
GPRAPI int grpc_slice_buf_start_eq(grpc_slice a, const void *b, size_t blen);
-/* return the index of the last instance of \a c in \a s, or -1 if not found */
+/** return the index of the last instance of \a c in \a s, or -1 if not found */
GPRAPI int grpc_slice_rchr(grpc_slice s, char c);
GPRAPI int grpc_slice_chr(grpc_slice s, char c);
-/* return the index of the first occurance of \a needle in \a haystack, or -1 if
- * it's not found */
+/** return the index of the first occurance of \a needle in \a haystack, or -1
+ if it's not found */
GPRAPI int grpc_slice_slice(grpc_slice haystack, grpc_slice needle);
GPRAPI uint32_t grpc_slice_hash(grpc_slice s);
-/* Do two slices point at the same memory, with the same length
+/** Do two slices point at the same memory, with the same length
If a or b is inlined, actually compares data */
GPRAPI int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b);
-/* Return a slice pointing to newly allocated memory that has the same contents
+/** Return a slice pointing to newly allocated memory that has the same contents
* as \a s */
GPRAPI grpc_slice grpc_slice_dup(grpc_slice a);
-/* Return a copy of slice as a C string. Offers no protection against embedded
+/** Return a copy of slice as a C string. Offers no protection against embedded
NULL's. Returned string must be freed with gpr_free. */
GPRAPI char *grpc_slice_to_c_string(grpc_slice s);
diff --git a/include/grpc/slice_buffer.h b/include/grpc/slice_buffer.h
index cdbd74776c..0d593954dc 100644
--- a/include/grpc/slice_buffer.h
+++ b/include/grpc/slice_buffer.h
@@ -40,15 +40,15 @@
extern "C" {
#endif
-/* initialize a slice buffer */
+/** initialize a slice buffer */
GPRAPI void grpc_slice_buffer_init(grpc_slice_buffer *sb);
-/* destroy a slice buffer - unrefs any held elements */
+/** destroy a slice buffer - unrefs any held elements */
GPRAPI void grpc_slice_buffer_destroy(grpc_slice_buffer *sb);
-/* Add an element to a slice buffer - takes ownership of the slice.
+/** Add an element to a slice buffer - takes ownership of the slice.
This function is allowed to concatenate the passed in slice to the end of
some other slice if desired by the slice buffer. */
GPRAPI void grpc_slice_buffer_add(grpc_slice_buffer *sb, grpc_slice slice);
-/* add an element to a slice buffer - takes ownership of the slice and returns
+/** add an element to a slice buffer - takes ownership of the slice and returns
the index of the slice.
Guarantees that the slice will not be concatenated at the end of another
slice (i.e. the data for this slice will begin at the first byte of the
@@ -59,35 +59,35 @@ GPRAPI size_t grpc_slice_buffer_add_indexed(grpc_slice_buffer *sb,
grpc_slice slice);
GPRAPI void grpc_slice_buffer_addn(grpc_slice_buffer *sb, grpc_slice *slices,
size_t n);
-/* add a very small (less than 8 bytes) amount of data to the end of a slice
+/** add a very small (less than 8 bytes) amount of data to the end of a slice
buffer: returns a pointer into which to add the data */
GPRAPI uint8_t *grpc_slice_buffer_tiny_add(grpc_slice_buffer *sb, size_t len);
-/* pop the last buffer, but don't unref it */
+/** pop the last buffer, but don't unref it */
GPRAPI void grpc_slice_buffer_pop(grpc_slice_buffer *sb);
-/* clear a slice buffer, unref all elements */
+/** clear a slice buffer, unref all elements */
GPRAPI void grpc_slice_buffer_reset_and_unref(grpc_slice_buffer *sb);
-/* swap the contents of two slice buffers */
+/** swap the contents of two slice buffers */
GPRAPI void grpc_slice_buffer_swap(grpc_slice_buffer *a, grpc_slice_buffer *b);
-/* move all of the elements of src into dst */
+/** move all of the elements of src into dst */
GPRAPI void grpc_slice_buffer_move_into(grpc_slice_buffer *src,
grpc_slice_buffer *dst);
-/* remove n bytes from the end of a slice buffer */
+/** remove n bytes from the end of a slice buffer */
GPRAPI void grpc_slice_buffer_trim_end(grpc_slice_buffer *src, size_t n,
grpc_slice_buffer *garbage);
-/* move the first n bytes of src into dst */
+/** move the first n bytes of src into dst */
GPRAPI void grpc_slice_buffer_move_first(grpc_slice_buffer *src, size_t n,
grpc_slice_buffer *dst);
-/* move the first n bytes of src into dst without adding references */
+/** move the first n bytes of src into dst without adding references */
GPRAPI void grpc_slice_buffer_move_first_no_ref(grpc_slice_buffer *src,
size_t n,
grpc_slice_buffer *dst);
-/* move the first n bytes of src into dst (copying them) */
+/** move the first n bytes of src into dst (copying them) */
GPRAPI void grpc_slice_buffer_move_first_into_buffer(grpc_exec_ctx *exec_ctx,
grpc_slice_buffer *src,
size_t n, void *dst);
-/* take the first slice in the slice buffer */
+/** take the first slice in the slice buffer */
GPRAPI grpc_slice grpc_slice_buffer_take_first(grpc_slice_buffer *src);
-/* undo the above with (a possibly different) \a slice */
+/** undo the above with (a possibly different) \a slice */
GPRAPI void grpc_slice_buffer_undo_take_first(grpc_slice_buffer *src,
grpc_slice slice);
diff --git a/include/grpc/support/alloc.h b/include/grpc/support/alloc.h
index 017d75a3d0..99be2d161a 100644
--- a/include/grpc/support/alloc.h
+++ b/include/grpc/support/alloc.h
@@ -44,26 +44,26 @@ extern "C" {
typedef struct gpr_allocation_functions {
void *(*malloc_fn)(size_t size);
- void *(*zalloc_fn)(size_t size); /* if NULL, uses malloc_fn then memset */
+ void *(*zalloc_fn)(size_t size); /** if NULL, uses malloc_fn then memset */
void *(*realloc_fn)(void *ptr, size_t size);
void (*free_fn)(void *ptr);
} gpr_allocation_functions;
-/* malloc.
+/** malloc.
* If size==0, always returns NULL. Otherwise this function never returns NULL.
* The pointer returned is suitably aligned for any kind of variable it could
* contain.
*/
GPRAPI void *gpr_malloc(size_t size);
-/* like malloc, but zero all bytes before returning them */
+/** like malloc, but zero all bytes before returning them */
GPRAPI void *gpr_zalloc(size_t size);
-/* free */
+/** free */
GPRAPI void gpr_free(void *ptr);
-/* realloc, never returns NULL */
+/** realloc, never returns NULL */
GPRAPI void *gpr_realloc(void *p, size_t size);
-/* aligned malloc, never returns NULL, will align to 1 << alignment_log */
+/** aligned malloc, never returns NULL, will align to 1 << alignment_log */
GPRAPI void *gpr_malloc_aligned(size_t size, size_t alignment_log);
-/* free memory allocated by gpr_malloc_aligned */
+/** free memory allocated by gpr_malloc_aligned */
GPRAPI void gpr_free_aligned(void *ptr);
/** Request the family of allocation functions in \a functions be used. NOTE
diff --git a/include/grpc/support/cmdline.h b/include/grpc/support/cmdline.h
index 5b7bc82594..5a83afb464 100644
--- a/include/grpc/support/cmdline.h
+++ b/include/grpc/support/cmdline.h
@@ -40,7 +40,7 @@
extern "C" {
#endif
-/* Simple command line parser.
+/** Simple command line parser.
Supports flags that can be specified as -foo, --foo, --no-foo, -no-foo, etc
And integers, strings that can be specified as -foo=4, -foo blah, etc
@@ -68,32 +68,32 @@ extern "C" {
typedef struct gpr_cmdline gpr_cmdline;
-/* Construct a command line parser: takes a short description of the tool
+/** Construct a command line parser: takes a short description of the tool
doing the parsing */
GPRAPI gpr_cmdline *gpr_cmdline_create(const char *description);
-/* Add an integer parameter, with a name (used on the command line) and some
+/** Add an integer parameter, with a name (used on the command line) and some
helpful text (used in the command usage) */
GPRAPI void gpr_cmdline_add_int(gpr_cmdline *cl, const char *name,
const char *help, int *value);
-/* The same, for a boolean flag */
+/** The same, for a boolean flag */
GPRAPI void gpr_cmdline_add_flag(gpr_cmdline *cl, const char *name,
const char *help, int *value);
-/* And for a string */
+/** And for a string */
GPRAPI void gpr_cmdline_add_string(gpr_cmdline *cl, const char *name,
const char *help, char **value);
-/* Set a callback for non-named arguments */
+/** Set a callback for non-named arguments */
GPRAPI void gpr_cmdline_on_extra_arg(
gpr_cmdline *cl, const char *name, const char *help,
void (*on_extra_arg)(void *user_data, const char *arg), void *user_data);
-/* Enable surviving failure: default behavior is to exit the process */
+/** Enable surviving failure: default behavior is to exit the process */
GPRAPI void gpr_cmdline_set_survive_failure(gpr_cmdline *cl);
-/* Parse the command line; returns 1 on success, on failure either dies
+/** Parse the command line; returns 1 on success, on failure either dies
(by default) or returns 0 if gpr_cmdline_set_survive_failure() has been
called */
GPRAPI int gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv);
-/* Destroy the parser */
+/** Destroy the parser */
GPRAPI void gpr_cmdline_destroy(gpr_cmdline *cl);
-/* Get a string describing usage */
+/** Get a string describing usage */
GPRAPI char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0);
#ifdef __cplusplus
diff --git a/include/grpc/support/cpu.h b/include/grpc/support/cpu.h
index 6734feb391..0da02ada22 100644
--- a/include/grpc/support/cpu.h
+++ b/include/grpc/support/cpu.h
@@ -40,13 +40,13 @@
extern "C" {
#endif
-/* Interface providing CPU information for currently running system */
+/** Interface providing CPU information for currently running system */
-/* Return the number of CPU cores on the current system. Will return 0 if
+/** Return the number of CPU cores on the current system. Will return 0 if
the information is not available. */
GPRAPI unsigned gpr_cpu_num_cores(void);
-/* Return the CPU on which the current thread is executing; N.B. This should
+/** Return the CPU on which the current thread is executing; N.B. This should
be considered advisory only - it is possible that the thread is switched
to a different CPU at any time. Returns a value in range
[0, gpr_cpu_num_cores() - 1] */
diff --git a/include/grpc/support/histogram.h b/include/grpc/support/histogram.h
index c545038528..96db758878 100644
--- a/include/grpc/support/histogram.h
+++ b/include/grpc/support/histogram.h
@@ -48,7 +48,7 @@ GPRAPI gpr_histogram *gpr_histogram_create(double resolution,
GPRAPI void gpr_histogram_destroy(gpr_histogram *h);
GPRAPI void gpr_histogram_add(gpr_histogram *h, double x);
-/* The following merges the second histogram into the first. It only works
+/** The following merges the second histogram into the first. It only works
if they have the same buckets and resolution. Returns 0 on failure, 1
on success */
GPRAPI int gpr_histogram_merge(gpr_histogram *dst, const gpr_histogram *src);
diff --git a/include/grpc/support/host_port.h b/include/grpc/support/host_port.h
index 15819543a9..ee786beb19 100644
--- a/include/grpc/support/host_port.h
+++ b/include/grpc/support/host_port.h
@@ -40,7 +40,7 @@
extern "C" {
#endif
-/* Given a host and port, creates a newly-allocated string of the form
+/** Given a host and port, creates a newly-allocated string of the form
"host:port" or "[ho:st]:port", depending on whether the host contains colons
like an IPv6 literal. If the host is already bracketed, then additional
brackets will not be added.
@@ -52,7 +52,7 @@ extern "C" {
In the unlikely event of an error, returns -1 and sets *out to NULL. */
GPRAPI int gpr_join_host_port(char **out, const char *host, int port);
-/* Given a name in the form "host:port" or "[ho:st]:port", split into hostname
+/** Given a name in the form "host:port" or "[ho:st]:port", split into hostname
and port number, into newly allocated strings, which must later be
destroyed using gpr_free().
Return 1 on success, 0 on failure. Guarantees *host and *port == NULL on
diff --git a/include/grpc/support/log.h b/include/grpc/support/log.h
index 88346cc9f4..917b01183a 100644
--- a/include/grpc/support/log.h
+++ b/include/grpc/support/log.h
@@ -44,7 +44,7 @@
extern "C" {
#endif
-/* GPR log API.
+/** GPR log API.
Usage (within grpc):
@@ -54,7 +54,7 @@ extern "C" {
gpr_log(GPR_INFO, "hello world");
gpr_log(GPR_ERROR, "%d %s!!", argument1, argument2); */
-/* The severity of a log message - use the #defines below when calling into
+/** The severity of a log message - use the #defines below when calling into
gpr_log to additionally supply file and line data */
typedef enum gpr_log_severity {
GPR_LOG_SEVERITY_DEBUG,
@@ -64,15 +64,15 @@ typedef enum gpr_log_severity {
#define GPR_LOG_VERBOSITY_UNSET -1
-/* Returns a string representation of the log severity */
+/** Returns a string representation of the log severity */
const char *gpr_log_severity_string(gpr_log_severity severity);
-/* Macros to build log contexts at various severity levels */
+/** Macros to build log contexts at various severity levels */
#define GPR_DEBUG __FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG
#define GPR_INFO __FILE__, __LINE__, GPR_LOG_SEVERITY_INFO
#define GPR_ERROR __FILE__, __LINE__, GPR_LOG_SEVERITY_ERROR
-/* Log a message. It's advised to use GPR_xxx above to generate the context
+/** Log a message. It's advised to use GPR_xxx above to generate the context
* for each message */
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity,
const char *format, ...) GPR_PRINT_FORMAT_CHECK(4, 5);
@@ -80,12 +80,12 @@ GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity,
GPRAPI void gpr_log_message(const char *file, int line,
gpr_log_severity severity, const char *message);
-/* Set global log verbosity */
+/** Set global log verbosity */
GPRAPI void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print);
GPRAPI void gpr_log_verbosity_init();
-/* Log overrides: applications can use this API to intercept logging calls
+/** Log overrides: applications can use this API to intercept logging calls
and use their own implementations */
typedef struct {
@@ -98,7 +98,7 @@ typedef struct {
typedef void (*gpr_log_func)(gpr_log_func_args *args);
GPRAPI void gpr_set_log_function(gpr_log_func func);
-/* abort() the process if x is zero, having written a line to the log.
+/** abort() the process if x is zero, having written a line to the log.
Intended for internal invariants. If the error can be recovered from,
without the possibility of corruption, or might best be reflected via
diff --git a/include/grpc/support/log_windows.h b/include/grpc/support/log_windows.h
index 943a8e908b..b8a4078464 100644
--- a/include/grpc/support/log_windows.h
+++ b/include/grpc/support/log_windows.h
@@ -40,7 +40,7 @@
extern "C" {
#endif
-/* Returns a string allocated with gpr_malloc that contains a UTF-8
+/** Returns a string allocated with gpr_malloc that contains a UTF-8
* formatted error message, corresponding to the error messageid.
* Use in conjunction with GetLastError() et al.
*/
diff --git a/include/grpc/support/string_util.h b/include/grpc/support/string_util.h
index 5ab983d15d..8b268a6006 100644
--- a/include/grpc/support/string_util.h
+++ b/include/grpc/support/string_util.h
@@ -40,13 +40,13 @@
extern "C" {
#endif
-/* String utility functions */
+/** String utility functions */
-/* Returns a copy of src that can be passed to gpr_free().
+/** Returns a copy of src that can be passed to gpr_free().
If allocation fails or if src is NULL, returns NULL. */
GPRAPI char *gpr_strdup(const char *src);
-/* printf to a newly-allocated string. The set of supported formats may vary
+/** printf to a newly-allocated string. The set of supported formats may vary
between platforms.
On success, returns the number of bytes printed (excluding the final '\0'),
diff --git a/include/grpc/support/subprocess.h b/include/grpc/support/subprocess.h
index 2baa43ece2..dfb80989dc 100644
--- a/include/grpc/support/subprocess.h
+++ b/include/grpc/support/subprocess.h
@@ -42,13 +42,13 @@ extern "C" {
typedef struct gpr_subprocess gpr_subprocess;
-/* .exe on windows, empty on unices */
+/** .exe on windows, empty on unices */
GPRAPI const char *gpr_subprocess_binary_extension();
GPRAPI gpr_subprocess *gpr_subprocess_create(int argc, const char **argv);
-/* if subprocess has not been joined, kill it */
+/** if subprocess has not been joined, kill it */
GPRAPI void gpr_subprocess_destroy(gpr_subprocess *p);
-/* returns exit status; can be called at most once */
+/** returns exit status; can be called at most once */
GPRAPI int gpr_subprocess_join(gpr_subprocess *p);
GPRAPI void gpr_subprocess_interrupt(gpr_subprocess *p);
diff --git a/include/grpc/support/sync.h b/include/grpc/support/sync.h
index 5cfeecb601..7d727a0cfc 100644
--- a/include/grpc/support/sync.h
+++ b/include/grpc/support/sync.h
@@ -41,49 +41,49 @@
extern "C" {
#endif
-/* --- Mutex interface ---
+/** --- Mutex interface ---
At most one thread may hold an exclusive lock on a mutex at any given time.
Actions taken by a thread that holds a mutex exclusively happen after
actions taken by all previous holders of the mutex. Variables of type
gpr_mu are uninitialized when first declared. */
-/* Initialize *mu. Requires: *mu uninitialized. */
+/** Initialize *mu. Requires: *mu uninitialized. */
GPRAPI void gpr_mu_init(gpr_mu *mu);
-/* Cause *mu no longer to be initialized, freeing any memory in use. Requires:
+/** Cause *mu no longer to be initialized, freeing any memory in use. Requires:
*mu initialized; no other concurrent operation on *mu. */
GPRAPI void gpr_mu_destroy(gpr_mu *mu);
-/* Wait until no thread has a lock on *mu, cause the calling thread to own an
+/** Wait until no thread has a lock on *mu, cause the calling thread to own an
exclusive lock on *mu, then return. May block indefinitely or crash if the
calling thread has a lock on *mu. Requires: *mu initialized. */
GPRAPI void gpr_mu_lock(gpr_mu *mu);
-/* Release an exclusive lock on *mu held by the calling thread. Requires: *mu
+/** Release an exclusive lock on *mu held by the calling thread. Requires: *mu
initialized; the calling thread holds an exclusive lock on *mu. */
GPRAPI void gpr_mu_unlock(gpr_mu *mu);
-/* Without blocking, attempt to acquire an exclusive lock on *mu for the
+/** Without blocking, attempt to acquire an exclusive lock on *mu for the
calling thread, then return non-zero iff success. Fail, if any thread holds
the lock; succeeds with high probability if no thread holds the lock.
Requires: *mu initialized. */
GPRAPI int gpr_mu_trylock(gpr_mu *mu);
-/* --- Condition variable interface ---
+/** --- Condition variable interface ---
A while-loop should be used with gpr_cv_wait() when waiting for conditions
to become true. See the example below. Variables of type gpr_cv are
uninitialized when first declared. */
-/* Initialize *cv. Requires: *cv uninitialized. */
+/** Initialize *cv. Requires: *cv uninitialized. */
GPRAPI void gpr_cv_init(gpr_cv *cv);
-/* Cause *cv no longer to be initialized, freeing any memory in use. Requires:
+/** Cause *cv no longer to be initialized, freeing any memory in use. Requires:
*cv initialized; no other concurrent operation on *cv.*/
GPRAPI void gpr_cv_destroy(gpr_cv *cv);
-/* Atomically release *mu and wait on *cv. When the calling thread is woken
+/** Atomically release *mu and wait on *cv. When the calling thread is woken
from *cv or the deadline abs_deadline is exceeded, execute gpr_mu_lock(mu)
and return whether the deadline was exceeded. Use
abs_deadline==gpr_inf_future for no deadline. abs_deadline can be either
@@ -92,83 +92,83 @@ GPRAPI void gpr_cv_destroy(gpr_cv *cv);
holds an exclusive lock on *mu. */
GPRAPI int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline);
-/* If any threads are waiting on *cv, wake at least one.
+/** If any threads are waiting on *cv, wake at least one.
Clients may treat this as an optimization of gpr_cv_broadcast()
for use in the case where waking more than one waiter is not useful.
Requires: *cv initialized. */
GPRAPI void gpr_cv_signal(gpr_cv *cv);
-/* Wake all threads waiting on *cv. Requires: *cv initialized. */
+/** Wake all threads waiting on *cv. Requires: *cv initialized. */
GPRAPI void gpr_cv_broadcast(gpr_cv *cv);
-/* --- One-time initialization ---
+/** --- One-time initialization ---
gpr_once must be declared with static storage class, and initialized with
GPR_ONCE_INIT. e.g.,
static gpr_once once_var = GPR_ONCE_INIT; */
-/* Ensure that (*init_routine)() has been called exactly once (for the
+/** Ensure that (*init_routine)() has been called exactly once (for the
specified gpr_once instance) and then return.
If multiple threads call gpr_once() on the same gpr_once instance, one of
them will call (*init_routine)(), and the others will block until that call
finishes.*/
GPRAPI void gpr_once_init(gpr_once *once, void (*init_routine)(void));
-/* --- One-time event notification ---
+/** --- One-time event notification ---
These operations act on a gpr_event, which should be initialized with
gpr_ev_init(), or with GPR_EVENT_INIT if static, e.g.,
static gpr_event event_var = GPR_EVENT_INIT;
It requires no destruction. */
-/* Initialize *ev. */
+/** Initialize *ev. */
GPRAPI void gpr_event_init(gpr_event *ev);
-/* Set *ev so that gpr_event_get() and gpr_event_wait() will return value.
+/** Set *ev so that gpr_event_get() and gpr_event_wait() will return value.
Requires: *ev initialized; value != NULL; no prior or concurrent calls to
gpr_event_set(ev, ...) since initialization. */
GPRAPI void gpr_event_set(gpr_event *ev, void *value);
-/* Return the value set by gpr_event_set(ev, ...), or NULL if no such call has
+/** Return the value set by gpr_event_set(ev, ...), or NULL if no such call has
completed. If the result is non-NULL, all operations that occurred prior to
the gpr_event_set(ev, ...) set will be visible after this call returns.
Requires: *ev initialized. This operation is faster than acquiring a mutex
on most platforms. */
GPRAPI void *gpr_event_get(gpr_event *ev);
-/* Wait until *ev is set by gpr_event_set(ev, ...), or abs_deadline is
+/** Wait until *ev is set by gpr_event_set(ev, ...), or abs_deadline is
exceeded, then return gpr_event_get(ev). Requires: *ev initialized. Use
abs_deadline==gpr_inf_future for no deadline. When the event has been
signalled before the call, this operation is faster than acquiring a mutex
on most platforms. */
GPRAPI void *gpr_event_wait(gpr_event *ev, gpr_timespec abs_deadline);
-/* --- Reference counting ---
+/** --- Reference counting ---
These calls act on the type gpr_refcount. It requires no destruction. */
-/* Initialize *r to value n. */
+/** Initialize *r to value n. */
GPRAPI void gpr_ref_init(gpr_refcount *r, int n);
-/* Increment the reference count *r. Requires *r initialized. */
+/** Increment the reference count *r. Requires *r initialized. */
GPRAPI void gpr_ref(gpr_refcount *r);
-/* Increment the reference count *r. Requires *r initialized.
+/** Increment the reference count *r. Requires *r initialized.
Crashes if refcount is zero */
GPRAPI void gpr_ref_non_zero(gpr_refcount *r);
-/* Increment the reference count *r by n. Requires *r initialized, n > 0. */
+/** Increment the reference count *r by n. Requires *r initialized, n > 0. */
GPRAPI void gpr_refn(gpr_refcount *r, int n);
-/* Decrement the reference count *r and return non-zero iff it has reached
+/** Decrement the reference count *r and return non-zero iff it has reached
zero. . Requires *r initialized. */
GPRAPI int gpr_unref(gpr_refcount *r);
-/* Return non-zero iff the reference count of *r is one, and thus is owned
+/** Return non-zero iff the reference count of *r is one, and thus is owned
by exactly one object. */
GPRAPI int gpr_ref_is_unique(gpr_refcount *r);
-/* --- Stats counters ---
+/** --- Stats counters ---
These calls act on the integral type gpr_stats_counter. It requires no
destruction. Static instances may be initialized with
@@ -176,16 +176,16 @@ GPRAPI int gpr_ref_is_unique(gpr_refcount *r);
Beware: These operations do not imply memory barriers. Do not use them to
synchronize other events. */
-/* Initialize *c to the value n. */
+/** Initialize *c to the value n. */
GPRAPI void gpr_stats_init(gpr_stats_counter *c, intptr_t n);
-/* *c += inc. Requires: *c initialized. */
+/** *c += inc. Requires: *c initialized. */
GPRAPI void gpr_stats_inc(gpr_stats_counter *c, intptr_t inc);
-/* Return *c. Requires: *c initialized. */
+/** Return *c. Requires: *c initialized. */
GPRAPI intptr_t gpr_stats_read(const gpr_stats_counter *c);
-/* ==================Example use of interface===================
+/** ==================Example use of interface===================
A producer-consumer queue of up to N integers,
illustrating the use of the calls in this interface. */
#if 0
diff --git a/include/grpc/support/thd.h b/include/grpc/support/thd.h
index 0514288793..ba6cbb0cb0 100644
--- a/include/grpc/support/thd.h
+++ b/include/grpc/support/thd.h
@@ -33,7 +33,7 @@
#ifndef GRPC_SUPPORT_THD_H
#define GRPC_SUPPORT_THD_H
-/* Thread interface for GPR.
+/** Thread interface for GPR.
Types
gpr_thd_id a thread identifier.
@@ -50,37 +50,37 @@ extern "C" {
typedef uintptr_t gpr_thd_id;
-/* Thread creation options. */
+/** Thread creation options. */
typedef struct {
- int flags; /* Opaque field. Get and set with accessors below. */
+ int flags; /** Opaque field. Get and set with accessors below. */
} gpr_thd_options;
-/* Create a new thread running (*thd_body)(arg) and place its thread identifier
+/** Create a new thread running (*thd_body)(arg) and place its thread identifier
in *t, and return true. If there are insufficient resources, return false.
If options==NULL, default options are used.
The thread is immediately runnable, and exits when (*thd_body)() returns. */
GPRAPI int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
const gpr_thd_options *options);
-/* Return a gpr_thd_options struct with all fields set to defaults. */
+/** Return a gpr_thd_options struct with all fields set to defaults. */
GPRAPI gpr_thd_options gpr_thd_options_default(void);
-/* Set the thread to become detached on startup - this is the default. */
+/** Set the thread to become detached on startup - this is the default. */
GPRAPI void gpr_thd_options_set_detached(gpr_thd_options *options);
-/* Set the thread to become joinable - mutually exclusive with detached. */
+/** Set the thread to become joinable - mutually exclusive with detached. */
GPRAPI void gpr_thd_options_set_joinable(gpr_thd_options *options);
-/* Returns non-zero if the option detached is set. */
+/** Returns non-zero if the option detached is set. */
GPRAPI int gpr_thd_options_is_detached(const gpr_thd_options *options);
-/* Returns non-zero if the option joinable is set. */
+/** Returns non-zero if the option joinable is set. */
GPRAPI int gpr_thd_options_is_joinable(const gpr_thd_options *options);
-/* Returns the identifier of the current thread. */
+/** Returns the identifier of the current thread. */
GPRAPI gpr_thd_id gpr_thd_currentid(void);
-/* Blocks until the specified thread properly terminates.
+/** Blocks until the specified thread properly terminates.
Calling this on a detached thread has unpredictable results. */
GPRAPI void gpr_thd_join(gpr_thd_id t);
diff --git a/include/grpc/support/time.h b/include/grpc/support/time.h
index 66bcfca6ed..2384f5e906 100644
--- a/include/grpc/support/time.h
+++ b/include/grpc/support/time.h
@@ -43,11 +43,11 @@
extern "C" {
#endif
-/* Time constants. */
+/** Time constants. */
GPRAPI gpr_timespec
-gpr_time_0(gpr_clock_type type); /* The zero time interval. */
-GPRAPI gpr_timespec gpr_inf_future(gpr_clock_type type); /* The far future */
-GPRAPI gpr_timespec gpr_inf_past(gpr_clock_type type); /* The far past. */
+gpr_time_0(gpr_clock_type type); /** The zero time interval. */
+GPRAPI gpr_timespec gpr_inf_future(gpr_clock_type type); /** The far future */
+GPRAPI gpr_timespec gpr_inf_past(gpr_clock_type type); /** The far past. */
#define GPR_MS_PER_SEC 1000
#define GPR_US_PER_SEC 1000000
@@ -56,28 +56,28 @@ GPRAPI gpr_timespec gpr_inf_past(gpr_clock_type type); /* The far past. */
#define GPR_NS_PER_US 1000
#define GPR_US_PER_MS 1000
-/* initialize time subsystem */
+/** initialize time subsystem */
GPRAPI void gpr_time_init(void);
-/* Return the current time measured from the given clocks epoch. */
+/** Return the current time measured from the given clocks epoch. */
GPRAPI gpr_timespec gpr_now(gpr_clock_type clock);
-/* Convert a timespec from one clock to another */
+/** Convert a timespec from one clock to another */
GPRAPI gpr_timespec gpr_convert_clock_type(gpr_timespec t,
gpr_clock_type target_clock);
-/* Return -ve, 0, or +ve according to whether a < b, a == b, or a > b
+/** Return -ve, 0, or +ve according to whether a < b, a == b, or a > b
respectively. */
GPRAPI int gpr_time_cmp(gpr_timespec a, gpr_timespec b);
GPRAPI gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b);
GPRAPI gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b);
-/* Add and subtract times. Calculations saturate at infinities. */
+/** Add and subtract times. Calculations saturate at infinities. */
GPRAPI gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b);
GPRAPI gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b);
-/* Return a timespec representing a given number of time units. INT64_MIN is
+/** Return a timespec representing a given number of time units. INT64_MIN is
interpreted as gpr_inf_past, and INT64_MAX as gpr_inf_future. */
GPRAPI gpr_timespec gpr_time_from_micros(int64_t x, gpr_clock_type clock_type);
GPRAPI gpr_timespec gpr_time_from_nanos(int64_t x, gpr_clock_type clock_type);
@@ -88,12 +88,12 @@ GPRAPI gpr_timespec gpr_time_from_hours(int64_t x, gpr_clock_type clock_type);
GPRAPI int32_t gpr_time_to_millis(gpr_timespec timespec);
-/* Return 1 if two times are equal or within threshold of each other,
+/** Return 1 if two times are equal or within threshold of each other,
0 otherwise */
GPRAPI int gpr_time_similar(gpr_timespec a, gpr_timespec b,
gpr_timespec threshold);
-/* Sleep until at least 'until' - an absolute timeout */
+/** Sleep until at least 'until' - an absolute timeout */
GPRAPI void gpr_sleep_until(gpr_timespec until);
GPRAPI double gpr_timespec_to_micros(gpr_timespec t);
diff --git a/include/grpc/support/tls.h b/include/grpc/support/tls.h
index 5365449f0d..a48c73b26f 100644
--- a/include/grpc/support/tls.h
+++ b/include/grpc/support/tls.h
@@ -36,7 +36,7 @@
#include <grpc/support/port_platform.h>
-/* Thread local storage.
+/** Thread local storage.
A minimal wrapper that should be implementable across many compilers,
and implementable efficiently across most modern compilers.
diff --git a/include/grpc/support/tls_gcc.h b/include/grpc/support/tls_gcc.h
index a47275f6f4..9667524d34 100644
--- a/include/grpc/support/tls_gcc.h
+++ b/include/grpc/support/tls_gcc.h
@@ -38,7 +38,7 @@
#include <grpc/support/log.h>
-/* Thread local storage based on gcc compiler primitives.
+/** Thread local storage based on gcc compiler primitives.
#include tls.h to use this - and see that file for documentation */
#ifndef NDEBUG
@@ -58,7 +58,7 @@ struct gpr_gcc_thread_local {
*((tls)->inited) = true; \
} while (0)
-/* It is allowed to call gpr_tls_init after gpr_tls_destroy is called. */
+/** It is allowed to call gpr_tls_init after gpr_tls_destroy is called. */
#define gpr_tls_destroy(tls) \
do { \
GPR_ASSERT(*((tls)->inited)); \
diff --git a/include/grpc/support/tls_msvc.h b/include/grpc/support/tls_msvc.h
index efc653b4e4..4ef8eeff0d 100644
--- a/include/grpc/support/tls_msvc.h
+++ b/include/grpc/support/tls_msvc.h
@@ -34,7 +34,7 @@
#ifndef GRPC_SUPPORT_TLS_MSVC_H
#define GRPC_SUPPORT_TLS_MSVC_H
-/* Thread local storage based on ms visual c compiler primitives.
+/** Thread local storage based on ms visual c compiler primitives.
#include tls.h to use this - and see that file for documentation */
struct gpr_msvc_thread_local {
diff --git a/include/grpc/support/tls_pthread.h b/include/grpc/support/tls_pthread.h
index e681da2ecd..7cc6a40645 100644
--- a/include/grpc/support/tls_pthread.h
+++ b/include/grpc/support/tls_pthread.h
@@ -37,7 +37,7 @@
#include <grpc/support/log.h> /* for GPR_ASSERT */
#include <pthread.h>
-/* Thread local storage based on pthread library calls.
+/** Thread local storage based on pthread library calls.
#include tls.h to use this - and see that file for documentation */
struct gpr_pthread_thread_local {
diff --git a/include/grpc/support/useful.h b/include/grpc/support/useful.h
index 9d8314e4be..c261fbaa14 100644
--- a/include/grpc/support/useful.h
+++ b/include/grpc/support/useful.h
@@ -34,12 +34,12 @@
#ifndef GRPC_SUPPORT_USEFUL_H
#define GRPC_SUPPORT_USEFUL_H
-/* useful macros that don't belong anywhere else */
+/** useful macros that don't belong anywhere else */
#define GPR_MIN(a, b) ((a) < (b) ? (a) : (b))
#define GPR_MAX(a, b) ((a) > (b) ? (a) : (b))
#define GPR_CLAMP(a, min, max) ((a) < (min) ? (min) : (a) > (max) ? (max) : (a))
-/* rotl, rotr assume x is unsigned */
+/** rotl, rotr assume x is unsigned */
#define GPR_ROTL(x, n) (((x) << (n)) | ((x) >> (sizeof(x) * 8 - (n))))
#define GPR_ROTR(x, n) (((x) >> (n)) | ((x) << (sizeof(x) * 8 - (n))))
diff --git a/include/grpc/support/workaround_list.h b/include/grpc/support/workaround_list.h
index 6a8aa1f955..ec4766510f 100644
--- a/include/grpc/support/workaround_list.h
+++ b/include/grpc/support/workaround_list.h
@@ -36,7 +36,7 @@
/* The list of IDs of server workarounds currently maintained by gRPC. For
* explanation and detailed descriptions of workarounds, see
- * /docs/workarounds.md
+ * /doc/workarounds.md
*/
typedef enum {
GRPC_WORKAROUND_ID_CRONET_COMPRESSION = 0,
diff --git a/package.json b/package.json
index e1499a089c..1ed182ced9 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
"lodash": "^4.15.0",
"nan": "^2.0.0",
"node-pre-gyp": "^0.6.0",
- "protobufjs": "^6.7.0"
+ "protobufjs": "^5.0.0"
},
"devDependencies": {
"async": "^2.0.1",
diff --git a/package.xml b/package.xml
index 63b44600ba..e560139dcd 100644
--- a/package.xml
+++ b/package.xml
@@ -10,7 +10,7 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
- <date>2017-03-01</date>
+ <date>2017-05-05</date>
<time>16:06:07</time>
<version>
<release>1.4.0dev</release>
@@ -22,8 +22,7 @@
</stability>
<license>BSD</license>
<notes>
-- Added arg info macros #9751
-- Updated codegen to be consistent with protobuf #9492
+- Fixed some memory leaks #9559, #10996
</notes>
<contents>
<dir baseinstalldir="/" name="/">
@@ -52,6 +51,7 @@
<file baseinstalldir="/" name="src/php/ext/grpc/server.h" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/server_credentials.h" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/timeval.h" role="src" />
+ <file baseinstalldir="/" name="src/php/ext/grpc/version.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/alloc.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/atm.h" role="src" />
<file baseinstalldir="/" name="include/grpc/support/atm_gcc_atomic.h" role="src" />
@@ -428,6 +428,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollsig_linux.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.c" role="src" />
+ <file baseinstalldir="/" name="src/core/lib/iomgr/ev_windows.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/executor.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/iocp_windows.c" role="src" />
@@ -1056,79 +1057,7 @@
<file baseinstalldir="/" name="third_party/boringssl/ssl/tls13_server.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/tls_method.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/ssl/tls_record.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_data.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_dns.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_getenv.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_getopt.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_inet_net_pton.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_iphlpapi.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_ipv6.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_library_init.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_llist.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_nowarn.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_platform.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_private.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_rules.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_setup.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_strcasecmp.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_strdup.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_version.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/bitncmp.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/config-win32.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/setup_once.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/ares_build.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/config_linux/ares_config.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/config_darwin/ares_config.h" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares__close_sockets.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares__get_hostent.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares__read_line.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares__timeval.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_cancel.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_create_query.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_data.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_destroy.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_expand_name.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_expand_string.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_fds.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_free_hostent.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_free_string.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_getenv.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_gethostbyaddr.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_gethostbyname.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_getnameinfo.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_getopt.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_getsock.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_init.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_library_init.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_llist.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_mkquery.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_nowarn.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_options.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_a_reply.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_aaaa_reply.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_mx_reply.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_naptr_reply.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_ns_reply.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_ptr_reply.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_soa_reply.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_srv_reply.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_parse_txt_reply.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_platform.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_process.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_query.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_search.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_send.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_strcasecmp.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_strdup.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_strerror.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_timeout.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_version.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/ares_writev.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/bitncmp.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/inet_net_pton.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/inet_ntop.c" role="src" />
- <file baseinstalldir="/" name="third_party/cares/cares/windows_port.c" role="src" />
+ <file name="LICENSE" role="doc" />
</dir>
</contents>
<dependencies>
@@ -1444,5 +1373,21 @@ Update to wrap gRPC C Core version 0.10.0
- Updated codegen to be consistent with protobuf #9492
</notes>
</release>
+ <release>
+ <version>
+ <release>1.2.0</release>
+ <api>1.2.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <date>2017-03-20</date>
+ <license>BSD</license>
+ <notes>
+- Added arg info macros #9751
+- Updated codegen to be consistent with protobuf #9492
+ </notes>
+ </release>
</changelog>
</package>
diff --git a/src/core/ext/filters/client_channel/client_channel.c b/src/core/ext/filters/client_channel/client_channel.c
index 24843d52e9..f2f27b9175 100644
--- a/src/core/ext/filters/client_channel/client_channel.c
+++ b/src/core/ext/filters/client_channel/client_channel.c
@@ -914,10 +914,13 @@ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
chand->interested_parties);
if (calld->connected_subchannel == NULL) {
- gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
+ gpr_atm_no_barrier_store(&calld->subchannel_call, (gpr_atm)CANCELLED_CALL);
fail_locked(exec_ctx, calld,
- GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
- "Failed to create subchannel", &error, 1));
+ error == GRPC_ERROR_NONE
+ ? GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "Call dropped by load balancing policy")
+ : GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
+ "Failed to create subchannel", &error, 1));
} else if (GET_CALL(calld) == CANCELLED_CALL) {
/* already cancelled before subchannel became ready */
grpc_error *cancellation_error =
@@ -1180,6 +1183,15 @@ static void start_transport_stream_op_batch_locked_inner(
&calld->next_step)) {
calld->pick_pending = false;
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
+ if (calld->connected_subchannel == NULL) {
+ gpr_atm_no_barrier_store(&calld->subchannel_call,
+ (gpr_atm)CANCELLED_CALL);
+ grpc_error *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "Call dropped by load balancing policy");
+ fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
+ grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error);
+ return; // Early out.
+ }
} else {
grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
chand->interested_parties);
diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h
index 184b2ef720..fb4aa084a6 100644
--- a/src/core/ext/filters/client_channel/lb_policy.h
+++ b/src/core/ext/filters/client_channel/lb_policy.h
@@ -149,7 +149,9 @@ void grpc_lb_policy_init(grpc_lb_policy *policy,
/** Finds an appropriate subchannel for a call, based on \a pick_args.
- \a target will be set to the selected subchannel, or NULL on failure.
+ \a target will be set to the selected subchannel, or NULL on failure
+ or when the LB policy decides to drop the call.
+
Upon success, \a user_data will be set to whatever opaque information
may need to be propagated from the LB policy, or NULL if not needed.
\a context will be populated with context to pass to the subchannel
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c
index b7c0e929b7..d2a2856a18 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c
@@ -327,6 +327,11 @@ typedef struct glb_lb_policy {
* response has arrived. */
grpc_grpclb_serverlist *serverlist;
+ /** Index into serverlist for next pick.
+ * If the server at this index is a drop, we return a drop.
+ * Otherwise, we delegate to the RR policy. */
+ size_t serverlist_index;
+
/** list of picks that are waiting on RR's policy connectivity */
pending_pick *pending_picks;
@@ -402,6 +407,9 @@ struct rr_connectivity_data {
static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
bool log) {
+ if (server->drop_for_rate_limiting || server->drop_for_load_balancing) {
+ return false;
+ }
const grpc_grpclb_ip_address *ip = &server->ip_address;
if (server->port >> 16 != 0) {
if (log) {
@@ -411,7 +419,6 @@ static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
}
return false;
}
-
if (ip->size != 4 && ip->size != 16) {
if (log) {
gpr_log(GPR_ERROR,
@@ -445,11 +452,12 @@ static const grpc_lb_user_data_vtable lb_token_vtable = {
static void parse_server(const grpc_grpclb_server *server,
grpc_resolved_address *addr) {
+ memset(addr, 0, sizeof(*addr));
+ if (server->drop_for_rate_limiting || server->drop_for_load_balancing) return;
const uint16_t netorder_port = htons((uint16_t)server->port);
/* the addresses are given in binary format (a in(6)_addr struct) in
* server->ip_address.bytes. */
const grpc_grpclb_ip_address *ip = &server->ip_address;
- memset(addr, 0, sizeof(*addr));
if (ip->size == 4) {
addr->len = sizeof(struct sockaddr_in);
struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr->addr;
@@ -586,16 +594,51 @@ static bool update_lb_connectivity_status_locked(
return true;
}
-/* perform a pick over \a rr_policy. Given that a pick can return immediately
- * (ignoring its completion callback) we need to perform the cleanups this
- * callback would be otherwise resposible for */
+/* Perform a pick over \a glb_policy->rr_policy. Given that a pick can return
+ * immediately (ignoring its completion callback), we need to perform the
+ * cleanups this callback would otherwise be resposible for.
+ * If \a force_async is true, then we will manually schedule the
+ * completion callback even if the pick is available immediately. */
static bool pick_from_internal_rr_locked(
- grpc_exec_ctx *exec_ctx, grpc_lb_policy *rr_policy,
- const grpc_lb_policy_pick_args *pick_args,
+ grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
+ const grpc_lb_policy_pick_args *pick_args, bool force_async,
grpc_connected_subchannel **target, wrapped_rr_closure_arg *wc_arg) {
- GPR_ASSERT(rr_policy != NULL);
+ // Look at the index into the serverlist to see if we should drop this call.
+ grpc_grpclb_server *server =
+ glb_policy->serverlist->servers[glb_policy->serverlist_index++];
+ if (glb_policy->serverlist_index == glb_policy->serverlist->num_servers) {
+ glb_policy->serverlist_index = 0; // Wrap-around.
+ }
+ if (server->drop_for_rate_limiting || server->drop_for_load_balancing) {
+ // Not using the RR policy, so unref it.
+ if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
+ gpr_log(GPR_INFO, "Unreffing RR for drop (0x%" PRIxPTR ")",
+ (intptr_t)wc_arg->rr_policy);
+ }
+ GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
+ // Update client load reporting stats to indicate the number of
+ // dropped calls. Note that we have to do this here instead of in
+ // the client_load_reporting filter, because we do not create a
+ // subchannel call (and therefore no client_load_reporting filter)
+ // for dropped calls.
+ grpc_grpclb_client_stats_add_call_started(wc_arg->client_stats);
+ grpc_grpclb_client_stats_add_call_finished(
+ server->drop_for_rate_limiting, server->drop_for_load_balancing,
+ false /* failed_to_send */, false /* known_received */,
+ wc_arg->client_stats);
+ grpc_grpclb_client_stats_unref(wc_arg->client_stats);
+ if (force_async) {
+ GPR_ASSERT(wc_arg->wrapped_closure != NULL);
+ grpc_closure_sched(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_NONE);
+ gpr_free(wc_arg->free_when_done);
+ return false;
+ }
+ gpr_free(wc_arg->free_when_done);
+ return true;
+ }
+ // Pick via the RR policy.
const bool pick_done = grpc_lb_policy_pick_locked(
- exec_ctx, rr_policy, pick_args, target, wc_arg->context,
+ exec_ctx, wc_arg->rr_policy, pick_args, target, wc_arg->context,
(void **)&wc_arg->lb_token, &wc_arg->wrapper_closure);
if (pick_done) {
/* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
@@ -604,17 +647,20 @@ static bool pick_from_internal_rr_locked(
(intptr_t)wc_arg->rr_policy);
}
GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
-
/* add the load reporting initial metadata */
initial_metadata_add_lb_token(exec_ctx, pick_args->initial_metadata,
pick_args->lb_token_mdelem_storage,
GRPC_MDELEM_REF(wc_arg->lb_token));
-
// Pass on client stats via context. Passes ownership of the reference.
GPR_ASSERT(wc_arg->client_stats != NULL);
wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].value = wc_arg->client_stats;
wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].destroy = destroy_client_stats;
-
+ if (force_async) {
+ GPR_ASSERT(wc_arg->wrapped_closure != NULL);
+ grpc_closure_sched(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_NONE);
+ gpr_free(wc_arg->free_when_done);
+ return false;
+ }
gpr_free(wc_arg->free_when_done);
}
/* else, the pending pick will be registered and taken care of by the
@@ -744,8 +790,8 @@ static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "",
(intptr_t)glb_policy->rr_policy);
}
- pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy,
- &pp->pick_args, pp->target,
+ pick_from_internal_rr_locked(exec_ctx, glb_policy, &pp->pick_args,
+ true /* force_async */, pp->target,
&pp->wrapped_on_complete_arg);
}
@@ -1115,8 +1161,9 @@ static int glb_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
wc_arg->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage;
wc_arg->initial_metadata = pick_args->initial_metadata;
wc_arg->free_when_done = wc_arg;
- pick_done = pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy,
- pick_args, target, wc_arg);
+ pick_done =
+ pick_from_internal_rr_locked(exec_ctx, glb_policy, pick_args,
+ false /* force_async */, target, wc_arg);
} else {
if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
gpr_log(GPR_DEBUG,
@@ -1517,7 +1564,7 @@ static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg,
* serverlist instance will be destroyed either upon the next
* update or in glb_destroy() */
glb_policy->serverlist = serverlist;
-
+ glb_policy->serverlist_index = 0;
rr_handover_locked(exec_ctx, glb_policy);
}
} else {
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c
index 81b6932fae..90e7c2efe5 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c
@@ -37,44 +37,39 @@
#include <grpc/support/alloc.h>
+/* invoked once for every Server in ServerList */
+static bool count_serverlist(pb_istream_t *stream, const pb_field_t *field,
+ void **arg) {
+ grpc_grpclb_serverlist *sl = *arg;
+ grpc_grpclb_server server;
+ if (!pb_decode(stream, grpc_lb_v1_Server_fields, &server)) {
+ gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream));
+ return false;
+ }
+ ++sl->num_servers;
+ return true;
+}
+
typedef struct decode_serverlist_arg {
- /* The first pass counts the number of servers in the server list. The second
- * one allocates and decodes. */
- bool first_pass;
/* The decoding callback is invoked once per server in serverlist. Remember
* which index of the serverlist are we currently decoding */
size_t decoding_idx;
- /* Populated after the first pass. Number of server in the input serverlist */
- size_t num_servers;
/* The decoded serverlist */
- grpc_grpclb_server **servers;
+ grpc_grpclb_serverlist *serverlist;
} decode_serverlist_arg;
/* invoked once for every Server in ServerList */
static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field,
void **arg) {
decode_serverlist_arg *dec_arg = *arg;
- if (dec_arg->first_pass) { /* count how many server do we have */
- grpc_grpclb_server server;
- if (!pb_decode(stream, grpc_lb_v1_Server_fields, &server)) {
- gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream));
- return false;
- }
- dec_arg->num_servers++;
- } else { /* second pass. Actually decode. */
- grpc_grpclb_server *server = gpr_zalloc(sizeof(grpc_grpclb_server));
- GPR_ASSERT(dec_arg->num_servers > 0);
- if (dec_arg->decoding_idx == 0) { /* first iteration of second pass */
- dec_arg->servers =
- gpr_malloc(sizeof(grpc_grpclb_server *) * dec_arg->num_servers);
- }
- if (!pb_decode(stream, grpc_lb_v1_Server_fields, server)) {
- gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream));
- return false;
- }
- dec_arg->servers[dec_arg->decoding_idx++] = server;
+ GPR_ASSERT(dec_arg->serverlist->num_servers >= dec_arg->decoding_idx);
+ grpc_grpclb_server *server = gpr_zalloc(sizeof(grpc_grpclb_server));
+ if (!pb_decode(stream, grpc_lb_v1_Server_fields, server)) {
+ gpr_free(server);
+ gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(stream));
+ return false;
}
-
+ dec_arg->serverlist->servers[dec_arg->decoding_idx++] = server;
return true;
}
@@ -165,36 +160,38 @@ grpc_grpclb_initial_response *grpc_grpclb_initial_response_parse(
grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
grpc_slice encoded_grpc_grpclb_response) {
- bool status;
- decode_serverlist_arg arg;
pb_istream_t stream =
pb_istream_from_buffer(GRPC_SLICE_START_PTR(encoded_grpc_grpclb_response),
GRPC_SLICE_LENGTH(encoded_grpc_grpclb_response));
pb_istream_t stream_at_start = stream;
+ grpc_grpclb_serverlist *sl = gpr_zalloc(sizeof(grpc_grpclb_serverlist));
grpc_grpclb_response res;
memset(&res, 0, sizeof(grpc_grpclb_response));
- memset(&arg, 0, sizeof(decode_serverlist_arg));
-
- res.server_list.servers.funcs.decode = decode_serverlist;
- res.server_list.servers.arg = &arg;
- arg.first_pass = true;
- status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res);
+ // First pass: count number of servers.
+ res.server_list.servers.funcs.decode = count_serverlist;
+ res.server_list.servers.arg = sl;
+ bool status = pb_decode(&stream, grpc_lb_v1_LoadBalanceResponse_fields, &res);
if (!status) {
+ gpr_free(sl);
gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
return NULL;
}
-
- arg.first_pass = false;
- status =
- pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields, &res);
- if (!status) {
- gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
- return NULL;
+ // Second pass: populate servers.
+ if (sl->num_servers > 0) {
+ sl->servers = gpr_zalloc(sizeof(grpc_grpclb_server *) * sl->num_servers);
+ decode_serverlist_arg decode_arg;
+ memset(&decode_arg, 0, sizeof(decode_arg));
+ decode_arg.serverlist = sl;
+ res.server_list.servers.funcs.decode = decode_serverlist;
+ res.server_list.servers.arg = &decode_arg;
+ status = pb_decode(&stream_at_start, grpc_lb_v1_LoadBalanceResponse_fields,
+ &res);
+ if (!status) {
+ grpc_grpclb_destroy_serverlist(sl);
+ gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
+ return NULL;
+ }
}
-
- grpc_grpclb_serverlist *sl = gpr_zalloc(sizeof(grpc_grpclb_serverlist));
- sl->num_servers = arg.num_servers;
- sl->servers = arg.servers;
if (res.server_list.has_expiration_interval) {
sl->expiration_interval = res.server_list.expiration_interval;
}
@@ -228,7 +225,7 @@ grpc_grpclb_serverlist *grpc_grpclb_serverlist_copy(
bool grpc_grpclb_serverlist_equals(const grpc_grpclb_serverlist *lhs,
const grpc_grpclb_serverlist *rhs) {
- if ((lhs == NULL) || (rhs == NULL)) {
+ if (lhs == NULL || rhs == NULL) {
return false;
}
if (lhs->num_servers != rhs->num_servers) {
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
index 06873821bd..7f596ce1f1 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
@@ -51,7 +51,7 @@ typedef grpc_lb_v1_LoadBalanceRequest grpc_grpclb_request;
typedef grpc_lb_v1_InitialLoadBalanceResponse grpc_grpclb_initial_response;
typedef grpc_lb_v1_Server grpc_grpclb_server;
typedef grpc_lb_v1_Duration grpc_grpclb_duration;
-typedef struct grpc_grpclb_serverlist {
+typedef struct {
grpc_grpclb_server **servers;
size_t num_servers;
grpc_grpclb_duration expiration_interval;
diff --git a/src/core/ext/filters/client_channel/parse_address.c b/src/core/ext/filters/client_channel/parse_address.c
index edc6ce697d..18381eec55 100644
--- a/src/core/ext/filters/client_channel/parse_address.c
+++ b/src/core/ext/filters/client_channel/parse_address.c
@@ -57,11 +57,11 @@ bool grpc_parse_unix(const grpc_uri *uri,
struct sockaddr_un *un = (struct sockaddr_un *)resolved_addr->addr;
const size_t maxlen = sizeof(un->sun_path);
const size_t path_len = strnlen(uri->path, maxlen);
- if (path_len == maxlen) return 0;
+ if (path_len == maxlen) return false;
un->sun_family = AF_UNIX;
strcpy(un->sun_path, uri->path);
resolved_addr->len = sizeof(*un);
- return 1;
+ return true;
}
#else /* GRPC_HAVE_UNIX_SOCKET */
@@ -73,74 +73,65 @@ bool grpc_parse_unix(const grpc_uri *uri,
#endif /* GRPC_HAVE_UNIX_SOCKET */
-bool grpc_parse_ipv4(const grpc_uri *uri,
- grpc_resolved_address *resolved_addr) {
- if (strcmp("ipv4", uri->scheme) != 0) {
- gpr_log(GPR_ERROR, "Expected 'ipv4' scheme, got '%s'", uri->scheme);
- return false;
- }
- const char *host_port = uri->path;
+bool grpc_parse_ipv4_hostport(const char *hostport, grpc_resolved_address *addr,
+ bool log_errors) {
+ bool success = false;
+ // Split host and port.
char *host;
char *port;
- int port_num;
- bool result = false;
- struct sockaddr_in *in = (struct sockaddr_in *)resolved_addr->addr;
-
- if (*host_port == '/') ++host_port;
- if (!gpr_split_host_port(host_port, &host, &port)) {
- return false;
- }
-
- memset(resolved_addr, 0, sizeof(grpc_resolved_address));
- resolved_addr->len = sizeof(struct sockaddr_in);
+ if (!gpr_split_host_port(hostport, &host, &port)) return false;
+ // Parse IP address.
+ memset(addr, 0, sizeof(*addr));
+ addr->len = sizeof(struct sockaddr_in);
+ struct sockaddr_in *in = (struct sockaddr_in *)addr->addr;
in->sin_family = AF_INET;
if (inet_pton(AF_INET, host, &in->sin_addr) == 0) {
- gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host);
+ if (log_errors) gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host);
goto done;
}
-
- if (port != NULL) {
- if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
- port_num > 65535) {
- gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port);
- goto done;
- }
- in->sin_port = htons((uint16_t)port_num);
- } else {
- gpr_log(GPR_ERROR, "no port given for ipv4 scheme");
+ // Parse port.
+ if (port == NULL) {
+ if (log_errors) gpr_log(GPR_ERROR, "no port given for ipv4 scheme");
goto done;
}
-
- result = true;
+ int port_num;
+ if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 || port_num > 65535) {
+ if (log_errors) gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port);
+ goto done;
+ }
+ in->sin_port = htons((uint16_t)port_num);
+ success = true;
done:
gpr_free(host);
gpr_free(port);
- return result;
+ return success;
}
-bool grpc_parse_ipv6(const grpc_uri *uri,
+bool grpc_parse_ipv4(const grpc_uri *uri,
grpc_resolved_address *resolved_addr) {
- if (strcmp("ipv6", uri->scheme) != 0) {
- gpr_log(GPR_ERROR, "Expected 'ipv6' scheme, got '%s'", uri->scheme);
+ if (strcmp("ipv4", uri->scheme) != 0) {
+ gpr_log(GPR_ERROR, "Expected 'ipv4' scheme, got '%s'", uri->scheme);
return false;
}
const char *host_port = uri->path;
- char *host;
- char *port;
- int port_num;
- int result = 0;
- struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)resolved_addr->addr;
-
if (*host_port == '/') ++host_port;
- if (!gpr_split_host_port(host_port, &host, &port)) {
- return 0;
- }
+ return grpc_parse_ipv4_hostport(host_port, resolved_addr,
+ true /* log_errors */);
+}
- memset(in6, 0, sizeof(*in6));
- resolved_addr->len = sizeof(*in6);
+bool grpc_parse_ipv6_hostport(const char *hostport, grpc_resolved_address *addr,
+ bool log_errors) {
+ bool success = false;
+ // Split host and port.
+ char *host;
+ char *port;
+ if (!gpr_split_host_port(hostport, &host, &port)) return false;
+ // Parse IP address.
+ memset(addr, 0, sizeof(*addr));
+ addr->len = sizeof(struct sockaddr_in6);
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr->addr;
in6->sin6_family = AF_INET6;
-
- /* Handle the RFC6874 syntax for IPv6 zone identifiers. */
+ // Handle the RFC6874 syntax for IPv6 zone identifiers.
char *host_end = (char *)gpr_memrchr(host, '%', strlen(host));
if (host_end != NULL) {
GPR_ASSERT(host_end >= host);
@@ -159,7 +150,7 @@ bool grpc_parse_ipv6(const grpc_uri *uri,
gpr_log(GPR_ERROR, "invalid ipv6 scope id: '%s'", host_end + 1);
goto done;
}
- // Handle "sin6_scope_id" being type "u_long". See grpc issue ##10027.
+ // Handle "sin6_scope_id" being type "u_long". See grpc issue #10027.
in6->sin6_scope_id = sin6_scope_id;
} else {
if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
@@ -167,24 +158,34 @@ bool grpc_parse_ipv6(const grpc_uri *uri,
goto done;
}
}
-
- if (port != NULL) {
- if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
- port_num > 65535) {
- gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port);
- goto done;
- }
- in6->sin6_port = htons((uint16_t)port_num);
- } else {
- gpr_log(GPR_ERROR, "no port given for ipv6 scheme");
+ // Parse port.
+ if (port == NULL) {
+ if (log_errors) gpr_log(GPR_ERROR, "no port given for ipv6 scheme");
goto done;
}
-
- result = 1;
+ int port_num;
+ if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 || port_num > 65535) {
+ if (log_errors) gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port);
+ goto done;
+ }
+ in6->sin6_port = htons((uint16_t)port_num);
+ success = true;
done:
gpr_free(host);
gpr_free(port);
- return result;
+ return success;
+}
+
+bool grpc_parse_ipv6(const grpc_uri *uri,
+ grpc_resolved_address *resolved_addr) {
+ if (strcmp("ipv6", uri->scheme) != 0) {
+ gpr_log(GPR_ERROR, "Expected 'ipv6' scheme, got '%s'", uri->scheme);
+ return false;
+ }
+ const char *host_port = uri->path;
+ if (*host_port == '/') ++host_port;
+ return grpc_parse_ipv6_hostport(host_port, resolved_addr,
+ true /* log_errors */);
}
bool grpc_parse_uri(const grpc_uri *uri, grpc_resolved_address *resolved_addr) {
diff --git a/src/core/ext/filters/client_channel/parse_address.h b/src/core/ext/filters/client_channel/parse_address.h
index fa7ea33a00..1a203a3b26 100644
--- a/src/core/ext/filters/client_channel/parse_address.h
+++ b/src/core/ext/filters/client_channel/parse_address.h
@@ -54,4 +54,10 @@ bool grpc_parse_ipv6(const grpc_uri *uri, grpc_resolved_address *resolved_addr);
/** Populate \a resolved_addr from \a uri. Returns true upon success. */
bool grpc_parse_uri(const grpc_uri *uri, grpc_resolved_address *resolved_addr);
+/** Parse bare IPv4 or IPv6 "IP:port" strings. */
+bool grpc_parse_ipv4_hostport(const char *hostport, grpc_resolved_address *addr,
+ bool log_errors);
+bool grpc_parse_ipv6_hostport(const char *hostport, grpc_resolved_address *addr,
+ bool log_errors);
+
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H */
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c
index ca7c7315b5..85986e5617 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c
@@ -61,6 +61,8 @@
typedef struct {
/** base class: must be first */
grpc_resolver base;
+ /** DNS server to use (if not system default) */
+ char *dns_server;
/** name to resolve (usually the same as target_name) */
char *name_to_resolve;
/** default port to use */
@@ -163,6 +165,8 @@ static void dns_ares_on_resolved_locked(grpc_exec_ctx *exec_ctx, void *arg,
result = grpc_channel_args_copy_and_add(r->channel_args, &new_arg, 1);
grpc_lb_addresses_destroy(exec_ctx, r->lb_addresses);
} else {
+ const char *msg = grpc_error_string(error);
+ gpr_log(GPR_DEBUG, "dns resolution failed: %s", msg);
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
gpr_timespec timeout = gpr_time_sub(next_try, now);
@@ -212,9 +216,10 @@ static void dns_ares_start_resolving_locked(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(!r->resolving);
r->resolving = true;
r->lb_addresses = NULL;
- grpc_resolve_grpclb_address_ares(
- exec_ctx, r->name_to_resolve, r->default_port, r->interested_parties,
- &r->dns_ares_on_resolved_locked, &r->lb_addresses);
+ grpc_dns_lookup_ares(exec_ctx, r->dns_server, r->name_to_resolve,
+ r->default_port, r->interested_parties,
+ &r->dns_ares_on_resolved_locked,
+ (void **)&r->lb_addresses, true /* is_lb_addrs_out */);
}
static void dns_ares_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
@@ -238,6 +243,7 @@ static void dns_ares_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
grpc_channel_args_destroy(exec_ctx, r->resolved_result);
}
grpc_pollset_set_destroy(exec_ctx, r->interested_parties);
+ gpr_free(r->dns_server);
gpr_free(r->name_to_resolve);
gpr_free(r->default_port);
grpc_channel_args_destroy(exec_ctx, r->channel_args);
@@ -249,14 +255,13 @@ static grpc_resolver *dns_ares_create(grpc_exec_ctx *exec_ctx,
const char *default_port) {
/* Get name from args. */
const char *path = args->uri->path;
- if (0 != strcmp(args->uri->authority, "")) {
- gpr_log(GPR_ERROR, "authority based dns uri's not supported");
- return NULL;
- }
if (path[0] == '/') ++path;
/* Create resolver. */
ares_dns_resolver *r = gpr_zalloc(sizeof(ares_dns_resolver));
grpc_resolver_init(&r->base, &dns_ares_resolver_vtable, args->combiner);
+ if (0 != strcmp(args->uri->authority, "")) {
+ r->dns_server = gpr_strdup(args->uri->authority);
+ }
r->name_to_resolve = gpr_strdup(path);
r->default_port = gpr_strdup(default_port);
r->channel_args = grpc_channel_args_copy(args->args);
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
index 55059018c8..ead078caa0 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
@@ -49,7 +49,10 @@
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include <nameser.h>
+
+#include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
+#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/iomgr/iomgr_internal.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
@@ -59,6 +62,8 @@ static gpr_once g_basic_init = GPR_ONCE_INIT;
static gpr_mu g_init_mu;
typedef struct grpc_ares_request {
+ /** indicates the DNS server to use, if specified */
+ struct ares_addr_port_node dns_server_addr;
/** following members are set in grpc_resolve_address_ares_impl */
/** closure to call when the request completes */
grpc_closure *on_done;
@@ -332,11 +337,12 @@ static void on_srv_query_done_cb(void *arg, int status, int timeouts,
grpc_exec_ctx_finish(&exec_ctx);
}
-static void resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
- const char *default_port,
- grpc_pollset_set *interested_parties,
- grpc_closure *on_done, void **addrs,
- bool is_lb_addrs_out) {
+void grpc_dns_lookup_ares(
+ grpc_exec_ctx *exec_ctx, const char *dns_server, const char *name,
+ const char *default_port, grpc_pollset_set *interested_parties,
+ grpc_closure *on_done,
+ void **addrs, bool is_lb_addrs_out) {
+ grpc_error *error = GRPC_ERROR_NONE;
/* TODO(zyc): Enable tracing after #9603 is checked in */
/* if (grpc_dns_trace) {
gpr_log(GPR_DEBUG, "resolve_address (blocking): name=%s, default_port=%s",
@@ -348,28 +354,23 @@ static void resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
char *port;
gpr_split_host_port(name, &host, &port);
if (host == NULL) {
- grpc_error *err = grpc_error_set_str(
+ error = grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
- grpc_closure_sched(exec_ctx, on_done, err);
goto error_cleanup;
} else if (port == NULL) {
if (default_port == NULL) {
- grpc_error *err = grpc_error_set_str(
+ error = grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"),
GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
- grpc_closure_sched(exec_ctx, on_done, err);
goto error_cleanup;
}
port = gpr_strdup(default_port);
}
grpc_ares_ev_driver *ev_driver;
- grpc_error *err = grpc_ares_ev_driver_create(&ev_driver, interested_parties);
- if (err != GRPC_ERROR_NONE) {
- GRPC_LOG_IF_ERROR("grpc_ares_ev_driver_create() failed", err);
- goto error_cleanup;
- }
+ error = grpc_ares_ev_driver_create(&ev_driver, interested_parties);
+ if (error != GRPC_ERROR_NONE) goto error_cleanup;
grpc_ares_request *r = gpr_malloc(sizeof(grpc_ares_request));
gpr_mu_init(&r->mu);
@@ -384,6 +385,40 @@ static void resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
r->success = false;
r->error = GRPC_ERROR_NONE;
ares_channel *channel = grpc_ares_ev_driver_get_channel(r->ev_driver);
+
+ // If dns_server is specified, use it.
+ if (dns_server != NULL) {
+ gpr_log(GPR_INFO, "Using DNS server %s", dns_server);
+ grpc_resolved_address addr;
+ if (grpc_parse_ipv4_hostport(dns_server, &addr, false /* log_errors */)) {
+ r->dns_server_addr.family = AF_INET;
+ memcpy(&r->dns_server_addr.addr.addr4, addr.addr, addr.len);
+ r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
+ r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
+ } else if (grpc_parse_ipv6_hostport(dns_server, &addr,
+ false /* log_errors */)) {
+ r->dns_server_addr.family = AF_INET6;
+ memcpy(&r->dns_server_addr.addr.addr6, addr.addr, addr.len);
+ r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
+ r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
+ } else {
+ error = grpc_error_set_str(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("cannot parse authority"),
+ GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
+ goto error_cleanup;
+ }
+ int status = ares_set_servers_ports(*channel, &r->dns_server_addr);
+ if (status != ARES_SUCCESS) {
+ char *error_msg;
+ gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
+ ares_strerror(status));
+ error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
+ gpr_free(error_msg);
+ goto error_cleanup;
+ }
+ }
+ // An extra reference is put here to avoid destroying the request in
+ // on_done_cb before calling grpc_ares_ev_driver_start.
gpr_ref_init(&r->pending_queries, 1);
if (grpc_ipv6_loopback_available()) {
grpc_ares_hostbyname_request *hr = create_hostbyname_request(
@@ -408,6 +443,7 @@ static void resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
return;
error_cleanup:
+ grpc_closure_sched(exec_ctx, on_done, error);
gpr_free(host);
gpr_free(port);
}
@@ -417,19 +453,9 @@ void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
grpc_pollset_set *interested_parties,
grpc_closure *on_done,
grpc_resolved_addresses **addrs) {
- resolve_address_ares_impl(exec_ctx, name, default_port, interested_parties,
- on_done, (void **)addrs,
- false /* is_lb_addrs_out */);
-}
-
-void grpc_resolve_grpclb_address_ares(grpc_exec_ctx *exec_ctx, const char *name,
- const char *default_port,
- grpc_pollset_set *interested_parties,
- grpc_closure *on_done,
- grpc_lb_addresses **addrs) {
- resolve_address_ares_impl(exec_ctx, name, default_port, interested_parties,
- on_done, (void **)addrs,
- true /* is_lb_addrs_out */);
+ grpc_dns_lookup_ares(exec_ctx, NULL /* dns_server */, name, default_port,
+ interested_parties, on_done, (void **)addrs,
+ false /* is_lb_addrs_out */);
}
void (*grpc_resolve_address_ares)(
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
index 1450ef373d..47d7b146f6 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
@@ -59,11 +59,11 @@ extern void (*grpc_resolve_address_ares)(grpc_exec_ctx *exec_ctx,
function. \a on_done may be called directly in this function without being
scheduled with \a exec_ctx, it must not try to acquire locks that are being
held by the caller. */
-void grpc_resolve_grpclb_address_ares(grpc_exec_ctx *exec_ctx, const char *addr,
- const char *default_port,
- grpc_pollset_set *interested_parties,
- grpc_closure *on_done,
- grpc_lb_addresses **addresses);
+void grpc_dns_lookup_ares(grpc_exec_ctx *exec_ctx, const char *dns_server,
+ const char *addr, const char *default_port,
+ grpc_pollset_set *interested_parties,
+ grpc_closure *on_done, void **addresses,
+ bool is_lb_addrs_out);
/* Initialize gRPC ares wrapper. Must be called at least once before
grpc_resolve_address_ares(). */
diff --git a/src/core/ext/filters/client_channel/subchannel.c b/src/core/ext/filters/client_channel/subchannel.c
index 1af3393a62..dd14bf1d02 100644
--- a/src/core/ext/filters/client_channel/subchannel.c
+++ b/src/core/ext/filters/client_channel/subchannel.c
@@ -283,6 +283,7 @@ static void disconnect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
gpr_atm old_refs;
+ // add a weak ref and subtract a strong ref (atomically)
old_refs = ref_mutate(c, (gpr_atm)1 - (gpr_atm)(1 << INTERNAL_REF_BITS),
1 REF_MUTATE_PURPOSE("STRONG_UNREF"));
if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) {
@@ -656,7 +657,6 @@ static bool publish_transport_locked(grpc_exec_ctx *exec_ctx,
gpr_free(sw_subchannel);
grpc_channel_stack_destroy(exec_ctx, stk);
gpr_free(con);
- GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
return false;
}
diff --git a/src/core/ext/filters/client_channel/subchannel_index.c b/src/core/ext/filters/client_channel/subchannel_index.c
index f6ef4a845e..b25dbfcf51 100644
--- a/src/core/ext/filters/client_channel/subchannel_index.c
+++ b/src/core/ext/filters/client_channel/subchannel_index.c
@@ -183,8 +183,11 @@ grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx,
enter_ctx(exec_ctx);
grpc_subchannel *c = NULL;
+ bool need_to_unref_constructed;
while (c == NULL) {
+ need_to_unref_constructed = false;
+
// Compare and swap loop:
// - take a reference to the current index
gpr_mu_lock(&g_mu);
@@ -194,8 +197,11 @@ grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx,
// - Check to see if a subchannel already exists
c = gpr_avl_get(index, key);
if (c != NULL) {
+ c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "index_register");
+ }
+ if (c != NULL) {
// yes -> we're done
- GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, constructed, "index_register");
+ need_to_unref_constructed = true;
} else {
// no -> update the avl and compare/swap
gpr_avl updated =
@@ -219,6 +225,10 @@ grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx,
leave_ctx(exec_ctx);
+ if (need_to_unref_constructed) {
+ GRPC_SUBCHANNEL_UNREF(exec_ctx, constructed, "index_register");
+ }
+
return c;
}
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index fb8ceaecb0..f3268bcfca 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -2139,15 +2139,8 @@ static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
double bdp_dbl) {
- int32_t bdp;
- const int32_t kMinBDP = 128;
- if (bdp_dbl <= kMinBDP) {
- bdp = kMinBDP;
- } else if (bdp_dbl > INT32_MAX) {
- bdp = INT32_MAX;
- } else {
- bdp = (int32_t)(bdp_dbl);
- }
+ // initial window size bounded [1,2^31-1], but we set the min to 128.
+ int32_t bdp = GPR_CLAMP((int32_t)bdp_dbl, 128, INT32_MAX);
int64_t delta =
(int64_t)bdp -
(int64_t)t->settings[GRPC_LOCAL_SETTINGS]
@@ -2161,7 +2154,26 @@ static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
}
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
(uint32_t)bdp);
- push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE, (uint32_t)bdp);
+}
+
+static void update_frame(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
+ double bw_dbl, double bdp_dbl) {
+ int32_t bdp = GPR_CLAMP((int32_t)bdp_dbl, 128, INT32_MAX);
+ int32_t target = GPR_MAX((int32_t)bw_dbl / 1000, bdp);
+ // frame size is bounded [2^14,2^24-1]
+ int32_t frame_size = GPR_CLAMP(target, 16384, 16777215);
+ int64_t delta = (int64_t)frame_size -
+ (int64_t)t->settings[GRPC_LOCAL_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE];
+ if (delta == 0 || (delta > -frame_size / 10 && delta < frame_size / 10)) {
+ return;
+ }
+ if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
+ gpr_log(GPR_DEBUG, "%s: update max_frame size to %d", t->peer_string,
+ (int)frame_size);
+ }
+ push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
+ (uint32_t)frame_size);
}
static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
@@ -2280,6 +2292,7 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
}
int64_t estimate = -1;
+ double bdp_guess = -1;
if (grpc_bdp_estimator_get_estimate(&t->bdp_estimator, &estimate)) {
double target = 1 + log2((double)estimate);
double memory_pressure = grpc_resource_quota_get_memory_pressure(
@@ -2297,9 +2310,15 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
}
double log2_bdp_guess =
grpc_pid_controller_update(&t->pid_controller, bdp_error, dt);
- update_bdp(exec_ctx, t, pow(2, log2_bdp_guess));
+ bdp_guess = pow(2, log2_bdp_guess);
+ update_bdp(exec_ctx, t, bdp_guess);
t->last_pid_update = now;
}
+
+ double bw = -1;
+ if (grpc_bdp_estimator_get_bw(&t->bdp_estimator, &bw)) {
+ update_frame(exec_ctx, t, bw, bdp_guess);
+ }
}
GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
} else {
diff --git a/src/core/lib/iomgr/ev_epollsig_linux.c b/src/core/lib/iomgr/ev_epollsig_linux.c
index 52362a62f4..92c555b7ea 100644
--- a/src/core/lib/iomgr/ev_epollsig_linux.c
+++ b/src/core/lib/iomgr/ev_epollsig_linux.c
@@ -65,9 +65,9 @@
#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1)
-#define GRPC_POLLING_TRACE(fmt, ...) \
+#define GRPC_POLLING_TRACE(...) \
if (GRPC_TRACER_ON(grpc_polling_trace)) { \
- gpr_log(GPR_INFO, (fmt), __VA_ARGS__); \
+ gpr_log(GPR_INFO, __VA_ARGS__); \
}
/* Uncomment the following to enable extra checks on poll_object operations */
@@ -732,7 +732,7 @@ static void workqueue_maybe_wakeup(polling_island *pi) {
it right now. Note that since we do an anticipatory mpscq_pop every poll
loop, it's ok if we miss the wakeup here, as we'll get the work item when
the next poller enters anyway. */
- if (current_pollers > min_current_pollers_for_wakeup) {
+ if (current_pollers >= min_current_pollers_for_wakeup) {
GRPC_LOG_IF_ERROR("workqueue_wakeup_fd",
grpc_wakeup_fd_wakeup(&pi->workqueue_wakeup_fd));
}
@@ -1332,7 +1332,13 @@ static bool maybe_do_workqueue_work(grpc_exec_ctx *exec_ctx,
gpr_mpscq_node *n = gpr_mpscq_pop(&pi->workqueue_items);
gpr_mu_unlock(&pi->workqueue_read_mu);
if (n != NULL) {
- if (gpr_atm_full_fetch_add(&pi->workqueue_item_count, -1) > 1) {
+ gpr_atm remaining =
+ gpr_atm_full_fetch_add(&pi->workqueue_item_count, -1) - 1;
+ GRPC_POLLING_TRACE(
+ "maybe_do_workqueue_work: pi: %p: got closure %p, remaining = "
+ "%" PRIdPTR,
+ pi, n, remaining);
+ if (remaining > 0) {
workqueue_maybe_wakeup(pi);
}
grpc_closure *c = (grpc_closure *)n;
@@ -1347,8 +1353,13 @@ static bool maybe_do_workqueue_work(grpc_exec_ctx *exec_ctx,
/* n == NULL might mean there's work but it's not available to be popped
* yet - try to ensure another workqueue wakes up to check shortly if so
*/
+ GRPC_POLLING_TRACE(
+ "maybe_do_workqueue_work: pi: %p: more to do, but not yet", pi);
workqueue_maybe_wakeup(pi);
}
+ } else {
+ GRPC_POLLING_TRACE("maybe_do_workqueue_work: pi: %p: read already locked",
+ pi);
}
return false;
}
@@ -1411,7 +1422,10 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx,
/* If we get some workqueue work to do, it might end up completing an item on
the completion queue, so there's no need to poll... so we skip that and
redo the complete loop to verify */
+ GRPC_POLLING_TRACE("pollset_work: pollset: %p, worker %p, pi %p", pollset,
+ worker, pi);
if (!maybe_do_workqueue_work(exec_ctx, pi)) {
+ GRPC_POLLING_TRACE("pollset_work: begins");
gpr_atm_no_barrier_fetch_add(&pi->poller_count, 1);
g_current_thread_polling_island = pi;
@@ -1472,6 +1486,7 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx,
g_current_thread_polling_island = NULL;
gpr_atm_no_barrier_fetch_add(&pi->poller_count, -1);
+ GRPC_POLLING_TRACE("pollset_work: ends");
}
GPR_ASSERT(pi != NULL);
diff --git a/src/core/lib/iomgr/ev_windows.c b/src/core/lib/iomgr/ev_windows.c
new file mode 100644
index 0000000000..7bf7327823
--- /dev/null
+++ b/src/core/lib/iomgr/ev_windows.c
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/lib/iomgr/port.h"
+
+#ifdef GRPC_WINSOCK_SOCKET
+
+#include "src/core/lib/debug/trace.h"
+
+grpc_tracer_flag grpc_polling_trace =
+ GRPC_TRACER_INITIALIZER(false); /* Disabled by default */
+
+#endif // GRPC_WINSOCK_SOCKET
diff --git a/src/core/lib/iomgr/tcp_server_uv.c b/src/core/lib/iomgr/tcp_server_uv.c
index e9246948f5..d446e5312a 100644
--- a/src/core/lib/iomgr/tcp_server_uv.c
+++ b/src/core/lib/iomgr/tcp_server_uv.c
@@ -56,6 +56,8 @@ struct grpc_tcp_listener {
int port;
/* linked list */
struct grpc_tcp_listener *next;
+
+ bool closed;
};
struct grpc_tcp_server {
@@ -77,6 +79,8 @@ struct grpc_tcp_server {
/* shutdown callback */
grpc_closure *shutdown_complete;
+ bool shutdown;
+
grpc_resource_quota *resource_quota;
};
@@ -109,6 +113,7 @@ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx,
s->shutdown_starting.head = NULL;
s->shutdown_starting.tail = NULL;
s->shutdown_complete = shutdown_complete;
+ s->shutdown = false;
*server = s;
return GRPC_ERROR_NONE;
}
@@ -125,6 +130,7 @@ void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
}
static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
+ GPR_ASSERT(s->shutdown);
if (s->shutdown_complete != NULL) {
grpc_closure_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE);
}
@@ -144,21 +150,31 @@ static void handle_close_callback(uv_handle_t *handle) {
grpc_tcp_listener *sp = (grpc_tcp_listener *)handle->data;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
sp->server->open_ports--;
- if (sp->server->open_ports == 0) {
+ if (sp->server->open_ports == 0 && sp->server->shutdown) {
finish_shutdown(&exec_ctx, sp->server);
}
grpc_exec_ctx_finish(&exec_ctx);
}
+static void close_listener(grpc_tcp_listener *sp) {
+ if (!sp->closed) {
+ sp->closed = true;
+ uv_close((uv_handle_t *)sp->handle, handle_close_callback);
+ }
+}
+
static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
int immediately_done = 0;
grpc_tcp_listener *sp;
+ GPR_ASSERT(!s->shutdown);
+ s->shutdown = true;
+
if (s->open_ports == 0) {
immediately_done = 1;
}
for (sp = s->head; sp; sp = sp->next) {
- uv_close((uv_handle_t *)sp->handle, handle_close_callback);
+ close_listener(sp);
}
if (immediately_done) {
@@ -196,9 +212,14 @@ static void on_connect(uv_stream_t *server, int status) {
int err;
if (status < 0) {
- gpr_log(GPR_INFO, "Skipping on_accept due to error: %s",
- uv_strerror(status));
- return;
+ switch (status) {
+ case UV_EINTR:
+ case UV_EAGAIN:
+ return;
+ default:
+ close_listener(sp);
+ return;
+ }
}
client = gpr_malloc(sizeof(uv_tcp_t));
@@ -287,6 +308,7 @@ static grpc_error *add_socket_to_server(grpc_tcp_server *s, uv_tcp_t *handle,
sp->handle = handle;
sp->port = port;
sp->port_index = port_index;
+ sp->closed = false;
handle->data = sp;
s->open_ports++;
GPR_ASSERT(sp->handle);
diff --git a/src/core/lib/iomgr/tcp_uv.c b/src/core/lib/iomgr/tcp_uv.c
index e7157537f6..dc23e4f521 100644
--- a/src/core/lib/iomgr/tcp_uv.c
+++ b/src/core/lib/iomgr/tcp_uv.c
@@ -88,12 +88,12 @@ static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
#ifdef GRPC_TCP_REFCOUNT_DEBUG
#define TCP_UNREF(exec_ctx, tcp, reason) \
tcp_unref((exec_ctx), (tcp), (reason), __FILE__, __LINE__)
-#define TCP_REF(tcp, reason) \
- tcp_ref((exec_ctx), (tcp), (reason), __FILE__, __LINE__)
+#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__)
static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
const char *reason, const char *file, int line) {
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp,
- reason, tcp->refcount.count, tcp->refcount.count - 1);
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+ "TCP unref %p : %s %" PRIiPTR " -> %" PRIiPTR, tcp, reason,
+ tcp->refcount.count, tcp->refcount.count - 1);
if (gpr_unref(&tcp->refcount)) {
tcp_free(exec_ctx, tcp);
}
@@ -101,8 +101,9 @@ static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
int line) {
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp,
- reason, tcp->refcount.count, tcp->refcount.count + 1);
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
+ "TCP ref %p : %s %" PRIiPTR " -> %" PRIiPTR, tcp, reason,
+ tcp->refcount.count, tcp->refcount.count + 1);
gpr_ref(&tcp->refcount);
}
#else
@@ -311,6 +312,7 @@ static void uv_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
tcp->shutting_down = true;
uv_shutdown_t *req = &tcp->shutdown_req;
uv_shutdown(req, (uv_stream_t *)tcp->handle, shutdown_callback);
+ grpc_resource_user_shutdown(exec_ctx, tcp->resource_user);
}
GRPC_ERROR_UNREF(why);
}
diff --git a/src/core/lib/support/cmdline.c b/src/core/lib/support/cmdline.c
index 88a65a8e2e..e5c9f3b84b 100644
--- a/src/core/lib/support/cmdline.c
+++ b/src/core/lib/support/cmdline.c
@@ -71,7 +71,7 @@ struct gpr_cmdline {
static int normal_state(gpr_cmdline *cl, char *arg);
gpr_cmdline *gpr_cmdline_create(const char *description) {
- gpr_cmdline *cl = gpr_zalloc(sizeof(gpr_cmdline));
+ gpr_cmdline *cl = (gpr_cmdline *)gpr_zalloc(sizeof(gpr_cmdline));
cl->description = description;
cl->state = normal_state;
@@ -100,7 +100,7 @@ static void add_arg(gpr_cmdline *cl, const char *name, const char *help,
GPR_ASSERT(0 != strcmp(a->name, name));
}
- a = gpr_zalloc(sizeof(arg));
+ a = (arg *)gpr_zalloc(sizeof(arg));
a->name = name;
a->help = help;
a->type = type;
@@ -302,7 +302,7 @@ static int normal_state(gpr_cmdline *cl, char *str) {
eq = strchr(str, '=');
if (eq != NULL) {
/* copy the string into a temp buffer and extract the name */
- tmp = arg_name = gpr_malloc((size_t)(eq - str + 1));
+ tmp = arg_name = (char *)gpr_malloc((size_t)(eq - str + 1));
memcpy(arg_name, str, (size_t)(eq - str));
arg_name[eq - str] = 0;
} else {
diff --git a/src/core/lib/support/histogram.c b/src/core/lib/support/histogram.c
index ba8176bb05..c88695409d 100644
--- a/src/core/lib/support/histogram.c
+++ b/src/core/lib/support/histogram.c
@@ -88,7 +88,7 @@ static double bucket_start(gpr_histogram *h, double x) {
gpr_histogram *gpr_histogram_create(double resolution,
double max_bucket_start) {
- gpr_histogram *h = gpr_malloc(sizeof(gpr_histogram));
+ gpr_histogram *h = (gpr_histogram *)gpr_malloc(sizeof(gpr_histogram));
GPR_ASSERT(resolution > 0.0);
GPR_ASSERT(max_bucket_start > resolution);
h->sum = 0.0;
@@ -102,7 +102,7 @@ gpr_histogram *gpr_histogram_create(double resolution,
h->num_buckets = bucket_for_unchecked(h, max_bucket_start) + 1;
GPR_ASSERT(h->num_buckets > 1);
GPR_ASSERT(h->num_buckets < 100000000);
- h->buckets = gpr_zalloc(sizeof(uint32_t) * h->num_buckets);
+ h->buckets = (uint32_t *)gpr_zalloc(sizeof(uint32_t) * h->num_buckets);
return h;
}
diff --git a/src/core/lib/support/host_port.c b/src/core/lib/support/host_port.c
index f19bdbc835..bbd42c26e0 100644
--- a/src/core/lib/support/host_port.c
+++ b/src/core/lib/support/host_port.c
@@ -98,7 +98,7 @@ int gpr_split_host_port(const char *name, char **host, char **port) {
}
/* Allocate return values. */
- *host = gpr_malloc(host_len + 1);
+ *host = (char *)gpr_malloc(host_len + 1);
memcpy(*host, host_start, host_len);
(*host)[host_len] = '\0';
diff --git a/src/core/lib/support/string.c b/src/core/lib/support/string.c
index d20b86f7cf..11297c9ddb 100644
--- a/src/core/lib/support/string.c
+++ b/src/core/lib/support/string.c
@@ -53,7 +53,7 @@ char *gpr_strdup(const char *src) {
}
len = strlen(src) + 1;
- dst = gpr_malloc(len);
+ dst = (char *)gpr_malloc(len);
memcpy(dst, src, len);
@@ -74,13 +74,13 @@ static dump_out dump_out_create(void) {
static void dump_out_append(dump_out *out, char c) {
if (out->length == out->capacity) {
out->capacity = GPR_MAX(8, 2 * out->capacity);
- out->data = gpr_realloc(out->data, out->capacity);
+ out->data = (char *)gpr_realloc(out->data, out->capacity);
}
out->data[out->length++] = c;
}
static void hexdump(dump_out *out, const char *buf, size_t len) {
- static const char hex[16] = "0123456789abcdef";
+ static const char *hex = "0123456789abcdef";
const uint8_t *const beg = (const uint8_t *)buf;
const uint8_t *const end = beg + len;
@@ -124,16 +124,16 @@ char *gpr_dump(const char *buf, size_t len, uint32_t flags) {
int gpr_parse_bytes_to_uint32(const char *buf, size_t len, uint32_t *result) {
uint32_t out = 0;
- uint32_t new;
+ uint32_t new_val;
size_t i;
if (len == 0) return 0; /* must have some bytes */
for (i = 0; i < len; i++) {
if (buf[i] < '0' || buf[i] > '9') return 0; /* bad char */
- new = 10 * out + (uint32_t)(buf[i] - '0');
- if (new < out) return 0; /* overflow */
- out = new;
+ new_val = 10 * out + (uint32_t)(buf[i] - '0');
+ if (new_val < out) return 0; /* overflow */
+ out = new_val;
}
*result = out;
@@ -201,7 +201,7 @@ int gpr_parse_nonnegative_int(const char *value) {
char *gpr_leftpad(const char *str, char flag, size_t length) {
const size_t str_length = strlen(str);
const size_t out_length = str_length > length ? str_length : length;
- char *out = gpr_malloc(out_length + 1);
+ char *out = (char *)gpr_malloc(out_length + 1);
memset(out, flag, out_length - str_length);
memcpy(out + out_length - str_length, str, str_length);
out[out_length] = 0;
@@ -225,7 +225,7 @@ char *gpr_strjoin_sep(const char **strs, size_t nstrs, const char *sep,
if (nstrs > 0) {
out_length += sep_len * (nstrs - 1); /* separators */
}
- out = gpr_malloc(out_length);
+ out = (char *)gpr_malloc(out_length);
out_length = 0;
for (i = 0; i < nstrs; i++) {
const size_t slen = strlen(strs[i]);
@@ -256,7 +256,7 @@ void gpr_strvec_destroy(gpr_strvec *sv) {
void gpr_strvec_add(gpr_strvec *sv, char *str) {
if (sv->count == sv->capacity) {
sv->capacity = GPR_MAX(sv->capacity + 8, sv->capacity * 2);
- sv->strs = gpr_realloc(sv->strs, sizeof(char *) * sv->capacity);
+ sv->strs = (char **)gpr_realloc(sv->strs, sizeof(char *) * sv->capacity);
}
sv->strs[sv->count++] = str;
}
@@ -278,12 +278,12 @@ int gpr_stricmp(const char *a, const char *b) {
static void add_string_to_split(const char *beg, const char *end, char ***strs,
size_t *nstrs, size_t *capstrs) {
- char *out = gpr_malloc((size_t)(end - beg) + 1);
+ char *out = (char *)gpr_malloc((size_t)(end - beg) + 1);
memcpy(out, beg, (size_t)(end - beg));
out[end - beg] = 0;
if (*nstrs == *capstrs) {
*capstrs = GPR_MAX(8, 2 * *capstrs);
- *strs = gpr_realloc(*strs, sizeof(*strs) * *capstrs);
+ *strs = (char **)gpr_realloc(*strs, sizeof(*strs) * *capstrs);
}
(*strs)[*nstrs] = out;
++*nstrs;
diff --git a/src/core/lib/support/string_posix.c b/src/core/lib/support/string_posix.c
index c804ed5ded..2438b18d21 100644
--- a/src/core/lib/support/string_posix.c
+++ b/src/core/lib/support/string_posix.c
@@ -58,7 +58,7 @@ int gpr_asprintf(char **strp, const char *format, ...) {
/* Allocate a new buffer, with space for the NUL terminator. */
strp_buflen = (size_t)ret + 1;
- if ((*strp = gpr_malloc(strp_buflen)) == NULL) {
+ if ((*strp = (char *)gpr_malloc(strp_buflen)) == NULL) {
/* This shouldn't happen, because gpr_malloc() calls abort(). */
return -1;
}
diff --git a/src/core/lib/support/subprocess_posix.c b/src/core/lib/support/subprocess_posix.c
index ed653b9c2e..b9d0796b01 100644
--- a/src/core/lib/support/subprocess_posix.c
+++ b/src/core/lib/support/subprocess_posix.c
@@ -67,7 +67,7 @@ gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
if (pid == -1) {
return NULL;
} else if (pid == 0) {
- exec_args = gpr_malloc(((size_t)argc + 1) * sizeof(char *));
+ exec_args = (char **)gpr_malloc(((size_t)argc + 1) * sizeof(char *));
memcpy(exec_args, argv, (size_t)argc * sizeof(char *));
exec_args[argc] = NULL;
execv(exec_args[0], exec_args);
@@ -76,7 +76,7 @@ gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
_exit(1);
return NULL;
} else {
- r = gpr_zalloc(sizeof(gpr_subprocess));
+ r = (gpr_subprocess *)gpr_zalloc(sizeof(gpr_subprocess));
r->pid = pid;
return r;
}
diff --git a/src/core/lib/support/thd_posix.c b/src/core/lib/support/thd_posix.c
index 2fc23bffaf..16e645ad91 100644
--- a/src/core/lib/support/thd_posix.c
+++ b/src/core/lib/support/thd_posix.c
@@ -65,7 +65,7 @@ int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
pthread_t p;
/* don't use gpr_malloc as we may cause an infinite recursion with
* the profiling code */
- struct thd_arg *a = malloc(sizeof(*a));
+ struct thd_arg *a = (struct thd_arg *)malloc(sizeof(*a));
GPR_ASSERT(a != NULL);
a->body = thd_body;
a->arg = arg;
diff --git a/src/core/lib/surface/completion_queue.c b/src/core/lib/surface/completion_queue.c
index b0a4b1fbcc..de905941c1 100644
--- a/src/core/lib/surface/completion_queue.c
+++ b/src/core/lib/surface/completion_queue.c
@@ -582,9 +582,9 @@ static void cq_end_op_for_next(grpc_exec_ctx *exec_ctx,
cq_event_queue_push(&cqd->queue, storage);
gpr_atm_no_barrier_fetch_add(&cqd->things_queued_ever, 1);
- int shutdown = gpr_unref(&cqd->pending_events);
-
gpr_mu_lock(cqd->mu);
+
+ int shutdown = gpr_unref(&cqd->pending_events);
if (!shutdown) {
grpc_error *kick_error = cc->poller_vtable->kick(POLLSET_FROM_CQ(cc), NULL);
gpr_mu_unlock(cqd->mu);
diff --git a/src/core/lib/transport/bdp_estimator.c b/src/core/lib/transport/bdp_estimator.c
index da8019d98b..e3a82b492a 100644
--- a/src/core/lib/transport/bdp_estimator.c
+++ b/src/core/lib/transport/bdp_estimator.c
@@ -53,6 +53,11 @@ bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator,
return true;
}
+bool grpc_bdp_estimator_get_bw(grpc_bdp_estimator *estimator, double *bw) {
+ *bw = estimator->bw_est;
+ return true;
+}
+
bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
int64_t num_bytes) {
estimator->accumulator += num_bytes;
diff --git a/src/core/lib/transport/bdp_estimator.h b/src/core/lib/transport/bdp_estimator.h
index 135376edd7..b9a7fc84bb 100644
--- a/src/core/lib/transport/bdp_estimator.h
+++ b/src/core/lib/transport/bdp_estimator.h
@@ -64,6 +64,8 @@ void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name);
// Returns true if a reasonable estimate could be obtained
bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator,
int64_t *estimate);
+// Returns true if a reasonable estimate could be obtained
+bool grpc_bdp_estimator_get_bw(grpc_bdp_estimator *estimator, double *bw);
// Returns true if the user should schedule a ping
bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator,
int64_t num_bytes);
diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc
index 2ead048a1f..6dca6a6862 100644
--- a/src/cpp/server/server_builder.cc
+++ b/src/cpp/server/server_builder.cc
@@ -358,4 +358,14 @@ void ServerBuilder::InternalAddPluginFactory(
(*g_plugin_factory_list).push_back(CreatePlugin);
}
+ServerBuilder& ServerBuilder::EnableWorkaround(grpc_workaround_list id) {
+ switch (id) {
+ case GRPC_WORKAROUND_ID_CRONET_COMPRESSION:
+ return AddChannelArgument(GRPC_ARG_WORKAROUND_CRONET_COMPRESSION, 1);
+ default:
+ gpr_log(GPR_ERROR, "Workaround %u does not exist or is obsolete.", id);
+ return *this;
+ }
+}
+
} // namespace grpc
diff --git a/src/csharp/Grpc.Core/Internal/CallError.cs b/src/csharp/Grpc.Core/Internal/CallError.cs
index 541575f5e6..a46f9b3859 100644
--- a/src/csharp/Grpc.Core/Internal/CallError.cs
+++ b/src/csharp/Grpc.Core/Internal/CallError.cs
@@ -72,7 +72,10 @@ namespace Grpc.Core.Internal
/// </summary>
public static void CheckOk(this CallError callError)
{
- GrpcPreconditions.CheckState(callError == CallError.OK, "Call error: " + callError);
+ if (callError != CallError.OK)
+ {
+ throw new InvalidOperationException("Call error: " + callError);
+ }
}
}
}
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index 3c368fbc6c..8ed0c0b92f 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -117,7 +117,7 @@ namespace Grpc.Core.Internal
{
var ctx = BatchContextSafeHandle.Create();
completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
- Native.grpcsharp_call_send_message(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, sendEmptyInitialMetadata).CheckOk();
+ Native.grpcsharp_call_send_message(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, sendEmptyInitialMetadata ? 1 : 0).CheckOk();
}
}
@@ -140,7 +140,7 @@ namespace Grpc.Core.Internal
var optionalPayloadLength = optionalPayload != null ? new UIntPtr((ulong)optionalPayload.Length) : UIntPtr.Zero;
completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
var statusDetailBytes = MarshalUtils.GetBytesUTF8(status.Detail);
- Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, statusDetailBytes, new UIntPtr((ulong)statusDetailBytes.Length), metadataArray, sendEmptyInitialMetadata,
+ Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, statusDetailBytes, new UIntPtr((ulong)statusDetailBytes.Length), metadataArray, sendEmptyInitialMetadata ? 1 : 0,
optionalPayload, optionalPayloadLength, writeFlags).CheckOk();
}
}
diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
index a98861af61..696987d2a8 100644
--- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
@@ -346,11 +346,11 @@ namespace Grpc.Core.Internal
public delegate CallError grpcsharp_call_start_duplex_streaming_delegate(CallSafeHandle call,
BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags);
public delegate CallError grpcsharp_call_send_message_delegate(CallSafeHandle call,
- BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, bool sendEmptyInitialMetadata);
+ BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, int sendEmptyInitialMetadata);
public delegate CallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call,
BatchContextSafeHandle ctx);
public delegate CallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call,
- BatchContextSafeHandle ctx, StatusCode statusCode, byte[] statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata,
+ BatchContextSafeHandle ctx, StatusCode statusCode, byte[] statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata,
byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
public delegate CallError grpcsharp_call_recv_message_delegate(CallSafeHandle call,
BatchContextSafeHandle ctx);
@@ -406,7 +406,7 @@ namespace Grpc.Core.Internal
public delegate CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin_delegate(NativeMetadataInterceptor interceptor);
public delegate void grpcsharp_metadata_credentials_notify_from_plugin_delegate(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails);
- public delegate ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create_delegate(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, bool forceClientAuth);
+ public delegate ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create_delegate(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, int forceClientAuth);
public delegate void grpcsharp_server_credentials_release_delegate(IntPtr credentials);
public delegate ServerSafeHandle grpcsharp_server_create_delegate(ChannelArgsSafeHandle args);
diff --git a/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
index 24f686fddc..c14fa7c827 100644
--- a/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
@@ -53,7 +53,7 @@ namespace Grpc.Core.Internal
return Native.grpcsharp_ssl_server_credentials_create(pemRootCerts,
keyCertPairCertChainArray, keyCertPairPrivateKeyArray,
new UIntPtr((ulong)keyCertPairCertChainArray.Length),
- forceClientAuth);
+ forceClientAuth ? 1 : 0);
}
protected override bool ReleaseHandle()
diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat
index aa8a8d3b17..d823942be5 100755
--- a/src/csharp/build_packages_dotnetcli.bat
+++ b/src/csharp/build_packages_dotnetcli.bat
@@ -51,11 +51,11 @@ powershell -Command "cp -r ..\..\platform=*\artifacts\protoc_* protoc_plugins"
@rem To be able to build, we also need to put grpc_csharp_ext to its normal location
xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release\
-%DOTNET% pack --configuration Release Grpc.Core --output ..\..\..\artifacts || goto :error
-%DOTNET% pack --configuration Release Grpc.Core.Testing --output ..\..\..\artifacts || goto :error
-%DOTNET% pack --configuration Release Grpc.Auth --output ..\..\..\artifacts || goto :error
-%DOTNET% pack --configuration Release Grpc.HealthCheck --output ..\..\..\artifacts || goto :error
-%DOTNET% pack --configuration Release Grpc.Reflection --output ..\..\..\artifacts || goto :error
+%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core --output ..\..\..\artifacts || goto :error
+%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ..\..\..\artifacts || goto :error
+%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Auth --output ..\..\..\artifacts || goto :error
+%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ..\..\..\artifacts || goto :error
+%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ..\..\..\artifacts || goto :error
%NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error
%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts
diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh
index d33923845c..f79c97fbbc 100755
--- a/src/csharp/build_packages_dotnetcli.sh
+++ b/src/csharp/build_packages_dotnetcli.sh
@@ -48,11 +48,11 @@ dotnet restore Grpc.sln
mkdir -p ../../libs/opt
cp nativelibs/csharp_ext_linux_x64/libgrpc_csharp_ext.so ../../libs/opt
-dotnet pack --configuration Release Grpc.Core --output ../../../artifacts
-dotnet pack --configuration Release Grpc.Core.Testing --output ../../../artifacts
-dotnet pack --configuration Release Grpc.Auth --output ../../../artifacts
-dotnet pack --configuration Release Grpc.HealthCheck --output ../../../artifacts
-dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts
+dotnet pack --configuration Release --include-symbols --include-source Grpc.Core --output ../../../artifacts
+dotnet pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ../../../artifacts
+dotnet pack --configuration Release --include-symbols --include-source Grpc.Auth --output ../../../artifacts
+dotnet pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ../../../artifacts
+dotnet pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ../../../artifacts
nuget pack Grpc.nuspec -Version "1.4.0-dev" -OutputDirectory ../../artifacts
nuget pack Grpc.Tools.nuspec -Version "1.4.0-dev" -OutputDirectory ../../artifacts
diff --git a/src/node/index.js b/src/node/index.js
index 0da3440eb7..2da77c3eae 100644
--- a/src/node/index.js
+++ b/src/node/index.js
@@ -70,8 +70,6 @@ grpc.setDefaultRootsPem(fs.readFileSync(SSL_ROOTS_PATH, 'ascii'));
* Buffers. Defaults to false
* - longsAsStrings: deserialize long values as strings instead of objects.
* Defaults to true
- * - enumsAsStrings: deserialize enum values as strings instead of numbers.
- * Defaults to true
* - deprecatedArgumentOrder: Use the beta method argument order for client
* methods, with optional arguments after the callback. Defaults to false.
* This option is only a temporary stopgap measure to smooth an API breakage.
@@ -105,10 +103,6 @@ exports.loadObject = function loadObject(value, options) {
switch (protobufjsVersion) {
case 6: return protobuf_js_6_common.loadObject(value, options);
case 5:
- var deprecation_message = 'Calling grpc.loadObject with an object ' +
- 'generated by ProtoBuf.js 5 is deprecated. Please upgrade to ' +
- 'ProtoBuf.js 6.';
- common.log(grpc.logVerbosity.INFO, deprecation_message);
return protobuf_js_5_common.loadObject(value, options);
default:
throw new Error('Unrecognized protobufjsVersion', protobufjsVersion);
@@ -117,19 +111,6 @@ exports.loadObject = function loadObject(value, options) {
var loadObject = exports.loadObject;
-function applyProtoRoot(filename, root) {
- if (_.isString(filename)) {
- return filename;
- }
- filename.root = path.resolve(filename.root) + '/';
- root.resolvePath = function(originPath, importPath, alreadyNormalized) {
- return ProtoBuf.util.path.resolve(filename.root,
- importPath,
- alreadyNormalized);
- };
- return filename.file;
-}
-
/**
* Load a gRPC object from a .proto file. The options object can provide the
* following options:
@@ -139,8 +120,6 @@ function applyProtoRoot(filename, root) {
* Buffers. Defaults to false
* - longsAsStrings: deserialize long values as strings instead of objects.
* Defaults to true
- * - enumsAsStrings: deserialize enum values as strings instead of numbers.
- * Defaults to true
* - deprecatedArgumentOrder: Use the beta method argument order for client
* methods, with optional arguments after the callback. Defaults to false.
* This option is only a temporary stopgap measure to smooth an API breakage.
@@ -152,17 +131,31 @@ function applyProtoRoot(filename, root) {
* @return {Object<string, *>} The resulting gRPC object
*/
exports.load = function load(filename, format, options) {
- /* Note: format is currently unused, because the API for loading a proto
- file or a JSON file is identical in Protobuf.js 6. In the future, there is
- still the possibility of adding other formats that would be loaded
- differently */
options = _.defaults(options, common.defaultGrpcOptions);
- options.protobufjs_version = 6;
- var root = new ProtoBuf.Root();
- var parse_options = {keepCase: !options.convertFieldsToCamelCase};
- return loadObject(root.loadSync(applyProtoRoot(filename, root),
- parse_options),
- options);
+ options.protobufjsVersion = 5;
+ if (!format) {
+ format = 'proto';
+ }
+ var convertFieldsToCamelCaseOriginal = ProtoBuf.convertFieldsToCamelCase;
+ if(options && options.hasOwnProperty('convertFieldsToCamelCase')) {
+ ProtoBuf.convertFieldsToCamelCase = options.convertFieldsToCamelCase;
+ }
+ var builder;
+ try {
+ switch(format) {
+ case 'proto':
+ builder = ProtoBuf.loadProtoFile(filename);
+ break;
+ case 'json':
+ builder = ProtoBuf.loadJsonFile(filename);
+ break;
+ default:
+ throw new Error('Unrecognized format "' + format + '"');
+ }
+ } finally {
+ ProtoBuf.convertFieldsToCamelCase = convertFieldsToCamelCaseOriginal;
+ }
+ return loadObject(builder.ns, options);
};
var log_template = _.template(
diff --git a/src/node/src/protobuf_js_5_common.js b/src/node/src/protobuf_js_5_common.js
index 62cf2f4aca..4041e05390 100644
--- a/src/node/src/protobuf_js_5_common.js
+++ b/src/node/src/protobuf_js_5_common.js
@@ -45,8 +45,7 @@ var client = require('./client');
* objects. Defaults to true
* @return {function(Buffer):cls} The deserialization function
*/
-exports.deserializeCls = function deserializeCls(cls, binaryAsBase64,
- longsAsStrings) {
+exports.deserializeCls = function deserializeCls(cls, options) {
/**
* Deserialize a buffer to a message object
* @param {Buffer} arg_buf The buffer to deserialize
@@ -55,7 +54,8 @@ exports.deserializeCls = function deserializeCls(cls, binaryAsBase64,
return function deserialize(arg_buf) {
// Convert to a native object with binary fields as Buffers (first argument)
// and longs as strings (second argument)
- return cls.decode(arg_buf).toRaw(binaryAsBase64, longsAsStrings);
+ return cls.decode(arg_buf).toRaw(options.binaryAsBase64,
+ options.longsAsStrings);
};
};
@@ -128,10 +128,10 @@ exports.getProtobufServiceAttrs = function getProtobufServiceAttrs(service,
responseType: method.resolvedResponseType,
requestSerialize: serializeCls(method.resolvedRequestType.build()),
requestDeserialize: deserializeCls(method.resolvedRequestType.build(),
- binaryAsBase64, longsAsStrings),
+ options),
responseSerialize: serializeCls(method.resolvedResponseType.build()),
responseDeserialize: deserializeCls(method.resolvedResponseType.build(),
- binaryAsBase64, longsAsStrings)
+ options)
};
}));
};
diff --git a/src/node/src/server.js b/src/node/src/server.js
index 08417a74c1..1d9cc7d2c1 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -781,6 +781,11 @@ Server.prototype.addService = function(service, implementation) {
});
};
+var logAddProtoServiceDeprecationOnce = _.once(function() {
+ common.log(constants.logVerbosity.INFO,
+ 'Server#addProtoService is deprecated. Use addService instead');
+});
+
/**
* Add a proto service to the server, with a corresponding implementation
* @deprecated Use grpc.load and Server#addService instead
@@ -792,8 +797,7 @@ Server.prototype.addProtoService = function(service, implementation) {
var options;
var protobuf_js_5_common = require('./protobuf_js_5_common');
var protobuf_js_6_common = require('./protobuf_js_6_common');
- common.log(constants.logVerbosity.INFO,
- 'Server#addProtoService is deprecated. Use addService instead');
+ logAddProtoServiceDeprecationOnce();
if (protobuf_js_5_common.isProbablyProtobufJs5(service)) {
options = _.defaults(service.grpc_options, common.defaultGrpcOptions);
this.addService(
diff --git a/src/node/test/common_test.js b/src/node/test/common_test.js
index e1ce864f97..b7c2c6a8d6 100644
--- a/src/node/test/common_test.js
+++ b/src/node/test/common_test.js
@@ -37,16 +37,15 @@ var assert = require('assert');
var _ = require('lodash');
var common = require('../src/common');
-var protobuf_js_6_common = require('../src/protobuf_js_6_common');
+var protobuf_js_5_common = require('../src/protobuf_js_5_common');
-var serializeCls = protobuf_js_6_common.serializeCls;
-var deserializeCls = protobuf_js_6_common.deserializeCls;
+var serializeCls = protobuf_js_5_common.serializeCls;
+var deserializeCls = protobuf_js_5_common.deserializeCls;
var ProtoBuf = require('protobufjs');
-var messages_proto = new ProtoBuf.Root();
-messages_proto = messages_proto.loadSync(
- __dirname + '/test_messages.proto', {keepCase: true}).resolveAll();
+var messages_proto = ProtoBuf.loadProtoFile(
+ __dirname + '/test_messages.proto').build();
var default_options = common.defaultGrpcOptions;
@@ -101,6 +100,7 @@ describe('Proto message long int serialize and deserialize', function() {
var longNumDeserialize = deserializeCls(messages_proto.LongValues,
num_options);
var serialized = longSerialize({int_64: pos_value});
+ console.log(longDeserialize(serialized));
assert.strictEqual(typeof longDeserialize(serialized).int_64, 'string');
/* With the longsAsStrings option disabled, long values are represented as
* objects with 3 keys: low, high, and unsigned */
@@ -136,7 +136,8 @@ describe('Proto message bytes serialize and deserialize', function() {
var serialized = sequenceSerialize({repeated_field: [10]});
assert.strictEqual(expected_serialize.compare(serialized), 0);
});
- it('should deserialize packed or unpacked repeated', function() {
+ // This tests a bug that was fixed in Protobuf.js 6
+ it.skip('should deserialize packed or unpacked repeated', function() {
var expectedDeserialize = {
bytes_field: new Buffer(''),
repeated_field: [10]
@@ -155,7 +156,8 @@ describe('Proto message bytes serialize and deserialize', function() {
assert.deepEqual(unpackedDeserialized, expectedDeserialize);
});
});
-describe('Proto message oneof serialize and deserialize', function() {
+// This tests a bug that was fixed in Protobuf.js 6
+describe.skip('Proto message oneof serialize and deserialize', function() {
var oneofSerialize = serializeCls(messages_proto.OneOfValues);
var oneofDeserialize = deserializeCls(
messages_proto.OneOfValues, default_options);
@@ -193,7 +195,8 @@ describe('Proto message enum serialize and deserialize', function() {
assert.deepEqual(enumDeserialize(nameSerialized),
enumDeserialize(numberSerialized));
});
- it('Should deserialize as a string the enumsAsStrings option', function() {
+ // This tests a bug that was fixed in Protobuf.js 6
+ it.skip('Should correctly handle the enumsAsStrings option', function() {
var serialized = enumSerialize({enum_value: 'TWO'});
var nameDeserialized = enumDeserialize(serialized);
var numberDeserialized = enumIntDeserialize(serialized);
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index 783028fa99..d2f0511af2 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -43,9 +43,8 @@ var ProtoBuf = require('protobufjs');
var grpc = require('..');
-var math_proto = new ProtoBuf.Root();
-math_proto = math_proto.loadSync(__dirname +
- '/../../proto/math/math.proto', {keepCase: true});
+var math_proto = ProtoBuf.loadProtoFile(__dirname +
+ '/../../proto/math/math.proto');
var mathService = math_proto.lookup('math.Math');
var mathServiceAttrs = grpc.loadObject(
@@ -332,9 +331,7 @@ describe('Echo service', function() {
var server;
var client;
before(function() {
- var test_proto = new ProtoBuf.Root();
- test_proto = test_proto.loadSync(__dirname + '/echo_service.proto',
- {keepCase: true});
+ var test_proto = ProtoBuf.loadProtoFile(__dirname + '/echo_service.proto');
var echo_service = test_proto.lookup('EchoService');
var Client = grpc.loadObject(echo_service);
server = new grpc.Server();
@@ -357,6 +354,13 @@ describe('Echo service', function() {
done();
});
});
+ it('Should convert an undefined argument to default values', function(done) {
+ client.echo(undefined, function(error, response) {
+ assert.ifError(error);
+ assert.deepEqual(response, {value: '', value2: 0});
+ done();
+ });
+ });
});
describe('Generic client and server', function() {
function toString(val) {
@@ -457,9 +461,7 @@ describe('Echo metadata', function() {
var server;
var metadata;
before(function() {
- var test_proto = new ProtoBuf.Root();
- test_proto = test_proto.loadSync(__dirname + '/test_service.proto',
- {keepCase: true});
+ var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
var test_service = test_proto.lookup('TestService');
var Client = grpc.loadObject(test_service);
server = new grpc.Server();
@@ -560,9 +562,7 @@ describe('Client malformed response handling', function() {
var client;
var badArg = new Buffer([0xFF]);
before(function() {
- var test_proto = new ProtoBuf.Root();
- test_proto = test_proto.loadSync(__dirname + '/test_service.proto',
- {keepCase: true});
+ var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
var test_service = test_proto.lookup('TestService');
var malformed_test_service = {
unary: {
@@ -669,9 +669,7 @@ describe('Server serialization failure handling', function() {
var client;
var server;
before(function() {
- var test_proto = new ProtoBuf.Root();
- test_proto = test_proto.loadSync(__dirname + '/test_service.proto',
- {keepCase: true});
+ var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
var test_service = test_proto.lookup('TestService');
var malformed_test_service = {
unary: {
@@ -772,16 +770,13 @@ describe('Server serialization failure handling', function() {
});
});
describe('Other conditions', function() {
- var test_service;
var Client;
var client;
var server;
var port;
before(function() {
- var test_proto = new ProtoBuf.Root();
- test_proto = test_proto.loadSync(__dirname + '/test_service.proto',
- {keepCase: true});
- test_service = test_proto.lookup('TestService');
+ var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
+ var test_service = test_proto.lookup('TestService');
Client = grpc.loadObject(test_service);
server = new grpc.Server();
var trailer_metadata = new grpc.Metadata();
@@ -1121,15 +1116,12 @@ describe('Call propagation', function() {
var proxy;
var proxy_impl;
- var test_service;
var Client;
var client;
var server;
before(function() {
- var test_proto = new ProtoBuf.Root();
- test_proto = test_proto.loadSync(__dirname + '/test_service.proto',
- {keepCase: true});
- test_service = test_proto.lookup('TestService');
+ var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
+ var test_service = test_proto.lookup('TestService');
server = new grpc.Server();
Client = grpc.loadObject(test_service);
server.addService(Client.service, {
diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m
index e36f5c3ee9..deaaf17b07 100644
--- a/src/objective-c/tests/GRPCClientTests.m
+++ b/src/objective-c/tests/GRPCClientTests.m
@@ -293,6 +293,35 @@ static GRPCProtoMethod *kUnaryCallMethod;
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
}
+- (void)testTrailers {
+ __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."];
+ __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."];
+
+ GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
+ path:kEmptyCallMethod.HTTPPath
+ requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
+ // Setting this special key in the header will cause the interop server to echo back the
+ // trailer data.
+ const unsigned char raw_bytes[] = {1,2,3,4};
+ NSData *trailer_data = [NSData dataWithBytes:raw_bytes length:sizeof(raw_bytes)];
+ call.requestHeaders[@"x-grpc-test-echo-trailing-bin"] = trailer_data;
+
+ id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+ XCTAssertNotNil(value, @"nil value received as response.");
+ XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
+ [response fulfill];
+ } completionHandler:^(NSError *errorOrNil) {
+ XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
+ XCTAssertEqualObjects((NSData *)call.responseTrailers[@"x-grpc-test-echo-trailing-bin"],
+ trailer_data,
+ @"Did not receive expected trailer");
+ [completion fulfill];
+ }];
+
+ [call startWithWriteable:responsesWriteable];
+ [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
+}
+
// TODO(makarandd): Move to a different file that contains only unit tests
- (void)testExceptions {
// Try to set parameters to nil for GRPCCall. This should cause an exception
diff --git a/src/php/README.md b/src/php/README.md
index f9f93ba815..90c8cb386a 100644
--- a/src/php/README.md
+++ b/src/php/README.md
@@ -174,6 +174,28 @@ $ sudo make install
```
+### Protobuf Runtime library
+
+There are two protobuf runtime libraries to choose from. They are idenfical in terms of APIs offered.
+
+1. C implementation (for better performance)
+
+``` sh
+$ sudo pecl install protobuf
+```
+
+2. PHP implementation (for easier installation)
+
+
+Add this to your `composer.json` file:
+
+```
+ "require": {
+ "google/protobuf": "^v3.3.0"
+ }
+```
+
+
### PHP Protoc Plugin
You need the gRPC PHP protoc plugin to generate the client stub classes.
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index d3fd88416b..94e0b73a49 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -125,7 +125,12 @@ zval *grpc_parse_metadata_array(grpc_metadata_array
php_grpc_add_next_index_stringl(inner_array, str_val,
GRPC_SLICE_LENGTH(elem->value), false);
add_assoc_zval(array, str_key, inner_array);
+ PHP_GRPC_FREE_STD_ZVAL(inner_array);
}
+ efree(str_key);
+#if PHP_MAJOR_VERSION >= 7
+ efree(str_val);
+#endif
}
return array;
}
@@ -256,8 +261,6 @@ PHP_METHOD(Call, startBatch) {
object_init(result);
php_grpc_ulong index;
zval *recv_status;
- PHP_GRPC_MAKE_STD_ZVAL(recv_status);
- object_init(recv_status);
zval *value;
zval *inner_value;
zval *message_value;
@@ -439,7 +442,7 @@ PHP_METHOD(Call, startBatch) {
grpc_completion_queue_pluck(completion_queue, call->wrapped,
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
#if PHP_MAJOR_VERSION >= 7
- zval recv_md;
+ zval *recv_md;
#endif
for (int i = 0; i < op_num; i++) {
switch(ops[i].op) {
@@ -460,8 +463,10 @@ PHP_METHOD(Call, startBatch) {
array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC);
add_property_zval(result, "metadata", array);
#else
- recv_md = *grpc_parse_metadata_array(&recv_metadata);
- add_property_zval(result, "metadata", &recv_md);
+ recv_md = grpc_parse_metadata_array(&recv_metadata);
+ add_property_zval(result, "metadata", recv_md);
+ zval_ptr_dtor(recv_md);
+ PHP_GRPC_FREE_STD_ZVAL(recv_md);
#endif
PHP_GRPC_DELREF(array);
break;
@@ -475,12 +480,16 @@ PHP_METHOD(Call, startBatch) {
}
break;
case GRPC_OP_RECV_STATUS_ON_CLIENT:
+ PHP_GRPC_MAKE_STD_ZVAL(recv_status);
+ object_init(recv_status);
#if PHP_MAJOR_VERSION < 7
array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC);
add_property_zval(recv_status, "metadata", array);
#else
- recv_md = *grpc_parse_metadata_array(&recv_trailing_metadata);
- add_property_zval(recv_status, "metadata", &recv_md);
+ recv_md = grpc_parse_metadata_array(&recv_trailing_metadata);
+ add_property_zval(recv_status, "metadata", recv_md);
+ zval_ptr_dtor(recv_md);
+ PHP_GRPC_FREE_STD_ZVAL(recv_md);
#endif
PHP_GRPC_DELREF(array);
add_property_long(recv_status, "code", status);
@@ -489,6 +498,9 @@ PHP_METHOD(Call, startBatch) {
true);
gpr_free(status_details_text);
add_property_zval(result, "status", recv_status);
+#if PHP_MAJOR_VERSION >= 7
+ zval_ptr_dtor(recv_status);
+#endif
PHP_GRPC_DELREF(recv_status);
PHP_GRPC_FREE_STD_ZVAL(recv_status);
break;
diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c
index 625c0c62ae..da7100f24a 100644
--- a/src/php/ext/grpc/call_credentials.c
+++ b/src/php/ext/grpc/call_credentials.c
@@ -172,34 +172,54 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context,
object_init(arg);
php_grpc_add_property_string(arg, "service_url", context.service_url, true);
php_grpc_add_property_string(arg, "method_name", context.method_name, true);
- zval *retval;
- PHP_GRPC_MAKE_STD_ZVAL(retval);
+ zval *retval = NULL;
#if PHP_MAJOR_VERSION < 7
zval **params[1];
params[0] = &arg;
state->fci->params = params;
state->fci->retval_ptr_ptr = &retval;
#else
+ PHP_GRPC_MAKE_STD_ZVAL(retval);
state->fci->params = arg;
state->fci->retval = retval;
#endif
state->fci->param_count = 1;
+ PHP_GRPC_DELREF(arg);
+
/* call the user callback function */
zend_call_function(state->fci, state->fci_cache TSRMLS_CC);
grpc_status_code code = GRPC_STATUS_OK;
grpc_metadata_array metadata;
+ bool cleanup = true;
if (Z_TYPE_P(retval) != IS_ARRAY) {
+ cleanup = false;
code = GRPC_STATUS_INVALID_ARGUMENT;
} else if (!create_metadata_array(retval, &metadata)) {
- grpc_metadata_array_destroy(&metadata);
code = GRPC_STATUS_INVALID_ARGUMENT;
}
+ if (retval != NULL) {
+#if PHP_MAJOR_VERSION < 7
+ zval_ptr_dtor(&retval);
+#else
+ zval_ptr_dtor(arg);
+ zval_ptr_dtor(retval);
+ PHP_GRPC_FREE_STD_ZVAL(arg);
+ PHP_GRPC_FREE_STD_ZVAL(retval);
+#endif
+ }
+
/* Pass control back to core */
cb(user_data, metadata.metadata, metadata.count, code, NULL);
+ if (cleanup) {
+ for (int i = 0; i < metadata.count; i++) {
+ grpc_slice_unref(metadata.metadata[i].value);
+ }
+ grpc_metadata_array_destroy(&metadata);
+ }
}
/* Cleanup function for plugin creds API */
@@ -207,8 +227,10 @@ void plugin_destroy_state(void *ptr) {
plugin_state *state = (plugin_state *)ptr;
efree(state->fci);
efree(state->fci_cache);
+#if PHP_MAJOR_VERSION < 7
PHP_GRPC_FREE_STD_ZVAL(state->fci->params);
PHP_GRPC_FREE_STD_ZVAL(state->fci->retval);
+#endif
efree(state);
}
diff --git a/src/php/ext/grpc/php_grpc.h b/src/php/ext/grpc/php_grpc.h
index 13083b0bc7..51f9dd5fe6 100644
--- a/src/php/ext/grpc/php_grpc.h
+++ b/src/php/ext/grpc/php_grpc.h
@@ -40,9 +40,6 @@
extern zend_module_entry grpc_module_entry;
#define phpext_grpc_ptr &grpc_module_entry
-#define PHP_GRPC_VERSION \
- "0.1.0" /* Replace with version number for your extension */
-
#ifdef PHP_WIN32
#define PHP_GRPC_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
@@ -56,10 +53,9 @@ extern zend_module_entry grpc_module_entry;
#endif
#include "php.h"
-
#include "php7_wrapper.h"
-
#include "grpc/grpc.h"
+#include "version.h"
/* These are all function declarations */
/* Code that runs at module initialization */
diff --git a/src/php/ext/grpc/version.h b/src/php/ext/grpc/version.h
new file mode 100644
index 0000000000..993ef2de27
--- /dev/null
+++ b/src/php/ext/grpc/version.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#ifndef VERSION_H
+#define VERSION_H
+
+#define PHP_GRPC_VERSION "1.4.0"
+
+#endif /* VERSION_H */
diff --git a/src/php/tests/qps/composer.json b/src/php/tests/qps/composer.json
index 0fc87098f5..8c1e7b6c74 100644
--- a/src/php/tests/qps/composer.json
+++ b/src/php/tests/qps/composer.json
@@ -1,7 +1,8 @@
{
"minimum-stability": "dev",
"require": {
- "grpc/grpc": "dev-master"
+ "grpc/grpc": "dev-master",
+ "google/protobuf": "^v3.3.0"
},
"autoload": {
"psr-4": {
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 502e946226..9770301d09 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -103,6 +103,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/iomgr/ev_epollsig_linux.c',
'src/core/lib/iomgr/ev_poll_posix.c',
'src/core/lib/iomgr/ev_posix.c',
+ 'src/core/lib/iomgr/ev_windows.c',
'src/core/lib/iomgr/exec_ctx.c',
'src/core/lib/iomgr/executor.c',
'src/core/lib/iomgr/iocp_windows.c',
diff --git a/templates/composer.json.template b/templates/composer.json.template
index 2d4cb11919..a18624db46 100644
--- a/templates/composer.json.template
+++ b/templates/composer.json.template
@@ -8,12 +8,15 @@
"homepage": "http://grpc.io",
"license": "BSD-3-Clause",
"require": {
- "php": ">=5.5.0",
- "google/protobuf": "^v3.3.0"
+ "php": ">=5.5.0"
},
"require-dev": {
"google/auth": "v0.9"
},
+ "suggest": {
+ "ext-protobuf": "For better performance, install the protobuf C extension.",
+ "google/protobuf": "To get started using grpc quickly, install the native protobuf library."
+ },
"autoload": {
"psr-4": {
"Grpc\\": "src/php/lib/Grpc/"
diff --git a/templates/config.m4.template b/templates/config.m4.template
index 13ff7389e6..a6357b7fb1 100644
--- a/templates/config.m4.template
+++ b/templates/config.m4.template
@@ -10,23 +10,21 @@
PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
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/cares)
- PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/cares)
LIBS="-lpthread $LIBS"
+ CFLAGS="-Wall -Werror -Wno-parentheses-equality -Wno-unused-value -std=c11"
+ CXXFLAGS="-std=c++11"
GRPC_SHARED_LIBADD="-lpthread $GRPC_SHARED_LIBADD"
+ PHP_REQUIRE_CXX()
PHP_ADD_LIBRARY(pthread)
-
PHP_ADD_LIBRARY(dl,,GRPC_SHARED_LIBADD)
PHP_ADD_LIBRARY(dl)
case $host in
*darwin*)
- PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/config_darwin)
;;
*)
- PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/cares/config_linux)
PHP_ADD_LIBRARY(rt,,GRPC_SHARED_LIBADD)
PHP_ADD_LIBRARY(rt)
;;
@@ -43,10 +41,9 @@
% endfor
% endif
% endfor
- , $ext_shared, , -Wall -Werror ${"\\"}
- -Wno-parentheses-equality -Wno-unused-value -std=c11 ${"\\"}
- -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN ${"\\"}
- -D_HAS_EXCEPTIONS=0 -DNOMINMAX)
+ , $ext_shared, , -fvisibility=hidden ${"\\"}
+ -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN ${"\\"}
+ -D_HAS_EXCEPTIONS=0 -DNOMINMAX -DGRPC_ARES=0)
PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
<%
diff --git a/templates/package.json.template b/templates/package.json.template
index 3bae8fde43..551c25f042 100644
--- a/templates/package.json.template
+++ b/templates/package.json.template
@@ -36,7 +36,7 @@
"lodash": "^4.15.0",
"nan": "^2.0.0",
"node-pre-gyp": "^0.6.0",
- "protobufjs": "^6.7.0"
+ "protobufjs": "^5.0.0"
},
"devDependencies": {
"async": "^2.0.1",
diff --git a/templates/package.xml.template b/templates/package.xml.template
index 8655cfa1d9..394b8154ee 100644
--- a/templates/package.xml.template
+++ b/templates/package.xml.template
@@ -12,7 +12,7 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
- <date>2017-03-01</date>
+ <date>2017-05-05</date>
<time>16:06:07</time>
<version>
<release>${settings.php_version.php()}</release>
@@ -24,8 +24,7 @@
</stability>
<license>BSD</license>
<notes>
- - Added arg info macros #9751
- - Updated codegen to be consistent with protobuf #9492
+ - Fixed some memory leaks #9559, #10996
</notes>
<contents>
<dir baseinstalldir="/" name="/">
@@ -43,6 +42,7 @@
% endfor
% endif
% endfor
+ <file name="LICENSE" role="doc" />
</dir>
</contents>
<dependencies>
@@ -358,5 +358,21 @@
- Updated codegen to be consistent with protobuf #9492
</notes>
</release>
+ <release>
+ <version>
+ <release>1.2.0</release>
+ <api>1.2.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <date>2017-03-20</date>
+ <license>BSD</license>
+ <notes>
+ - Added arg info macros #9751
+ - Updated codegen to be consistent with protobuf #9492
+ </notes>
+ </release>
</changelog>
</package>
diff --git a/templates/src/csharp/build_packages_dotnetcli.bat.template b/templates/src/csharp/build_packages_dotnetcli.bat.template
index 3db1e0ac3d..8624c34782 100755
--- a/templates/src/csharp/build_packages_dotnetcli.bat.template
+++ b/templates/src/csharp/build_packages_dotnetcli.bat.template
@@ -53,11 +53,11 @@
@rem To be able to build, we also need to put grpc_csharp_ext to its normal location
xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release${"\\"}
- %%DOTNET% pack --configuration Release Grpc.Core --output ..\..\..\artifacts || goto :error
- %%DOTNET% pack --configuration Release Grpc.Core.Testing --output ..\..\..\artifacts || goto :error
- %%DOTNET% pack --configuration Release Grpc.Auth --output ..\..\..\artifacts || goto :error
- %%DOTNET% pack --configuration Release Grpc.HealthCheck --output ..\..\..\artifacts || goto :error
- %%DOTNET% pack --configuration Release Grpc.Reflection --output ..\..\..\artifacts || goto :error
+ %%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core --output ..\..\..\artifacts || goto :error
+ %%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ..\..\..\artifacts || goto :error
+ %%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Auth --output ..\..\..\artifacts || goto :error
+ %%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ..\..\..\artifacts || goto :error
+ %%DOTNET% pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ..\..\..\artifacts || goto :error
%%NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error
%%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts
diff --git a/templates/src/csharp/build_packages_dotnetcli.sh.template b/templates/src/csharp/build_packages_dotnetcli.sh.template
index 65afec55c4..bff497c85a 100755
--- a/templates/src/csharp/build_packages_dotnetcli.sh.template
+++ b/templates/src/csharp/build_packages_dotnetcli.sh.template
@@ -50,11 +50,11 @@
mkdir -p ../../libs/opt
cp nativelibs/csharp_ext_linux_x64/libgrpc_csharp_ext.so ../../libs/opt
- dotnet pack --configuration Release Grpc.Core --output ../../../artifacts
- dotnet pack --configuration Release Grpc.Core.Testing --output ../../../artifacts
- dotnet pack --configuration Release Grpc.Auth --output ../../../artifacts
- dotnet pack --configuration Release Grpc.HealthCheck --output ../../../artifacts
- dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts
+ dotnet pack --configuration Release --include-symbols --include-source Grpc.Core --output ../../../artifacts
+ dotnet pack --configuration Release --include-symbols --include-source Grpc.Core.Testing --output ../../../artifacts
+ dotnet pack --configuration Release --include-symbols --include-source Grpc.Auth --output ../../../artifacts
+ dotnet pack --configuration Release --include-symbols --include-source Grpc.HealthCheck --output ../../../artifacts
+ dotnet pack --configuration Release --include-symbols --include-source Grpc.Reflection --output ../../../artifacts
nuget pack Grpc.nuspec -Version "${settings.csharp_version}" -OutputDirectory ../../artifacts
nuget pack Grpc.Tools.nuspec -Version "${settings.csharp_version}" -OutputDirectory ../../artifacts
diff --git a/templates/src/php/ext/grpc/version.h.template b/templates/src/php/ext/grpc/version.h.template
new file mode 100644
index 0000000000..828ea69296
--- /dev/null
+++ b/templates/src/php/ext/grpc/version.h.template
@@ -0,0 +1,42 @@
+%YAML 1.2
+--- |
+ /*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+ #ifndef VERSION_H
+ #define VERSION_H
+
+ #define PHP_GRPC_VERSION "${settings.php_version.php_composer()}"
+
+ #endif /* VERSION_H */
diff --git a/templates/tools/dockerfile/go_build_interop.sh.include b/templates/tools/dockerfile/go_build_interop.sh.include
new file mode 100755
index 0000000000..46aabc6b38
--- /dev/null
+++ b/templates/tools/dockerfile/go_build_interop.sh.include
@@ -0,0 +1,47 @@
+#!/bin/bash
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Builds Go interop server and client in a base image.
+set -e
+
+# Clone just the grpc-go source code without any dependencies.
+# We are cloning from a local git repo that contains the right revision
+# to test instead of using "go get" to download from Github directly.
+git clone --recursive /var/local/jenkins/grpc-go src/google.golang.org/grpc
+
+# Get all gRPC Go dependencies
+(cd src/google.golang.org/grpc && make deps && make testdeps)
+
+# copy service account keys if available
+cp -r /var/local/jenkins/service_account $HOME || true
+
+# Build the interop client and server
+(cd src/google.golang.org/grpc/interop/client && go install)
+(cd src/google.golang.org/grpc/interop/server && go install)
diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_go1.7/build_interop.sh.template b/templates/tools/dockerfile/interoptest/grpc_interop_go1.7/build_interop.sh.template
new file mode 100644
index 0000000000..a08798b1d6
--- /dev/null
+++ b/templates/tools/dockerfile/interoptest/grpc_interop_go1.7/build_interop.sh.template
@@ -0,0 +1,3 @@
+%YAML 1.2
+--- |
+ <%include file="../../go_build_interop.sh.include"/>
diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_go1.8/build_interop.sh.template b/templates/tools/dockerfile/interoptest/grpc_interop_go1.8/build_interop.sh.template
new file mode 100644
index 0000000000..a08798b1d6
--- /dev/null
+++ b/templates/tools/dockerfile/interoptest/grpc_interop_go1.8/build_interop.sh.template
@@ -0,0 +1,3 @@
+%YAML 1.2
+--- |
+ <%include file="../../go_build_interop.sh.include"/>
diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c
index 0fafb0c8c9..5c54549674 100644
--- a/test/core/end2end/cq_verifier.c
+++ b/test/core/end2end/cq_verifier.c
@@ -189,10 +189,16 @@ int byte_buffer_eq_string(grpc_byte_buffer *bb, const char *str) {
return res;
}
+static bool is_probably_integer(void *p) { return ((uintptr_t)p) < 1000000; }
+
static void expectation_to_strvec(gpr_strvec *buf, expectation *e) {
char *tmp;
- gpr_asprintf(&tmp, "%p ", e->tag);
+ if (is_probably_integer(e->tag)) {
+ gpr_asprintf(&tmp, "tag(%" PRIdPTR ") ", (intptr_t)e->tag);
+ } else {
+ gpr_asprintf(&tmp, "%p ", e->tag);
+ }
gpr_strvec_add(buf, tmp);
switch (e->type) {
diff --git a/test/core/end2end/fixtures/h2_full+workarounds.c b/test/core/end2end/fixtures/h2_full+workarounds.c
index 2e9264ffa6..fcb2024645 100644
--- a/test/core/end2end/fixtures/h2_full+workarounds.c
+++ b/test/core/end2end/fixtures/h2_full+workarounds.c
@@ -83,10 +83,11 @@ void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f,
void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f,
grpc_channel_args *server_args) {
+ int i;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
fullstack_fixture_data *ffd = f->fixture_data;
grpc_arg args[GRPC_MAX_WORKAROUND_ID];
- for (uint32_t i = 0; i < GRPC_MAX_WORKAROUND_ID; i++) {
+ for (i = 0; i < GRPC_MAX_WORKAROUND_ID; i++) {
args[i].key = workarounds_arg[i];
args[i].type = GRPC_ARG_INTEGER;
args[i].value.integer = 1;
diff --git a/test/core/end2end/fixtures/http_proxy_fixture.c b/test/core/end2end/fixtures/http_proxy_fixture.c
index c2d8480e69..b8a53ed113 100644
--- a/test/core/end2end/fixtures/http_proxy_fixture.c
+++ b/test/core/end2end/fixtures/http_proxy_fixture.c
@@ -50,6 +50,7 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/http/parser.h"
#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/exec_ctx.h"
@@ -71,6 +72,8 @@ struct grpc_end2end_http_proxy {
gpr_mu* mu;
grpc_pollset* pollset;
gpr_refcount users;
+
+ grpc_combiner* combiner;
};
//
@@ -400,19 +403,19 @@ static void on_accept(grpc_exec_ctx* exec_ctx, void* arg,
grpc_pollset_set_add_pollset(exec_ctx, conn->pollset_set, proxy->pollset);
grpc_endpoint_add_to_pollset_set(exec_ctx, endpoint, conn->pollset_set);
grpc_closure_init(&conn->on_read_request_done, on_read_request_done, conn,
- grpc_schedule_on_exec_ctx);
+ grpc_combiner_scheduler(conn->proxy->combiner, false));
grpc_closure_init(&conn->on_server_connect_done, on_server_connect_done, conn,
- grpc_schedule_on_exec_ctx);
+ grpc_combiner_scheduler(conn->proxy->combiner, false));
grpc_closure_init(&conn->on_write_response_done, on_write_response_done, conn,
- grpc_schedule_on_exec_ctx);
+ grpc_combiner_scheduler(conn->proxy->combiner, false));
grpc_closure_init(&conn->on_client_read_done, on_client_read_done, conn,
- grpc_schedule_on_exec_ctx);
+ grpc_combiner_scheduler(conn->proxy->combiner, false));
grpc_closure_init(&conn->on_client_write_done, on_client_write_done, conn,
- grpc_schedule_on_exec_ctx);
+ grpc_combiner_scheduler(conn->proxy->combiner, false));
grpc_closure_init(&conn->on_server_read_done, on_server_read_done, conn,
- grpc_schedule_on_exec_ctx);
+ grpc_combiner_scheduler(conn->proxy->combiner, false));
grpc_closure_init(&conn->on_server_write_done, on_server_write_done, conn,
- grpc_schedule_on_exec_ctx);
+ grpc_combiner_scheduler(conn->proxy->combiner, false));
grpc_slice_buffer_init(&conn->client_read_buffer);
grpc_slice_buffer_init(&conn->client_deferred_write_buffer);
grpc_slice_buffer_init(&conn->client_write_buffer);
@@ -453,6 +456,7 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(void) {
grpc_end2end_http_proxy* proxy =
(grpc_end2end_http_proxy*)gpr_malloc(sizeof(*proxy));
memset(proxy, 0, sizeof(*proxy));
+ proxy->combiner = grpc_combiner_create(NULL);
gpr_ref_init(&proxy->users, 1);
// Construct proxy address.
const int proxy_port = grpc_pick_unused_port_or_die();
@@ -504,6 +508,7 @@ void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy) {
grpc_pollset_shutdown(&exec_ctx, proxy->pollset,
grpc_closure_create(destroy_pollset, proxy->pollset,
grpc_schedule_on_exec_ctx));
+ grpc_combiner_unref(&exec_ctx, proxy->combiner);
gpr_free(proxy);
grpc_exec_ctx_finish(&exec_ctx);
}
diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c
index f0e3394b2e..87ad095170 100644
--- a/test/core/surface/concurrent_connectivity_test.c
+++ b/test/core/surface/concurrent_connectivity_test.c
@@ -112,7 +112,9 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *vargs, grpc_endpoint *tcp,
grpc_endpoint_shutdown(exec_ctx, tcp,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Connected"));
grpc_endpoint_destroy(exec_ctx, tcp);
+ gpr_mu_lock(args->mu);
GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, NULL));
+ gpr_mu_unlock(args->mu);
}
void bad_server_thread(void *vargs) {
diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc
index 8417f1a99c..4e1bcc7a60 100644
--- a/test/cpp/end2end/grpclb_end2end_test.cc
+++ b/test/cpp/end2end/grpclb_end2end_test.cc
@@ -98,12 +98,12 @@ namespace {
template <typename ServiceType>
class CountedService : public ServiceType {
public:
- int request_count() {
+ size_t request_count() {
std::unique_lock<std::mutex> lock(mu_);
return request_count_;
}
- int response_count() {
+ size_t response_count() {
std::unique_lock<std::mutex> lock(mu_);
return response_count_;
}
@@ -121,8 +121,8 @@ class CountedService : public ServiceType {
std::mutex mu_;
private:
- int request_count_ = 0;
- int response_count_ = 0;
+ size_t request_count_ = 0;
+ size_t response_count_ = 0;
};
using BackendService = CountedService<TestServiceImpl>;
@@ -243,9 +243,18 @@ class BalancerServiceImpl : public BalancerService {
}
static LoadBalanceResponse BuildResponseForBackends(
- const std::vector<int>& backend_ports) {
+ const std::vector<int>& backend_ports, int num_drops_for_rate_limiting,
+ int num_drops_for_load_balancing) {
LoadBalanceResponse response;
- for (const int backend_port : backend_ports) {
+ for (int i = 0; i < num_drops_for_rate_limiting; ++i) {
+ auto* server = response.mutable_server_list()->add_servers();
+ server->set_drop_for_rate_limiting(true);
+ }
+ for (int i = 0; i < num_drops_for_load_balancing; ++i) {
+ auto* server = response.mutable_server_list()->add_servers();
+ server->set_drop_for_load_balancing(true);
+ }
+ for (const int& backend_port : backend_ports) {
auto* server = response.mutable_server_list()->add_servers();
server->set_ip_address(Ip4ToPackedString("127.0.0.1"));
server->set_port(backend_port);
@@ -327,10 +336,8 @@ class GrpclbEnd2endTest : public ::testing::Test {
ChannelArguments args;
args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR,
response_generator_);
- std::ostringstream uri;
- uri << "test:///servername_not_used";
- channel_ =
- CreateCustomChannel(uri.str(), InsecureChannelCredentials(), args);
+ channel_ = CreateCustomChannel("test:///not_used",
+ InsecureChannelCredentials(), args);
stub_ = grpc::testing::EchoTestService::NewStub(channel_);
}
@@ -467,26 +474,33 @@ class SingleBalancerTest : public GrpclbEnd2endTest {
};
TEST_F(SingleBalancerTest, Vanilla) {
+ const size_t kNumRpcsPerAddress = 100;
ScheduleResponseForBalancer(
- 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), 0);
+ 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+ 0);
// Make sure that trying to connect works without a call.
channel_->GetState(true /* try_to_connect */);
- // Start servers and send 100 RPCs per server.
- const auto& statuses_and_responses = SendRpc(kMessage_, 100 * num_backends_);
+ // Send 100 RPCs per server.
+ const auto& statuses_and_responses =
+ SendRpc(kMessage_, kNumRpcsPerAddress * num_backends_);
for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
+ const Status& status = status_and_response.first;
+ const EchoResponse& response = status_and_response.second;
+ EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+ << " message=" << status.error_message();
+ EXPECT_EQ(response.message(), kMessage_);
}
// Each backend should have gotten 100 requests.
for (size_t i = 0; i < backends_.size(); ++i) {
- EXPECT_EQ(100, backend_servers_[i].service_->request_count());
+ EXPECT_EQ(kNumRpcsPerAddress,
+ backend_servers_[i].service_->request_count());
}
// The balancer got a single request.
- EXPECT_EQ(1, balancer_servers_[0].service_->request_count());
+ EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
// and sent a single response.
- EXPECT_EQ(1, balancer_servers_[0].service_->response_count());
+ EXPECT_EQ(1U, balancer_servers_[0].service_->response_count());
// Check LB policy name for the channel.
EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
@@ -500,7 +514,7 @@ TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) {
ScheduleResponseForBalancer(0, LoadBalanceResponse(), 0);
// Send non-empty serverlist only after kServerlistDelayMs
ScheduleResponseForBalancer(
- 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()),
+ 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
kServerlistDelayMs);
const auto t0 = system_clock::now();
@@ -518,17 +532,20 @@ TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) {
// Each backend should have gotten 1 request.
for (size_t i = 0; i < backends_.size(); ++i) {
- EXPECT_EQ(1, backend_servers_[i].service_->request_count());
+ EXPECT_EQ(1U, backend_servers_[i].service_->request_count());
}
for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
+ const Status& status = status_and_response.first;
+ const EchoResponse& response = status_and_response.second;
+ EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+ << " message=" << status.error_message();
+ EXPECT_EQ(response.message(), kMessage_);
}
// The balancer got a single request.
- EXPECT_EQ(1, balancer_servers_[0].service_->request_count());
+ EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
// and sent two responses.
- EXPECT_EQ(2, balancer_servers_[0].service_->response_count());
+ EXPECT_EQ(2U, balancer_servers_[0].service_->response_count());
// Check LB policy name for the channel.
EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
@@ -539,10 +556,11 @@ TEST_F(SingleBalancerTest, RepeatedServerlist) {
// Send a serverlist right away.
ScheduleResponseForBalancer(
- 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), 0);
+ 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+ 0);
// ... and the same one a bit later.
ScheduleResponseForBalancer(
- 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()),
+ 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
kServerlistDelayMs);
// Send num_backends/2 requests.
@@ -550,14 +568,17 @@ TEST_F(SingleBalancerTest, RepeatedServerlist) {
// only the first half of the backends will receive them.
for (size_t i = 0; i < backends_.size(); ++i) {
if (i < backends_.size() / 2)
- EXPECT_EQ(1, backend_servers_[i].service_->request_count());
+ EXPECT_EQ(1U, backend_servers_[i].service_->request_count());
else
- EXPECT_EQ(0, backend_servers_[i].service_->request_count());
+ EXPECT_EQ(0U, backend_servers_[i].service_->request_count());
}
EXPECT_EQ(statuses_and_responses.size(), num_backends_ / 2);
for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
+ const Status& status = status_and_response.first;
+ const EchoResponse& response = status_and_response.second;
+ EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+ << " message=" << status.error_message();
+ EXPECT_EQ(response.message(), kMessage_);
}
// Wait for the (duplicated) serverlist update.
@@ -566,7 +587,7 @@ TEST_F(SingleBalancerTest, RepeatedServerlist) {
gpr_time_from_millis(kServerlistDelayMs * 1.1, GPR_TIMESPAN)));
// Verify the LB has sent two responses.
- EXPECT_EQ(2, balancer_servers_[0].service_->response_count());
+ EXPECT_EQ(2U, balancer_servers_[0].service_->response_count());
// Some more calls to complete the total number of backends.
statuses_and_responses = SendRpc(
@@ -575,52 +596,146 @@ TEST_F(SingleBalancerTest, RepeatedServerlist) {
// Because a duplicated serverlist should have no effect, all backends must
// have been hit once now.
for (size_t i = 0; i < backends_.size(); ++i) {
- EXPECT_EQ(1, backend_servers_[i].service_->request_count());
+ EXPECT_EQ(1U, backend_servers_[i].service_->request_count());
}
EXPECT_EQ(statuses_and_responses.size(), num_backends_ / 2);
for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
+ const Status& status = status_and_response.first;
+ const EchoResponse& response = status_and_response.second;
+ EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+ << " message=" << status.error_message();
+ EXPECT_EQ(response.message(), kMessage_);
}
// The balancer got a single request.
- EXPECT_EQ(1, balancer_servers_[0].service_->request_count());
+ EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
// Check LB policy name for the channel.
EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName());
}
+TEST_F(SingleBalancerTest, Drop) {
+ const size_t kNumRpcsPerAddress = 100;
+ ScheduleResponseForBalancer(
+ 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 1, 2),
+ 0);
+ // Send 100 RPCs for each server and drop address.
+ const auto& statuses_and_responses =
+ SendRpc(kMessage_, kNumRpcsPerAddress * (num_backends_ + 3));
+
+ size_t num_drops = 0;
+ for (const auto& status_and_response : statuses_and_responses) {
+ const Status& status = status_and_response.first;
+ const EchoResponse& response = status_and_response.second;
+ if (!status.ok() &&
+ status.error_message() == "Call dropped by load balancing policy") {
+ ++num_drops;
+ } else {
+ EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+ << " message=" << status.error_message();
+ EXPECT_EQ(response.message(), kMessage_);
+ }
+ }
+ EXPECT_EQ(kNumRpcsPerAddress * 3, num_drops);
+
+ // Each backend should have gotten 100 requests.
+ for (size_t i = 0; i < backends_.size(); ++i) {
+ EXPECT_EQ(kNumRpcsPerAddress,
+ backend_servers_[i].service_->request_count());
+ }
+ // The balancer got a single request.
+ EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
+ // and sent a single response.
+ EXPECT_EQ(1U, balancer_servers_[0].service_->response_count());
+}
+
class SingleBalancerWithClientLoadReportingTest : public GrpclbEnd2endTest {
public:
SingleBalancerWithClientLoadReportingTest() : GrpclbEnd2endTest(4, 1, 2) {}
};
TEST_F(SingleBalancerWithClientLoadReportingTest, Vanilla) {
+ const size_t kNumRpcsPerAddress = 100;
ScheduleResponseForBalancer(
- 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), 0);
- // Start servers and send 100 RPCs per server.
- const auto& statuses_and_responses = SendRpc(kMessage_, 100 * num_backends_);
+ 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 0, 0),
+ 0);
+ // Send 100 RPCs per server.
+ const auto& statuses_and_responses =
+ SendRpc(kMessage_, kNumRpcsPerAddress * num_backends_);
for (const auto& status_and_response : statuses_and_responses) {
- EXPECT_TRUE(status_and_response.first.ok());
- EXPECT_EQ(status_and_response.second.message(), kMessage_);
+ const Status& status = status_and_response.first;
+ const EchoResponse& response = status_and_response.second;
+ EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+ << " message=" << status.error_message();
+ EXPECT_EQ(response.message(), kMessage_);
}
// Each backend should have gotten 100 requests.
for (size_t i = 0; i < backends_.size(); ++i) {
- EXPECT_EQ(100, backend_servers_[i].service_->request_count());
+ EXPECT_EQ(kNumRpcsPerAddress,
+ backend_servers_[i].service_->request_count());
}
// The balancer got a single request.
- EXPECT_EQ(1, balancer_servers_[0].service_->request_count());
+ EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
// and sent a single response.
- EXPECT_EQ(1, balancer_servers_[0].service_->response_count());
+ EXPECT_EQ(1U, balancer_servers_[0].service_->response_count());
const ClientStats client_stats = WaitForLoadReports();
- EXPECT_EQ(100 * num_backends_, client_stats.num_calls_started);
- EXPECT_EQ(100 * num_backends_, client_stats.num_calls_finished);
+ EXPECT_EQ(kNumRpcsPerAddress * num_backends_, client_stats.num_calls_started);
+ EXPECT_EQ(kNumRpcsPerAddress * num_backends_,
+ client_stats.num_calls_finished);
EXPECT_EQ(0U, client_stats.num_calls_finished_with_drop_for_rate_limiting);
EXPECT_EQ(0U, client_stats.num_calls_finished_with_drop_for_load_balancing);
EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send);
- EXPECT_EQ(100 * num_backends_,
+ EXPECT_EQ(kNumRpcsPerAddress * num_backends_,
+ client_stats.num_calls_finished_known_received);
+}
+
+TEST_F(SingleBalancerWithClientLoadReportingTest, Drop) {
+ const size_t kNumRpcsPerAddress = 3;
+ ScheduleResponseForBalancer(
+ 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), 2, 1),
+ 0);
+ // Send 100 RPCs for each server and drop address.
+ const auto& statuses_and_responses =
+ SendRpc(kMessage_, kNumRpcsPerAddress * (num_backends_ + 3));
+
+ size_t num_drops = 0;
+ for (const auto& status_and_response : statuses_and_responses) {
+ const Status& status = status_and_response.first;
+ const EchoResponse& response = status_and_response.second;
+ if (!status.ok() &&
+ status.error_message() == "Call dropped by load balancing policy") {
+ ++num_drops;
+ } else {
+ EXPECT_TRUE(status.ok()) << "code=" << status.error_code()
+ << " message=" << status.error_message();
+ EXPECT_EQ(response.message(), kMessage_);
+ }
+ }
+ EXPECT_EQ(kNumRpcsPerAddress * 3, num_drops);
+
+ // Each backend should have gotten 100 requests.
+ for (size_t i = 0; i < backends_.size(); ++i) {
+ EXPECT_EQ(kNumRpcsPerAddress,
+ backend_servers_[i].service_->request_count());
+ }
+ // The balancer got a single request.
+ EXPECT_EQ(1U, balancer_servers_[0].service_->request_count());
+ // and sent a single response.
+ EXPECT_EQ(1U, balancer_servers_[0].service_->response_count());
+
+ const ClientStats client_stats = WaitForLoadReports();
+ EXPECT_EQ(kNumRpcsPerAddress * (num_backends_ + 3),
+ client_stats.num_calls_started);
+ EXPECT_EQ(kNumRpcsPerAddress * (num_backends_ + 3),
+ client_stats.num_calls_finished);
+ EXPECT_EQ(kNumRpcsPerAddress * 2,
+ client_stats.num_calls_finished_with_drop_for_rate_limiting);
+ EXPECT_EQ(kNumRpcsPerAddress,
+ client_stats.num_calls_finished_with_drop_for_load_balancing);
+ EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send);
+ EXPECT_EQ(kNumRpcsPerAddress * num_backends_,
client_stats.num_calls_finished_known_received);
}
diff --git a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
index 6b9fa8b38d..d7e3a9cf47 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
@@ -101,6 +101,8 @@ class TrickledCHTTP2 : public EndpointPairFixture {
}
void AddToLabel(std::ostream& out, benchmark::State& state) {
+ grpc_chttp2_transport* client =
+ reinterpret_cast<grpc_chttp2_transport*>(client_transport_);
out << " writes/iter:"
<< ((double)stats_.num_writes / (double)state.iterations())
<< " cli_transport_stalls/iter:"
@@ -116,7 +118,8 @@ class TrickledCHTTP2 : public EndpointPairFixture {
(double)state.iterations())
<< " svr_stream_stalls/iter:"
<< ((double)server_stats_.streams_stalled_due_to_stream_flow_control /
- (double)state.iterations());
+ (double)state.iterations())
+ << " cli_bw_est:" << (double)client->bdp_estimator.bw_est;
}
void Log(int64_t iteration) {
diff --git a/third_party/protobuf b/third_party/protobuf
-Subproject a6189acd18b00611c1dc7042299ad75486f08a1
+Subproject 593e917c176b5bc5aafa57bf9f6030d749d91cd
diff --git a/tools/README.md b/tools/README.md
index 62e91246d0..3cef618179 100644
--- a/tools/README.md
+++ b/tools/README.md
@@ -13,6 +13,8 @@ container engine, BigQuery etc)
internal_ci: Support for running tests on an internal CI platform.
+interop_matrix: Scripts to build, upload, and run gRPC clients in docker with various language/runtimes.
+
jenkins: Support for running tests on Jenkins.
run_tests: Scripts to run gRPC tests in parallel.
diff --git a/tools/dockerfile/grpc_artifact_linux_armv6/Dockerfile b/tools/dockerfile/grpc_artifact_linux_armv6/Dockerfile
new file mode 100644
index 0000000000..b085dd00db
--- /dev/null
+++ b/tools/dockerfile/grpc_artifact_linux_armv6/Dockerfile
@@ -0,0 +1,39 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Docker file for building gRPC Raspbian binaries
+
+FROM quay.io/grpc/raspbian_armv6
+
+# Place any extra build instructions between these commands
+# Recommend modifying upstream docker image (quay.io/grpc/raspbian_armv6)
+# for build steps because running them under QEMU is very slow
+# (https://github.com/kpayson64/armv7hf-debian-qemu)
+# RUN [ "cross-build-start" ]
+# RUN [ "cross-build-end" ]
diff --git a/tools/dockerfile/grpc_artifact_linux_armv7/Dockerfile b/tools/dockerfile/grpc_artifact_linux_armv7/Dockerfile
new file mode 100644
index 0000000000..d7759a6c50
--- /dev/null
+++ b/tools/dockerfile/grpc_artifact_linux_armv7/Dockerfile
@@ -0,0 +1,39 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Docker file for building gRPC Raspbian binaries
+
+FROM quay.io/grpc/raspbian_armv7
+
+# Place any extra build instructions between these commands
+# Recommend modifying upstream docker image (quay.io/grpc/raspbian_armv7)
+# for build steps because running them under QEMU is very slow
+# (https://github.com/kpayson64/armv7hf-debian-qemu)
+# RUN [ "cross-build-start" ]
+# RUN [ "cross-build-end" ]
diff --git a/tools/dockerfile/interoptest/grpc_interop_go1.7/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_go1.7/build_interop.sh
new file mode 100644
index 0000000000..5eca90cdea
--- /dev/null
+++ b/tools/dockerfile/interoptest/grpc_interop_go1.7/build_interop.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Builds Go interop server and client in a base image.
+set -e
+
+# Clone just the grpc-go source code without any dependencies.
+# We are cloning from a local git repo that contains the right revision
+# to test instead of using "go get" to download from Github directly.
+git clone --recursive /var/local/jenkins/grpc-go src/google.golang.org/grpc
+
+# Get all gRPC Go dependencies
+(cd src/google.golang.org/grpc && make deps && make testdeps)
+
+# copy service account keys if available
+cp -r /var/local/jenkins/service_account $HOME || true
+
+# Build the interop client and server
+(cd src/google.golang.org/grpc/interop/client && go install)
+(cd src/google.golang.org/grpc/interop/server && go install)
+
diff --git a/tools/dockerfile/interoptest/grpc_interop_go1.8/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_go1.8/build_interop.sh
new file mode 100644
index 0000000000..5eca90cdea
--- /dev/null
+++ b/tools/dockerfile/interoptest/grpc_interop_go1.8/build_interop.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Builds Go interop server and client in a base image.
+set -e
+
+# Clone just the grpc-go source code without any dependencies.
+# We are cloning from a local git repo that contains the right revision
+# to test instead of using "go get" to download from Github directly.
+git clone --recursive /var/local/jenkins/grpc-go src/google.golang.org/grpc
+
+# Get all gRPC Go dependencies
+(cd src/google.golang.org/grpc && make deps && make testdeps)
+
+# copy service account keys if available
+cp -r /var/local/jenkins/service_account $HOME || true
+
+# Build the interop client and server
+(cd src/google.golang.org/grpc/interop/client && go install)
+(cd src/google.golang.org/grpc/interop/server && go install)
+
diff --git a/tools/dockerfile/push_testing_images.sh b/tools/dockerfile/push_testing_images.sh
index 973e045ffe..c9e61958af 100755
--- a/tools/dockerfile/push_testing_images.sh
+++ b/tools/dockerfile/push_testing_images.sh
@@ -44,7 +44,7 @@ cd -
DOCKERHUB_ORGANIZATION=grpctesting
-for DOCKERFILE_DIR in tools/dockerfile/test/*
+for DOCKERFILE_DIR in tools/dockerfile/test/* tools/dockerfile/grpc_artifact_* tools/dockerfile/interoptest/*
do
# Generate image name based on Dockerfile checksum. That works well as long
# as can count on dockerfiles being written in a way that changing the logical
diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++
index b7531bc276..b6f2857b39 100644
--- a/tools/doxygen/Doxyfile.c++
+++ b/tools/doxygen/Doxyfile.c++
@@ -794,6 +794,7 @@ doc/statuscodes.md \
doc/stress_test_framework.md \
doc/unit_testing.md \
doc/wait-for-ready.md \
+doc/workarounds.md \
include/grpc++/alarm.h \
include/grpc++/channel.h \
include/grpc++/client_context.h \
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 5bae9fad9b..5242172f96 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -794,6 +794,7 @@ doc/statuscodes.md \
doc/stress_test_framework.md \
doc/unit_testing.md \
doc/wait-for-ready.md \
+doc/workarounds.md \
include/grpc++/alarm.h \
include/grpc++/channel.h \
include/grpc++/client_context.h \
@@ -955,6 +956,7 @@ src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_poll_posix.h \
src/core/lib/iomgr/ev_posix.c \
src/core/lib/iomgr/ev_posix.h \
+src/core/lib/iomgr/ev_windows.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/exec_ctx.h \
src/core/lib/iomgr/executor.c \
diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core
index 74e76bfce9..c5ae421d40 100644
--- a/tools/doxygen/Doxyfile.core
+++ b/tools/doxygen/Doxyfile.core
@@ -794,6 +794,7 @@ doc/statuscodes.md \
doc/stress_test_framework.md \
doc/unit_testing.md \
doc/wait-for-ready.md \
+doc/workarounds.md \
include/grpc/byte_buffer.h \
include/grpc/byte_buffer_reader.h \
include/grpc/census.h \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 597f22b634..eb0883b797 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -794,6 +794,7 @@ doc/statuscodes.md \
doc/stress_test_framework.md \
doc/unit_testing.md \
doc/wait-for-ready.md \
+doc/workarounds.md \
include/grpc/byte_buffer.h \
include/grpc/byte_buffer_reader.h \
include/grpc/census.h \
@@ -1098,6 +1099,7 @@ src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_poll_posix.h \
src/core/lib/iomgr/ev_posix.c \
src/core/lib/iomgr/ev_posix.h \
+src/core/lib/iomgr/ev_windows.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/exec_ctx.h \
src/core/lib/iomgr/executor.c \
diff --git a/tools/gcp/utils/gcr_upload.py b/tools/gcp/utils/gcr_upload.py
deleted file mode 100755
index b22f8731f6..0000000000
--- a/tools/gcp/utils/gcr_upload.py
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/env python2.7
-# Copyright 2017, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Upload docker images to Google Container Registry."""
-
-from __future__ import print_function
-
-import argparse
-import atexit
-import os
-import shutil
-import subprocess
-import tempfile
-
-argp = argparse.ArgumentParser(description='Run interop tests.')
-argp.add_argument('--gcr_path',
- default='gcr.io/grpc-testing',
- help='Path of docker images in Google Container Registry')
-
-argp.add_argument('--gcr_tag',
- default='latest',
- help='the tag string for the images to upload')
-
-argp.add_argument('--with_files',
- default=[],
- nargs='+',
- help='additional files to include in the docker image')
-
-argp.add_argument('--with_file_dest',
- default='/var/local/image_info',
- help='Destination directory for with_files inside docker image')
-
-argp.add_argument('--images',
- default=[],
- nargs='+',
- help='local docker images in the form of repo:tag ' +
- '(i.e. grpc_interop_java:26328ad8) to upload')
-
-argp.add_argument('--keep',
- action='store_true',
- help='keep the created local images after uploading to GCR')
-
-
-args = argp.parse_args()
-
-def upload_to_gcr(image):
- """Tags and Pushes a docker image in Google Containger Registry.
-
- image: docker image name, i.e. grpc_interop_java:26328ad8
-
- A docker image image_foo:tag_old will be uploaded as
- <gcr_path>/image_foo:<gcr_tag>
- after inserting extra with_files under with_file_dest in the image. The
- original image name will be stored as label original_name:"image_foo:tag_old".
- """
- tag_idx = image.find(':')
- if tag_idx == -1:
- print('Failed to parse docker image name %s' % image)
- return False
- new_tag = '%s/%s:%s' % (args.gcr_path, image[:tag_idx], args.gcr_tag)
-
- lines = ['FROM ' + image]
- lines.append('LABEL original_name="%s"' % image)
-
- temp_dir = tempfile.mkdtemp()
- atexit.register(lambda: subprocess.call(['rm', '-rf', temp_dir]))
-
- # Copy with_files inside the tmp directory, which will be the docker build
- # context.
- for f in args.with_files:
- shutil.copy(f, temp_dir)
- lines.append('COPY %s %s/' % (os.path.basename(f), args.with_file_dest))
-
- # Create a Dockerfile.
- with open(os.path.join(temp_dir, 'Dockerfile'), 'w') as f:
- f.write('\n'.join(lines))
-
- build_cmd = ['docker', 'build', '--rm', '--tag', new_tag, temp_dir]
- subprocess.check_output(build_cmd)
-
- if not args.keep:
- atexit.register(lambda: subprocess.call(['docker', 'rmi', new_tag]))
-
- # Upload to GCR.
- if args.gcr_path:
- subprocess.call(['gcloud', 'docker', '--', 'push', new_tag])
-
- return True
-
-
-for image in args.images:
- upload_to_gcr(image)
diff --git a/tools/internal_ci/helper_scripts/prepare_build_interop_rc b/tools/internal_ci/helper_scripts/prepare_build_interop_rc
new file mode 100644
index 0000000000..c988cadb71
--- /dev/null
+++ b/tools/internal_ci/helper_scripts/prepare_build_interop_rc
@@ -0,0 +1,43 @@
+#!/bin/bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Source this rc script to prepare the environment for interop builds
+# This rc script must be used in the root directory of gRPC
+
+export LANG=en_US.UTF-8
+
+# Download Docker images from DockerHub
+export DOCKERHUB_ORGANIZATION=grpctesting
+
+git submodule update --init
+
+# Set up gRPC-Go and gRPC-Java to test
+git clone --recursive https://github.com/grpc/grpc-go ./../grpc-go
+git clone --recursive https://github.com/grpc/grpc-java ./../grpc-java
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_java.cfg b/tools/internal_ci/linux/grpc_interop_badserver_java.cfg
index e521b085c5..8a149ac20b 100644
--- a/tools/internal_ci/linux/grpc_interop_badserver_java.cfg
+++ b/tools/internal_ci/linux/grpc_interop_badserver_java.cfg
@@ -35,6 +35,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_interop_badserver_java.sh"
timeout_mins: 480
action {
define_artifacts {
- regex: "**/report.xml"
+ regex: "**/report.xml",
+ regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_java.sh b/tools/internal_ci/linux/grpc_interop_badserver_java.sh
index 02d7b9d431..f5f89f35d1 100755
--- a/tools/internal_ci/linux/grpc_interop_badserver_java.sh
+++ b/tools/internal_ci/linux/grpc_interop_badserver_java.sh
@@ -36,6 +36,7 @@ export LANG=en_US.UTF-8
cd $(dirname $0)/../../..
source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+source tools/internal_ci/helper_scripts/prepare_build_interop_rc
-tools/run_tests/run_interop_tests.py -l java --use_docker --http2_server_interop $@
+tools/run_tests/run_interop_tests.py -l java --use_docker --http2_server_interop
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_python.cfg b/tools/internal_ci/linux/grpc_interop_badserver_python.cfg
index 940f760e97..15aaf04627 100644
--- a/tools/internal_ci/linux/grpc_interop_badserver_python.cfg
+++ b/tools/internal_ci/linux/grpc_interop_badserver_python.cfg
@@ -35,6 +35,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_interop_badserver_python.sh"
timeout_mins: 480
action {
define_artifacts {
- regex: "**/report.xml"
+ regex: "**/report.xml",
+ regex: "github/grpc/reports/**"
}
}
diff --git a/tools/internal_ci/linux/grpc_interop_badserver_python.sh b/tools/internal_ci/linux/grpc_interop_badserver_python.sh
index 3ceb181d90..0a664aca86 100755
--- a/tools/internal_ci/linux/grpc_interop_badserver_python.sh
+++ b/tools/internal_ci/linux/grpc_interop_badserver_python.sh
@@ -36,6 +36,7 @@ export LANG=en_US.UTF-8
cd $(dirname $0)/../../..
source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+source tools/internal_ci/helper_scripts/prepare_build_interop_rc
-tools/run_tests/run_interop_tests.py -l python --use_docker --http2_server_interop $@
+tools/run_tests/run_interop_tests.py -l python --use_docker --http2_server_interop
diff --git a/tools/internal_ci/linux/grpc_interop_tocloud.sh b/tools/internal_ci/linux/grpc_interop_tocloud.sh
index a3067e70e6..3c5f81f686 100755
--- a/tools/internal_ci/linux/grpc_interop_tocloud.sh
+++ b/tools/internal_ci/linux/grpc_interop_tocloud.sh
@@ -36,5 +36,6 @@ export LANG=en_US.UTF-8
cd $(dirname $0)/../../..
source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+source tools/internal_ci/helper_scripts/prepare_build_interop_rc
tools/run_tests/run_interop_tests.py -l all -s all --use_docker --http2_interop -t -j 12 $@
diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg
new file mode 100644
index 0000000000..385ec278e6
--- /dev/null
+++ b/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg
@@ -0,0 +1,39 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.sh"
+timeout_mins: 1440
+action {
+ define_artifacts {
+ regex: "**/*sponge_log.xml"
+ }
+}
diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.sh b/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.sh
new file mode 100755
index 0000000000..27e4a10282
--- /dev/null
+++ b/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../../../..
+
+source tools/internal_ci/helper_scripts/prepare_build_linux_rc
+
+tools/run_tests/run_tests_matrix.py -f c ubsan --inner_jobs 16 -j 1 --internal_ci
diff --git a/tools/internal_ci/macos/grpc_interop.cfg b/tools/internal_ci/macos/grpc_interop.cfg
new file mode 100644
index 0000000000..e3e782bfd8
--- /dev/null
+++ b/tools/internal_ci/macos/grpc_interop.cfg
@@ -0,0 +1,40 @@
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Config file for the internal CI (in protobuf text format)
+
+# Location of the continuous shell script in repository.
+build_file: "grpc/tools/internal_ci/macos/grpc_interop.sh"
+timeout_mins: 240
+action {
+ define_artifacts {
+ regex: "**/*sponge_log.xml",
+ regex: "github/grpc/reports/**"
+ }
+}
diff --git a/tools/internal_ci/macos/grpc_interop.sh b/tools/internal_ci/macos/grpc_interop.sh
new file mode 100755
index 0000000000..4b68266f74
--- /dev/null
+++ b/tools/internal_ci/macos/grpc_interop.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../../..
+
+source tools/internal_ci/helper_scripts/prepare_build_interop_rc
+
+tools/run_tests/run_interop_tests.py -l objc -s all --use_docker -t -j 1
diff --git a/tools/interop_matrix/README.md b/tools/interop_matrix/README.md
new file mode 100644
index 0000000000..8493099d1a
--- /dev/null
+++ b/tools/interop_matrix/README.md
@@ -0,0 +1,40 @@
+# Overview
+
+This directory contains scripts that facilitate building and running gRPC tests for combinations of language/runtimes (known as matrix).
+
+The setup builds gRPC docker images for each language/runtime and upload it to Google Container Registry (GCR). These images, encapsulating gRPC stack
+from specific releases/tag, are used to test version compatiblity between gRPC release versions.
+
+## Instructions for creating GCR images
+- Edit `./client_matrix.py` to include desired gRPC release.
+- Run `tools/interop_matrix/create_matrix_images.py`. Useful options:
+ - `--git_checkout` enables git checkout grpc release branch/tag.
+ - `--release` specifies a git release tag. Make sure it is a valid tag in the grpc github rep.
+ - `--language` specifies a language.
+ For examle, To build all languages for all gRPC releases across all runtimes, do `tools/interop_matrix/create_matrix_images.py --git_checkout --release=all`.
+- Verify the newly created docker images are uploaded to GCR. For example:
+ - `gcloud beta container images list --repository gcr.io/grpc-testing` shows image repos.
+ - `gcloud beta container images list-tags gcr.io/grpc-testing/grpc_interop_go1.7` show tags for a image repo.
+
+## Instructions for adding new language/runtimes*
+- Create new `Dockerfile.template`, `build_interop.sh.template` for the language/runtime under `template/tools/dockerfile/`.
+- Run `tools/buildgen/generate_projects.sh` to create corresponding files under `tools/dockerfile/`.
+- Add language/runtimes to `client_matrix.py` following existing language/runtimes examples.
+- Run `tools/interop_matrix/create_matrix_images.py` which will build and upload images to GCR. Unless you are also building images for a gRPC release, make sure not to set `--gcr_tag` (the default tag 'master' is used for testing).
+
+*: Please delete your docker images at https://pantheon.corp.google.com/gcr/images/grpc-testing?project=grpc-testing afterwards. Permissions to access GrpcTesting project is required for this step.
+
+## Instructions for creating new test cases
+- Create test cases by running `LANG=<lang> [RELEASE=<release>] ./create_testcases.sh`. For example,
+ - `LANG=go ./create_testcases.sh` will generate `./testcases/go__master`, which is also a functional bash script.
+ - `LANG=go KEEP_IMAGE=1 ./create_testcases.sh` will generate `./testcases/go__master` and keep the local docker image so it can be invoked simply via `./testcases/go__master`. Note: remove local docker images manually afterwards with `docker rmi <image_id>`.
+- Stage and commit the generated test case file `./testcases/<lang>__<release>`.
+
+## Instructions for running test cases against a GCR image
+- Run test cases by specifying `docker_image` variable inline with the test case script created above.
+For example:
+ - `docker_image=gcr.io/grpc-testing/grpc_interop_go1.7:master ./testcases/go__master` will run go__master test cases against `go1.7` with gRPC release `master` docker image in GCR.
+
+
+Note:
+- File path starting with `tools/` or `template/` are relative to the grpc repo root dir. File path starting with `./` are relative to current directory (`tools/interop_matrix`).
diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py
new file mode 100644
index 0000000000..b06b0b7205
--- /dev/null
+++ b/tools/interop_matrix/client_matrix.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python2.7
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Dictionaries used for client matrix testing.
+
+def get_github_repo(lang):
+ return {
+ 'go': 'git@github.com:grpc/grpc-go.git',
+ 'java': 'git@github.com:grpc/grpc-java.git',
+ }.get(lang, 'git@github.com:grpc/grpc.git')
+
+# Dictionary of runtimes per language
+LANG_RUNTIME_MATRIX = {
+ 'go': ['go1.7', 'go1.8'],
+}
+
+# Dictionary of releases per language. For each language, we need to provide
+# a tuple of release tag (used as the tag for the GCR image) and also github hash.
+LANG_RELEASE_MATRIX = {
+ 'go': ['v1.0.1-GA', 'v1.3.0'],
+}
diff --git a/tools/interop_matrix/create_matrix_images.py b/tools/interop_matrix/create_matrix_images.py
new file mode 100755
index 0000000000..582b4cccfc
--- /dev/null
+++ b/tools/interop_matrix/create_matrix_images.py
@@ -0,0 +1,272 @@
+#!/usr/bin/env python2.7
+# Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Build and upload docker images to Google Container Registry per matrix."""
+
+from __future__ import print_function
+
+import argparse
+import atexit
+import multiprocessing
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+# Langauage Runtime Matrix
+import client_matrix
+
+python_util_dir = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), '../run_tests/python_utils'))
+sys.path.append(python_util_dir)
+import dockerjob
+import jobset
+
+_IMAGE_BUILDER = 'tools/run_tests/dockerize/build_interop_image.sh'
+_LANGUAGES = client_matrix.LANG_RUNTIME_MATRIX.keys()
+# All gRPC release tags, flattened, deduped and sorted.
+_RELEASES = sorted(list(set(
+ i for l in client_matrix.LANG_RELEASE_MATRIX.values() for i in l)))
+
+# Destination directory inside docker image to keep extra info from build time.
+_BUILD_INFO = '/var/local/build_info'
+
+argp = argparse.ArgumentParser(description='Run interop tests.')
+argp.add_argument('--gcr_path',
+ default='gcr.io/grpc-testing',
+ help='Path of docker images in Google Container Registry')
+
+argp.add_argument('--release',
+ default='master',
+ choices=['all', 'master'] + _RELEASES,
+ help='github commit tag to checkout. When building all '
+ 'releases defined in client_matrix.py, use "all". Valid only '
+ 'with --git_checkout.')
+
+argp.add_argument('-l', '--language',
+ choices=['all'] + sorted(_LANGUAGES),
+ nargs='+',
+ default=['all'],
+ help='Test languages to build docker images for.')
+
+argp.add_argument('--git_checkout',
+ action='store_true',
+ help='Use a separate git clone tree for building grpc stack. '
+ 'Required when using --release flag. By default, current'
+ 'tree and the sibling will be used for building grpc stack.')
+
+argp.add_argument('--git_checkout_root',
+ default='/export/hda3/tmp/grpc_matrix',
+ help='Directory under which grpc-go/java/main repo will be '
+ 'cloned. Valid only with --git_checkout.')
+
+argp.add_argument('--keep',
+ action='store_true',
+ help='keep the created local images after uploading to GCR')
+
+
+args = argp.parse_args()
+
+def add_files_to_image(image, with_files, label=None):
+ """Add files to a docker image.
+
+ image: docker image name, i.e. grpc_interop_java:26328ad8
+ with_files: additional files to include in the docker image.
+ label: label string to attach to the image.
+ """
+ tag_idx = image.find(':')
+ if tag_idx == -1:
+ jobset.message('FAILED', 'invalid docker image %s' % image, do_newline=True)
+ sys.exit(1)
+ orig_tag = '%s_' % image
+ subprocess.check_output(['docker', 'tag', image, orig_tag])
+
+ lines = ['FROM ' + orig_tag]
+ if label:
+ lines.append('LABEL %s' % label)
+
+ temp_dir = tempfile.mkdtemp()
+ atexit.register(lambda: subprocess.call(['rm', '-rf', temp_dir]))
+
+ # Copy with_files inside the tmp directory, which will be the docker build
+ # context.
+ for f in with_files:
+ shutil.copy(f, temp_dir)
+ lines.append('COPY %s %s/' % (os.path.basename(f), _BUILD_INFO))
+
+ # Create a Dockerfile.
+ with open(os.path.join(temp_dir, 'Dockerfile'), 'w') as f:
+ f.write('\n'.join(lines))
+
+ jobset.message('START', 'Repackaging %s' % image, do_newline=True)
+ build_cmd = ['docker', 'build', '--rm', '--tag', image, temp_dir]
+ subprocess.check_output(build_cmd)
+ dockerjob.remove_image(orig_tag, skip_nonexistent=True)
+
+def build_image_jobspec(runtime, env, gcr_tag):
+ """Build interop docker image for a language with runtime.
+
+ runtime: a <lang><version> string, for example go1.8.
+ env: dictionary of env to passed to the build script.
+ gcr_tag: the tag for the docker image (i.e. v1.3.0).
+ """
+ basename = 'grpc_interop_%s' % runtime
+ tag = '%s/%s:%s' % (args.gcr_path, basename, gcr_tag)
+ build_env = {
+ 'INTEROP_IMAGE': tag,
+ 'BASE_NAME': basename,
+ 'TTY_FLAG': '-t'
+ }
+ build_env.update(env)
+ build_job = jobset.JobSpec(
+ cmdline=[_IMAGE_BUILDER],
+ environ=build_env,
+ shortname='build_docker_%s' % runtime,
+ timeout_seconds=30*60)
+ build_job.tag = tag
+ return build_job
+
+def build_all_images_for_lang(lang):
+ """Build all docker images for a language across releases and runtimes."""
+ if not args.git_checkout:
+ if args.release != 'master':
+ print('WARNING: --release is set but will be ignored\n')
+ releases = ['master']
+ else:
+ if args.release == 'all':
+ releases = client_matrix.LANG_RELEASE_MATRIX[lang]
+ else:
+ # Build a particular release.
+ if args.release not in ['master'] + client_matrix.LANG_RELEASE_MATRIX[lang]:
+ jobset.message('SKIPPED',
+ '%s for %s is not defined' % (args.release, lang),
+ do_newline=True)
+ return []
+ releases = [args.release]
+
+ images = []
+ for release in releases:
+ images += build_all_images_for_release(lang, release)
+ jobset.message('SUCCESS',
+ 'All docker images built for %s at %s.' % (lang, releases),
+ do_newline=True)
+ return images
+
+def build_all_images_for_release(lang, release):
+ """Build all docker images for a release across all runtimes."""
+ docker_images = []
+ build_jobs = []
+
+ env = {}
+ # If we not using current tree or the sibling for grpc stack, do checkout.
+ if args.git_checkout:
+ stack_base = checkout_grpc_stack(lang, release)
+ var ={'go': 'GRPC_GO_ROOT', 'java': 'GRPC_JAVA_ROOT'}.get(lang, 'GRPC_ROOT')
+ env[var] = stack_base
+
+ for runtime in client_matrix.LANG_RUNTIME_MATRIX[lang]:
+ job = build_image_jobspec(runtime, env, release)
+ docker_images.append(job.tag)
+ build_jobs.append(job)
+
+ jobset.message('START', 'Building interop docker images.', do_newline=True)
+ print('Jobs to run: \n%s\n' % '\n'.join(str(j) for j in build_jobs))
+
+ num_failures, _ = jobset.run(
+ build_jobs, newline_on_success=True, maxjobs=multiprocessing.cpu_count())
+ if num_failures:
+ jobset.message('FAILED', 'Failed to build interop docker images.',
+ do_newline=True)
+ docker_images_cleanup.extend(docker_images)
+ sys.exit(1)
+
+ jobset.message('SUCCESS',
+ 'All docker images built for %s at %s.' % (lang, release),
+ do_newline=True)
+
+ if release != 'master':
+ commit_log = os.path.join(stack_base, 'commit_log')
+ if os.path.exists(commit_log):
+ for image in docker_images:
+ add_files_to_image(image, [commit_log], 'release=%s' % release)
+ return docker_images
+
+def cleanup():
+ if not args.keep:
+ for image in docker_images_cleanup:
+ dockerjob.remove_image(image, skip_nonexistent=True)
+
+docker_images_cleanup = []
+atexit.register(cleanup)
+
+def checkout_grpc_stack(lang, release):
+ """Invokes 'git check' for the lang/release and returns directory created."""
+ assert args.git_checkout and args.git_checkout_root
+
+ if not os.path.exists(args.git_checkout_root):
+ os.makedirs(args.git_checkout_root)
+
+ repo = client_matrix.get_github_repo(lang)
+ # Get the subdir name part of repo
+ # For example, 'git@github.com:grpc/grpc-go.git' should use 'grpc-go'.
+ repo_dir = os.path.splitext(os.path.basename(repo))[0]
+ stack_base = os.path.join(args.git_checkout_root, repo_dir)
+
+ # Assume the directory is reusable for git checkout.
+ if not os.path.exists(stack_base):
+ subprocess.check_call(['git', 'clone', '--recursive', repo],
+ cwd=os.path.dirname(stack_base))
+
+ # git checkout.
+ jobset.message('START', 'git checkout %s from %s' % (release, stack_base),
+ do_newline=True)
+ # We should NEVER do checkout on current tree !!!
+ assert not os.path.dirname(__file__).startswith(stack_base)
+ output = subprocess.check_output(
+ ['git', 'checkout', release], cwd=stack_base, stderr=subprocess.STDOUT)
+ commit_log = subprocess.check_output(['git', 'log', '-1'], cwd=stack_base)
+ jobset.message('SUCCESS', 'git checkout', output + commit_log, do_newline=True)
+
+ # Write git log to commit_log so it can be packaged with the docker image.
+ with open(os.path.join(stack_base, 'commit_log'), 'w') as f:
+ f.write(commit_log)
+ return stack_base
+
+languages = args.language if args.language != ['all'] else _LANGUAGES
+for lang in languages:
+ docker_images = build_all_images_for_lang(lang)
+ for image in docker_images:
+ jobset.message('START', 'Uploading %s' % image, do_newline=True)
+ # docker image name must be in the format <gcr_path>/<image>:<gcr_tag>
+ assert image.startswith(args.gcr_path) and image.find(':') != -1
+
+ # subprocess.call(['gcloud', 'docker', '--', 'push', image])
+ subprocess.call(['gcloud', 'docker', '--', 'push', image])
diff --git a/tools/interop_matrix/create_testcases.sh b/tools/interop_matrix/create_testcases.sh
new file mode 100755
index 0000000000..cbdd388306
--- /dev/null
+++ b/tools/interop_matrix/create_testcases.sh
@@ -0,0 +1,81 @@
+%#!/bin/bash
+#% Copyright 2017, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Creates test cases for a language by running run_interop_test in manual mode
+# and save the generated output under ./testcases/<lang>__<release>.
+#
+# Params:
+# LANG - The language.
+# SKIP_TEST - If set, skip running the test cases for sanity.
+# RELEASE - Create testcase for specific release, defautl to 'master'.
+# KEEP_IMAGE - Do not clean local docker image created for the test cases.
+
+set -e
+
+cd $(dirname $0)/../..
+GRPC_ROOT=$(pwd)
+CMDS_SH="${GRPC_ROOT}/interop_client_cmds.sh"
+TESTCASES_DIR=${GRPC_ROOT}/tools/interop_matrix/testcases
+
+echo "Create '$LANG' test cases for gRPC release '${RELEASE:=master}'"
+
+# Invoke run_interop_test in manual mode.
+${GRPC_ROOT}/tools/run_tests/run_interop_tests.py -l $LANG --use_docker \
+ --cloud_to_prod --manual_run
+
+# Clean up
+function cleanup {
+ [ -z "$testcase" ] && testcase=$CMDS_SH
+ echo "testcase: $testcase"
+ if [ -e $testcase ]; then
+ # The script should generate a line with "${docker_image:=...}".
+ eval docker_image=$(grep -oe '${docker_image:=.*}' $testcase)
+ if [ -z "$KEEP_IMAGE" ]; then
+ echo "Clean up docker_image $docker_image"
+ docker rmi -f $docker_image
+ else
+ echo "Kept docker_image $docker_image"
+ fi
+ fi
+ [ -e "$CMDS_SH" ] && rm $CMDS_SH
+}
+trap cleanup EXIT
+# Running the testcases as sanity unless we are asked to skip.
+[ -z "$SKIP_TEST" ] && (echo "Running test cases: $CMDS_SH"; sh $CMDS_SH)
+
+mkdir -p $TESTCASES_DIR
+testcase=$TESTCASES_DIR/${LANG}__$RELEASE
+if [ -e $testcase ]; then
+ echo "Updating: $testcase"
+ diff $testcase $CMDS_SH || true
+fi
+mv $CMDS_SH $testcase
+chmod a+x $testcase
+echo "Test cases created: $testcase"
diff --git a/tools/interop_matrix/testcases/go__master b/tools/interop_matrix/testcases/go__master
new file mode 100755
index 0000000000..2624c7f92c
--- /dev/null
+++ b/tools/interop_matrix/testcases/go__master
@@ -0,0 +1,11 @@
+#!/bin/bash
+echo "Testing ${docker_image:=grpc_interop_go:41fffd01-a6c8-41b6-8136-c0aaa1ec2437}"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response"
+docker run -i --rm=true -w /go/src/google.golang.org/grpc/interop/client --net=host $docker_image bash -c "go run client.go --server_host=216.239.32.254 --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server"
diff --git a/tools/profiling/microbenchmarks/bm_json.py b/tools/profiling/microbenchmarks/bm_json.py
index 917269823d..f4d628e11f 100644
--- a/tools/profiling/microbenchmarks/bm_json.py
+++ b/tools/profiling/microbenchmarks/bm_json.py
@@ -54,6 +54,10 @@ _BM_SPECS = {
'tpl': [],
'dyn': ['request_size', 'bandwidth_kilobits'],
},
+ 'BM_PumpUnbalancedUnary_Trickle': {
+ 'tpl': [],
+ 'dyn': ['request_size', 'bandwidth_kilobits'],
+ },
'BM_ErrorStringOnNewError': {
'tpl': ['fixture'],
'dyn': [],
diff --git a/tools/run_tests/artifacts/artifact_targets.py b/tools/run_tests/artifacts/artifact_targets.py
index 5a71b96f9e..e3658acbf6 100644
--- a/tools/run_tests/artifacts/artifact_targets.py
+++ b/tools/run_tests/artifacts/artifact_targets.py
@@ -41,7 +41,7 @@ import python_utils.jobset as jobset
def create_docker_jobspec(name, dockerfile_dir, shell_command, environ={},
flake_retries=0, timeout_retries=0, timeout_seconds=30*60,
- docker_base_image=None):
+ docker_base_image=None, extra_docker_args=None):
"""Creates jobspec for a task running under docker."""
environ = environ.copy()
environ['RUN_COMMAND'] = shell_command
@@ -56,6 +56,8 @@ def create_docker_jobspec(name, dockerfile_dir, shell_command, environ={},
if docker_base_image is not None:
docker_env['DOCKER_BASE_IMAGE'] = docker_base_image
+ if extra_docker_args is not None:
+ docker_env['EXTRA_DOCKER_ARGS'] = extra_docker_args
jobspec = jobset.JobSpec(
cmdline=['tools/run_tests/dockerize/build_and_run_docker.sh'] + docker_args,
environ=docker_env,
@@ -115,7 +117,22 @@ class PythonArtifact:
def build_jobspec(self):
environ = {}
- if self.platform == 'linux':
+ if self.platform == 'linux_extra':
+ # Raspberry Pi build
+ environ['PYTHON'] = '/usr/local/bin/python{}'.format(self.py_version)
+ environ['PIP'] = '/usr/local/bin/pip{}'.format(self.py_version)
+ # https://github.com/resin-io-projects/armv7hf-debian-qemu/issues/9
+ # A QEMU bug causes submodule update to hang, so we copy directly
+ environ['RELATIVE_COPY_PATH'] = '.'
+ extra_args = ' --entrypoint=/usr/bin/qemu-arm-static '
+ return create_docker_jobspec(self.name,
+ 'tools/dockerfile/grpc_artifact_linux_{}'.format(self.arch),
+ 'tools/run_tests/artifacts/build_artifact_python.sh',
+ environ=environ,
+ timeout_seconds=60*60*5,
+ docker_base_image='quay.io/grpc/raspbian_{}'.format(self.arch),
+ extra_docker_args=extra_args)
+ elif self.platform == 'linux':
if self.arch == 'x86':
environ['SETARCH_CMD'] = 'linux32'
# Inside the manylinux container, the python installations are located in
@@ -349,6 +366,14 @@ def targets():
PythonArtifact('linux', 'x86', 'cp34-cp34m'),
PythonArtifact('linux', 'x86', 'cp35-cp35m'),
PythonArtifact('linux', 'x86', 'cp36-cp36m'),
+ PythonArtifact('linux_extra', 'armv7', '2.7'),
+ PythonArtifact('linux_extra', 'armv7', '3.4'),
+ PythonArtifact('linux_extra', 'armv7', '3.5'),
+ PythonArtifact('linux_extra', 'armv7', '3.6'),
+ PythonArtifact('linux_extra', 'armv6', '2.7'),
+ PythonArtifact('linux_extra', 'armv6', '3.4'),
+ PythonArtifact('linux_extra', 'armv6', '3.5'),
+ PythonArtifact('linux_extra', 'armv6', '3.6'),
PythonArtifact('linux', 'x64', 'cp27-cp27m'),
PythonArtifact('linux', 'x64', 'cp27-cp27mu'),
PythonArtifact('linux', 'x64', 'cp34-cp34m'),
diff --git a/tools/run_tests/dockerize/build_and_run_docker.sh b/tools/run_tests/dockerize/build_and_run_docker.sh
index 8c25c861c1..6189e9a5c0 100755
--- a/tools/run_tests/dockerize/build_and_run_docker.sh
+++ b/tools/run_tests/dockerize/build_and_run_docker.sh
@@ -74,8 +74,9 @@ docker run \
-v "$git_root:/var/local/jenkins/grpc:ro" \
-w /var/local/git/grpc \
--name=$CONTAINER_NAME \
+ $EXTRA_DOCKER_ARGS \
$DOCKER_IMAGE_NAME \
- bash -l "/var/local/jenkins/grpc/$DOCKER_RUN_SCRIPT" || FAILED="true"
+ /bin/bash -l "/var/local/jenkins/grpc/$DOCKER_RUN_SCRIPT" || FAILED="true"
# Copy output artifacts
if [ "$OUTPUT_DIR" != "" ]
diff --git a/tools/run_tests/dockerize/build_interop_image.sh b/tools/run_tests/dockerize/build_interop_image.sh
index 3385738f9c..a1c78d7b26 100755
--- a/tools/run_tests/dockerize/build_interop_image.sh
+++ b/tools/run_tests/dockerize/build_interop_image.sh
@@ -39,21 +39,24 @@ set -x
# TTY_FLAG - optional -t flag to make docker allocate tty
# BUILD_INTEROP_DOCKER_EXTRA_ARGS - optional args to be passed to the
# docker run command
+# GRPC_ROOT - grpc base directory, default to top of this tree.
+# GRPC_GO_ROOT - grpc-go base directory, default to '$GRPC_ROOT/../grpc-go'
+# GRPC_JAVA_ROOT - grpc-java base directory, default to '$GRPC_ROOT/../grpc-java'
cd `dirname $0`/../../..
-GRPC_ROOT=`pwd`
+echo "GRPC_ROOT: ${GRPC_ROOT:=$(pwd)}"
MOUNT_ARGS="-v $GRPC_ROOT:/var/local/jenkins/grpc:ro"
-GRPC_JAVA_ROOT=`cd ../grpc-java && pwd`
-if [ "$GRPC_JAVA_ROOT" != "" ]
+echo "GRPC_JAVA_ROOT: ${GRPC_JAVA_ROOT:=$(cd ../grpc-java && pwd)}"
+if [ -n "$GRPC_JAVA_ROOT" ]
then
MOUNT_ARGS+=" -v $GRPC_JAVA_ROOT:/var/local/jenkins/grpc-java:ro"
else
echo "WARNING: grpc-java not found, it won't be mounted to the docker container."
fi
-GRPC_GO_ROOT=`cd ../grpc-go && pwd`
-if [ "$GRPC_GO_ROOT" != "" ]
+echo "GRPC_GO_ROOT: ${GRPC_GO_ROOT:=$(cd ../grpc-go && pwd)}"
+if [ -n "$GRPC_GO_ROOT" ]
then
MOUNT_ARGS+=" -v $GRPC_GO_ROOT:/var/local/jenkins/grpc-go:ro"
else
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index ce65f1d48a..a5d7fda928 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -7969,6 +7969,7 @@
"src/core/lib/iomgr/ev_poll_posix.h",
"src/core/lib/iomgr/ev_posix.c",
"src/core/lib/iomgr/ev_posix.h",
+ "src/core/lib/iomgr/ev_windows.c",
"src/core/lib/iomgr/exec_ctx.c",
"src/core/lib/iomgr/exec_ctx.h",
"src/core/lib/iomgr/executor.c",
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index ae2da26e1f..6da7b85430 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -544,12 +544,14 @@ def docker_run_cmdline(cmdline, image, docker_args=[], cwd=None, environ=None):
return docker_cmdline
-def manual_cmdline(docker_cmdline):
+def manual_cmdline(docker_cmdline, docker_image):
"""Returns docker cmdline adjusted for manual invocation."""
print_cmdline = []
for item in docker_cmdline:
if item.startswith('--name='):
continue
+ if item == docker_image:
+ item = "$docker_image"
# add quotes when necessary
if any(character.isspace() for character in item):
item = "\"%s\"" % item
@@ -644,7 +646,9 @@ def cloud_to_prod_jobspec(language, test_case, server_host_name,
docker_args=['--net=host',
'--name=%s' % container_name])
if manual_cmd_log is not None:
- manual_cmd_log.append(manual_cmdline(cmdline))
+ if manual_cmd_log == []:
+ manual_cmd_log.append('echo "Testing ${docker_image:=%s}"' % docker_image)
+ manual_cmd_log.append(manual_cmdline(cmdline, docker_image))
cwd = None
environ = None
@@ -710,7 +714,9 @@ def cloud_to_cloud_jobspec(language, test_case, server_name, server_host,
docker_args=['--net=host',
'--name=%s' % container_name])
if manual_cmd_log is not None:
- manual_cmd_log.append(manual_cmdline(cmdline))
+ if manual_cmd_log == []:
+ manual_cmd_log.append('echo "Testing ${docker_image:=%s}"' % docker_image)
+ manual_cmd_log.append(manual_cmdline(cmdline, docker_iamge))
cwd = None
test_job = jobset.JobSpec(
@@ -770,7 +776,9 @@ def server_jobspec(language, docker_image, insecure=False, manual_cmd_log=None):
environ=environ,
docker_args=docker_args)
if manual_cmd_log is not None:
- manual_cmd_log.append(manual_cmdline(docker_cmdline))
+ if manual_cmd_log == []:
+ manual_cmd_log.append('echo "Testing ${docker_image:=%s}"' % docker_image)
+ manual_cmd_log.append(manual_cmdline(docker_cmdline, docker_iamge))
server_job = jobset.JobSpec(
cmdline=docker_cmdline,
environ=environ,
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 7b3306d030..882c646126 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -75,8 +75,9 @@ _FORCE_ENVIRON_FOR_WRAPPERS = {
_POLLING_STRATEGIES = {
- 'linux': ['epollsig', 'poll', 'poll-cv']
+ 'linux': ['epollsig', 'poll', 'poll-cv'],
# TODO(ctiller, sreecha): enable epoll1, epollex, epoll-thread-pool
+ 'mac': ['poll'],
}
@@ -1440,6 +1441,9 @@ def _has_epollexclusive():
return True
except subprocess.CalledProcessError, e:
return False
+ except OSError, e:
+ # For languages other than C and Windows the binary won't exist
+ return False
# returns a list of things that failed (or an empty list on success)
@@ -1459,7 +1463,7 @@ def _build_and_run(
suite_name=args.report_suite_name)
return []
- if not args.travis and not _has_epollexclusive() and 'epollex' in _POLLING_STRATEGIES[platform_string()]:
+ if not args.travis and not _has_epollexclusive() and platform_string() in _POLLING_STRATEGIES and 'epollex' in _POLLING_STRATEGIES[platform_string()]:
print('\n\nOmitting EPOLLEXCLUSIVE tests\n\n')
_POLLING_STRATEGIES[platform_string()].remove('epollex')
diff --git a/tools/ubsan_suppressions.txt b/tools/ubsan_suppressions.txt
index f87ed18565..3384efcac9 100644
--- a/tools/ubsan_suppressions.txt
+++ b/tools/ubsan_suppressions.txt
@@ -4,6 +4,5 @@ nonnull-attribute:CBB_add_bytes
nonnull-attribute:rsa_blinding_get
nonnull-attribute:ssl_copy_key_material
alignment:CRYPTO_cbc128_encrypt
-nonnull-attribute:google::protobuf::DescriptorBuilder::BuildFileImpl
-nonnull-attribute:google::protobuf::TextFormat::Printer::TextGenerator::Write
-
+nonnull-attribute:google::protobuf::*
+alignment:google::protobuf::*
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
index 8ee98937b0..ae51c43b13 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
@@ -630,6 +630,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_windows.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
index d601e68560..12eef9494f 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
@@ -202,6 +202,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_windows.c">
+ <Filter>src\core\lib\iomgr</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
index 85ba613a77..bd105366d3 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
@@ -614,6 +614,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_windows.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
index 72e3448c07..f1f4f1729a 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
@@ -187,6 +187,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_windows.c">
+ <Filter>src\core\lib\iomgr</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index 439ce056ea..2ccda23694 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -573,6 +573,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_windows.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index e6407c1a48..3a1c1f9c5a 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -82,6 +82,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_windows.c">
+ <Filter>src\core\lib\iomgr</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
index c6844e5fa8..061fca6d28 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
@@ -403,6 +403,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_windows.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
index 46786d3333..35d0ea0cfd 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
@@ -139,6 +139,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_windows.c">
+ <Filter>src\core\lib\iomgr</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index d611e3e148..d084d70702 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -540,6 +540,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_windows.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\executor.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 39a76e97cf..ba826852a3 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -85,6 +85,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_windows.c">
+ <Filter>src\core\lib\iomgr</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.c">
<Filter>src\core\lib\iomgr</Filter>
</ClCompile>