diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index dbec90aefc9..d103ec92af2 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -2,7 +2,7 @@
name: Report a bug
about: Create a report to help us improve
labels: kind/bug, priority/P2
-assignees: veblush
+assignees: nicolasnoble
---
diff --git a/.github/ISSUE_TEMPLATE/cleanup_request.md b/.github/ISSUE_TEMPLATE/cleanup_request.md
index ef88ef49ac5..284797c9e59 100644
--- a/.github/ISSUE_TEMPLATE/cleanup_request.md
+++ b/.github/ISSUE_TEMPLATE/cleanup_request.md
@@ -2,7 +2,7 @@
name: Request a cleanup
about: Suggest a cleanup in our repository
labels: kind/internal cleanup, priority/P2
-assignees: donnadionne
+assignees: nicolasnoble
---
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index f230fe25a3a..f538eae6194 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -2,7 +2,7 @@
name: Request a feature
about: Suggest an idea for this project
labels: kind/enhancement, priority/P2
-assignees: donnadionne
+assignees: nicolasnoble
---
diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md
index 77ecf5ea984..da5741aa267 100644
--- a/.github/ISSUE_TEMPLATE/question.md
+++ b/.github/ISSUE_TEMPLATE/question.md
@@ -2,7 +2,7 @@
name: Ask a question
about: Ask a question
labels: kind/question, priority/P3
-assignees: donnadionne
+assignees: nicolasnoble
---
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index eddba6676da..57af6c21597 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -8,4 +8,4 @@ If you know who should review your pull request, please remove the mentioning be
-->
-@donnadionne
+@nicolasnoble
diff --git a/BUILD b/BUILD
index 655a1b017b9..32bb6512ec4 100644
--- a/BUILD
+++ b/BUILD
@@ -124,6 +124,7 @@ GRPC_SECURE_PUBLIC_HDRS = [
# TODO(ctiller): layer grpc atop grpc_unsecure, layer grpc++ atop grpc++_unsecure
GRPCXX_SRCS = [
"src/cpp/client/channel_cc.cc",
+ "src/cpp/client/client_callback.cc",
"src/cpp/client/client_context.cc",
"src/cpp/client/client_interceptor.cc",
"src/cpp/client/create_channel.cc",
@@ -1026,6 +1027,7 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/client_channel_channelz.cc",
"src/core/ext/filters/client_channel/client_channel_factory.cc",
"src/core/ext/filters/client_channel/client_channel_plugin.cc",
+ "src/core/ext/filters/client_channel/config_selector.cc",
"src/core/ext/filters/client_channel/global_subchannel_pool.cc",
"src/core/ext/filters/client_channel/health/health_check_client.cc",
"src/core/ext/filters/client_channel/http_connect_handshaker.cc",
@@ -1043,6 +1045,7 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/retry_throttle.cc",
"src/core/ext/filters/client_channel/server_address.cc",
"src/core/ext/filters/client_channel/service_config.cc",
+ "src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc",
"src/core/ext/filters/client_channel/service_config_parser.cc",
"src/core/ext/filters/client_channel/subchannel.cc",
"src/core/ext/filters/client_channel/subchannel_pool_interface.cc",
@@ -1053,6 +1056,7 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/client_channel.h",
"src/core/ext/filters/client_channel/client_channel_channelz.h",
"src/core/ext/filters/client_channel/client_channel_factory.h",
+ "src/core/ext/filters/client_channel/config_selector.h",
"src/core/ext/filters/client_channel/connector.h",
"src/core/ext/filters/client_channel/global_subchannel_pool.h",
"src/core/ext/filters/client_channel/health/health_check_client.h",
@@ -1183,6 +1187,7 @@ grpc_cc_library(
language = "c++",
deps = [
"grpc_base",
+ "grpc_message_size_filter",
],
)
diff --git a/BUILD.gn b/BUILD.gn
index e444c251c08..f2e173ad9c5 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -211,6 +211,8 @@ config("grpc_config") {
"src/core/ext/filters/client_channel/client_channel_factory.cc",
"src/core/ext/filters/client_channel/client_channel_factory.h",
"src/core/ext/filters/client_channel/client_channel_plugin.cc",
+ "src/core/ext/filters/client_channel/config_selector.cc",
+ "src/core/ext/filters/client_channel/config_selector.h",
"src/core/ext/filters/client_channel/connector.h",
"src/core/ext/filters/client_channel/global_subchannel_pool.cc",
"src/core/ext/filters/client_channel/global_subchannel_pool.h",
@@ -293,6 +295,7 @@ config("grpc_config") {
"src/core/ext/filters/client_channel/service_config.cc",
"src/core/ext/filters/client_channel/service_config.h",
"src/core/ext/filters/client_channel/service_config_call_data.h",
+ "src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc",
"src/core/ext/filters/client_channel/service_config_parser.cc",
"src/core/ext/filters/client_channel/service_config_parser.h",
"src/core/ext/filters/client_channel/subchannel.cc",
@@ -1219,6 +1222,7 @@ config("grpc_config") {
"include/grpcpp/support/time.h",
"include/grpcpp/support/validate_service_config.h",
"src/cpp/client/channel_cc.cc",
+ "src/cpp/client/client_callback.cc",
"src/cpp/client/client_context.cc",
"src/cpp/client/client_interceptor.cc",
"src/cpp/client/create_channel.cc",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aabacf1cc0b..3fa1c7bb8c1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -26,8 +26,8 @@ cmake_minimum_required(VERSION 3.5.1)
set(PACKAGE_NAME "grpc")
set(PACKAGE_VERSION "1.31.0-dev")
-set(gRPC_CORE_VERSION "10.0.0")
-set(gRPC_CORE_SOVERSION "10")
+set(gRPC_CORE_VERSION "11.0.0")
+set(gRPC_CORE_SOVERSION "11")
set(gRPC_CPP_VERSION "1.31.0-dev")
set(gRPC_CPP_SOVERSION "1")
set(gRPC_CSHARP_VERSION "2.31.0-dev")
@@ -569,7 +569,6 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_c secure_endpoint_test)
add_dependencies(buildtests_c security_connector_test)
add_dependencies(buildtests_c sequential_connectivity_test)
- add_dependencies(buildtests_c server_chttp2_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c server_ssl_test)
endif()
@@ -793,6 +792,7 @@ if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx server_builder_with_socket_mutator_test)
endif()
+ add_dependencies(buildtests_cxx server_chttp2_test)
add_dependencies(buildtests_cxx server_context_test_spouse_test)
add_dependencies(buildtests_cxx server_early_return_test)
add_dependencies(buildtests_cxx server_interceptors_end2end_test)
@@ -1328,6 +1328,7 @@ add_library(grpc
src/core/ext/filters/client_channel/client_channel_channelz.cc
src/core/ext/filters/client_channel/client_channel_factory.cc
src/core/ext/filters/client_channel/client_channel_plugin.cc
+ src/core/ext/filters/client_channel/config_selector.cc
src/core/ext/filters/client_channel/global_subchannel_pool.cc
src/core/ext/filters/client_channel/health/health_check_client.cc
src/core/ext/filters/client_channel/http_connect_handshaker.cc
@@ -1375,6 +1376,7 @@ add_library(grpc
src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/service_config.cc
+ src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
src/core/ext/filters/client_channel/service_config_parser.cc
src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc
@@ -1999,6 +2001,7 @@ add_library(grpc_unsecure
src/core/ext/filters/client_channel/client_channel_channelz.cc
src/core/ext/filters/client_channel/client_channel_factory.cc
src/core/ext/filters/client_channel/client_channel_plugin.cc
+ src/core/ext/filters/client_channel/config_selector.cc
src/core/ext/filters/client_channel/global_subchannel_pool.cc
src/core/ext/filters/client_channel/health/health_check_client.cc
src/core/ext/filters/client_channel/http_connect_handshaker.cc
@@ -2046,6 +2049,7 @@ add_library(grpc_unsecure
src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/service_config.cc
+ src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
src/core/ext/filters/client_channel/service_config_parser.cc
src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc
@@ -2482,6 +2486,7 @@ endif()
add_library(grpc++
src/cpp/client/channel_cc.cc
+ src/cpp/client/client_callback.cc
src/cpp/client/client_context.cc
src/cpp/client/client_interceptor.cc
src/cpp/client/create_channel.cc
@@ -3182,6 +3187,7 @@ endif()
add_library(grpc++_unsecure
src/cpp/client/channel_cc.cc
+ src/cpp/client/client_callback.cc
src/cpp/client/client_context.cc
src/cpp/client/client_interceptor.cc
src/cpp/client/create_channel.cc
@@ -6826,35 +6832,6 @@ target_link_libraries(sequential_connectivity_test
)
-endif()
-if(gRPC_BUILD_TESTS)
-
-add_executable(server_chttp2_test
- test/core/surface/server_chttp2_test.cc
-)
-
-target_include_directories(server_chttp2_test
- PRIVATE
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/include
- ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
- ${_gRPC_SSL_INCLUDE_DIR}
- ${_gRPC_UPB_GENERATED_DIR}
- ${_gRPC_UPB_GRPC_GENERATED_DIR}
- ${_gRPC_UPB_INCLUDE_DIR}
- ${_gRPC_ZLIB_INCLUDE_DIR}
-)
-
-target_link_libraries(server_chttp2_test
- ${_gRPC_ALLTARGETS_LIBRARIES}
- grpc_test_util
- grpc
- gpr
- address_sorting
- upb
-)
-
-
endif()
if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@@ -13000,6 +12977,44 @@ endif()
endif()
if(gRPC_BUILD_TESTS)
+add_executable(server_chttp2_test
+ test/core/surface/server_chttp2_test.cc
+ third_party/googletest/googletest/src/gtest-all.cc
+ third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+target_include_directories(server_chttp2_test
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+ ${_gRPC_SSL_INCLUDE_DIR}
+ ${_gRPC_UPB_GENERATED_DIR}
+ ${_gRPC_UPB_GRPC_GENERATED_DIR}
+ ${_gRPC_UPB_INCLUDE_DIR}
+ ${_gRPC_ZLIB_INCLUDE_DIR}
+ third_party/googletest/googletest/include
+ third_party/googletest/googletest
+ third_party/googletest/googlemock/include
+ third_party/googletest/googlemock
+ ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(server_chttp2_test
+ ${_gRPC_PROTOBUF_LIBRARIES}
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ grpc_test_util
+ grpc
+ gpr
+ address_sorting
+ upb
+ ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+
+endif()
+if(gRPC_BUILD_TESTS)
+
add_executable(server_context_test_spouse_test
test/cpp/test/server_context_test_spouse_test.cc
third_party/googletest/googletest/src/gtest-all.cc
@@ -15122,7 +15137,7 @@ include(CMakePackageConfigHelpers)
configure_file(cmake/gRPCConfig.cmake.in
gRPCConfig.cmake @ONLY)
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/gRPCConfigVersion.cmake
- VERSION ${PACKAGE_VERSION}
+ VERSION ${gRPC_CPP_VERSION}
COMPATIBILITY AnyNewerVersion)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/gRPCConfig.cmake
@@ -15189,7 +15204,7 @@ generate_pkgconfig(
generate_pkgconfig(
"gRPC++"
"C++ wrapper for gRPC"
- "${PACKAGE_VERSION}"
+ "${gRPC_CPP_VERSION}"
"grpc"
"-lgrpc++ -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
""
@@ -15199,7 +15214,7 @@ generate_pkgconfig(
generate_pkgconfig(
"gRPC++ unsecure"
"C++ wrapper for gRPC without SSL"
- "${PACKAGE_VERSION}"
+ "${gRPC_CPP_VERSION}"
"grpc_unsecure"
"-lgrpc++_unsecure -labsl_bad_optional_access -labsl_str_format_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity -labsl_dynamic_annotations"
""
diff --git a/Makefile b/Makefile
index 75fab892c73..675c7613d50 100644
--- a/Makefile
+++ b/Makefile
@@ -469,7 +469,7 @@ E = @echo
Q = @
endif
-CORE_VERSION = 10.0.0
+CORE_VERSION = 11.0.0
CPP_VERSION = 1.31.0-dev
CSHARP_VERSION = 2.31.0-dev
@@ -519,7 +519,7 @@ SHARED_EXT_CORE = dll
SHARED_EXT_CPP = dll
SHARED_EXT_CSHARP = dll
SHARED_PREFIX =
-SHARED_VERSION_CORE = -10
+SHARED_VERSION_CORE = -11
SHARED_VERSION_CPP = -1
SHARED_VERSION_CSHARP = -2
else ifeq ($(SYSTEM),Darwin)
@@ -1112,7 +1112,6 @@ secure_channel_create_test: $(BINDIR)/$(CONFIG)/secure_channel_create_test
secure_endpoint_test: $(BINDIR)/$(CONFIG)/secure_endpoint_test
security_connector_test: $(BINDIR)/$(CONFIG)/security_connector_test
sequential_connectivity_test: $(BINDIR)/$(CONFIG)/sequential_connectivity_test
-server_chttp2_test: $(BINDIR)/$(CONFIG)/server_chttp2_test
server_ssl_test: $(BINDIR)/$(CONFIG)/server_ssl_test
server_test: $(BINDIR)/$(CONFIG)/server_test
slice_buffer_test: $(BINDIR)/$(CONFIG)/slice_buffer_test
@@ -1269,6 +1268,7 @@ secure_auth_context_test: $(BINDIR)/$(CONFIG)/secure_auth_context_test
server_builder_plugin_test: $(BINDIR)/$(CONFIG)/server_builder_plugin_test
server_builder_test: $(BINDIR)/$(CONFIG)/server_builder_test
server_builder_with_socket_mutator_test: $(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test
+server_chttp2_test: $(BINDIR)/$(CONFIG)/server_chttp2_test
server_context_test_spouse_test: $(BINDIR)/$(CONFIG)/server_context_test_spouse_test
server_early_return_test: $(BINDIR)/$(CONFIG)/server_early_return_test
server_fuzzer: $(BINDIR)/$(CONFIG)/server_fuzzer
@@ -1487,7 +1487,6 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/secure_endpoint_test \
$(BINDIR)/$(CONFIG)/security_connector_test \
$(BINDIR)/$(CONFIG)/sequential_connectivity_test \
- $(BINDIR)/$(CONFIG)/server_chttp2_test \
$(BINDIR)/$(CONFIG)/server_ssl_test \
$(BINDIR)/$(CONFIG)/server_test \
$(BINDIR)/$(CONFIG)/slice_buffer_test \
@@ -1631,6 +1630,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/server_builder_plugin_test \
$(BINDIR)/$(CONFIG)/server_builder_test \
$(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test \
+ $(BINDIR)/$(CONFIG)/server_chttp2_test \
$(BINDIR)/$(CONFIG)/server_context_test_spouse_test \
$(BINDIR)/$(CONFIG)/server_early_return_test \
$(BINDIR)/$(CONFIG)/server_interceptors_end2end_test \
@@ -1788,6 +1788,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/server_builder_plugin_test \
$(BINDIR)/$(CONFIG)/server_builder_test \
$(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test \
+ $(BINDIR)/$(CONFIG)/server_chttp2_test \
$(BINDIR)/$(CONFIG)/server_context_test_spouse_test \
$(BINDIR)/$(CONFIG)/server_early_return_test \
$(BINDIR)/$(CONFIG)/server_interceptors_end2end_test \
@@ -2043,8 +2044,6 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/secure_endpoint_test || ( echo test secure_endpoint_test failed ; exit 1 )
$(E) "[RUN] Testing security_connector_test"
$(Q) $(BINDIR)/$(CONFIG)/security_connector_test || ( echo test security_connector_test failed ; exit 1 )
- $(E) "[RUN] Testing server_chttp2_test"
- $(Q) $(BINDIR)/$(CONFIG)/server_chttp2_test || ( echo test server_chttp2_test failed ; exit 1 )
$(E) "[RUN] Testing server_ssl_test"
$(Q) $(BINDIR)/$(CONFIG)/server_ssl_test || ( echo test server_ssl_test failed ; exit 1 )
$(E) "[RUN] Testing server_test"
@@ -2299,6 +2298,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/server_builder_test || ( echo test server_builder_test failed ; exit 1 )
$(E) "[RUN] Testing server_builder_with_socket_mutator_test"
$(Q) $(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test || ( echo test server_builder_with_socket_mutator_test failed ; exit 1 )
+ $(E) "[RUN] Testing server_chttp2_test"
+ $(Q) $(BINDIR)/$(CONFIG)/server_chttp2_test || ( echo test server_chttp2_test failed ; exit 1 )
$(E) "[RUN] Testing server_context_test_spouse_test"
$(Q) $(BINDIR)/$(CONFIG)/server_context_test_spouse_test || ( echo test server_context_test_spouse_test failed ; exit 1 )
$(E) "[RUN] Testing server_early_return_test"
@@ -3042,7 +3043,7 @@ install-shared_c: shared_c strip-shared_c install-pkg-config_c
ifeq ($(SYSTEM),MINGW32)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libaddress_sorting.a
else ifneq ($(SYSTEM),Darwin)
- $(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libaddress_sorting.so.10
+ $(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libaddress_sorting.so.11
$(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libaddress_sorting.so
endif
$(E) "[INSTALL] Installing $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -3051,7 +3052,7 @@ endif
ifeq ($(SYSTEM),MINGW32)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgpr.a
else ifneq ($(SYSTEM),Darwin)
- $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so.10
+ $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so.11
$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so
endif
$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -3060,7 +3061,7 @@ endif
ifeq ($(SYSTEM),MINGW32)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc.a
else ifneq ($(SYSTEM),Darwin)
- $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so.10
+ $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so.11
$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so
endif
$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -3069,7 +3070,7 @@ endif
ifeq ($(SYSTEM),MINGW32)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc_csharp_ext.a
else ifneq ($(SYSTEM),Darwin)
- $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_csharp_ext.so.10
+ $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_csharp_ext.so.11
$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_csharp_ext.so
endif
$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -3078,7 +3079,7 @@ endif
ifeq ($(SYSTEM),MINGW32)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc_unsecure.a
else ifneq ($(SYSTEM),Darwin)
- $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so.10
+ $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so.11
$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so
endif
$(E) "[INSTALL] Installing $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)"
@@ -3087,7 +3088,7 @@ endif
ifeq ($(SYSTEM),MINGW32)
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libupb.a
else ifneq ($(SYSTEM),Darwin)
- $(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libupb.so.10
+ $(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libupb.so.11
$(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libupb.so
endif
ifneq ($(SYSTEM),MINGW32)
@@ -3248,8 +3249,8 @@ $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE):
ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBADDRESS_SORTING_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
else
- $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libaddress_sorting.so.10 -o $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBADDRESS_SORTING_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
- $(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).so.10
+ $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libaddress_sorting.so.11 -o $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBADDRESS_SORTING_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
+ $(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).so.11
$(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).so
endif
endif
@@ -3610,8 +3611,8 @@ $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OB
ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
else
- $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.10 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
- $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.10
+ $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.11 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
+ $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.11
$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so
endif
endif
@@ -3630,6 +3631,7 @@ LIBGRPC_SRC = \
src/core/ext/filters/client_channel/client_channel_channelz.cc \
src/core/ext/filters/client_channel/client_channel_factory.cc \
src/core/ext/filters/client_channel/client_channel_plugin.cc \
+ src/core/ext/filters/client_channel/config_selector.cc \
src/core/ext/filters/client_channel/global_subchannel_pool.cc \
src/core/ext/filters/client_channel/health/health_check_client.cc \
src/core/ext/filters/client_channel/http_connect_handshaker.cc \
@@ -3677,6 +3679,7 @@ LIBGRPC_SRC = \
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
+ src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc \
src/core/ext/filters/client_channel/service_config_parser.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
@@ -4092,8 +4095,8 @@ $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_
ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgpr -laddress_sorting -lupb
else
- $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.10 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgpr -laddress_sorting -lupb
- $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.10
+ $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.11 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgpr -laddress_sorting -lupb
+ $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.11
$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so
endif
endif
@@ -4149,8 +4152,8 @@ $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE):
ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgrpc -lgpr -laddress_sorting -lupb
else
- $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.10 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgrpc -lgpr -laddress_sorting -lupb
- $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).so.10
+ $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.11 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgrpc -lgpr -laddress_sorting -lupb
+ $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).so.11
$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).so
endif
endif
@@ -4275,6 +4278,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/filters/client_channel/client_channel_channelz.cc \
src/core/ext/filters/client_channel/client_channel_factory.cc \
src/core/ext/filters/client_channel/client_channel_plugin.cc \
+ src/core/ext/filters/client_channel/config_selector.cc \
src/core/ext/filters/client_channel/global_subchannel_pool.cc \
src/core/ext/filters/client_channel/health/health_check_client.cc \
src/core/ext/filters/client_channel/http_connect_handshaker.cc \
@@ -4322,6 +4326,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
+ src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc \
src/core/ext/filters/client_channel/service_config_parser.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
@@ -4650,8 +4655,8 @@ $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $
ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgpr -laddress_sorting -lupb
else
- $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.10 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgpr -laddress_sorting -lupb
- $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.10
+ $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.11 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) -lgpr -laddress_sorting -lupb
+ $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.11
$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so
endif
endif
@@ -4717,6 +4722,7 @@ $(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/helpers.o: $(GENDIR)/src/proto/grpc
LIBGRPC++_SRC = \
src/cpp/client/channel_cc.cc \
+ src/cpp/client/client_callback.cc \
src/cpp/client/client_context.cc \
src/cpp/client/client_interceptor.cc \
src/cpp/client/create_channel.cc \
@@ -5422,6 +5428,7 @@ endif
LIBGRPC++_UNSECURE_SRC = \
src/cpp/client/channel_cc.cc \
+ src/cpp/client/client_callback.cc \
src/cpp/client/client_context.cc \
src/cpp/client/client_interceptor.cc \
src/cpp/client/create_channel.cc \
@@ -6269,8 +6276,8 @@ $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBUPB_OB
ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBUPB_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
else
- $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libupb.so.10 -o $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBUPB_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
- $(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).so.10
+ $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libupb.so.11 -o $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBUPB_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS)
+ $(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).so.11
$(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).so
endif
endif
@@ -10052,38 +10059,6 @@ endif
endif
-SERVER_CHTTP2_TEST_SRC = \
- test/core/surface/server_chttp2_test.cc \
-
-SERVER_CHTTP2_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_CHTTP2_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/server_chttp2_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/server_chttp2_test: $(SERVER_CHTTP2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
- $(E) "[LD] Linking $@"
- $(Q) mkdir -p `dirname $@`
- $(Q) $(LDXX) $(LDFLAGS) $(SERVER_CHTTP2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/server_chttp2_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/surface/server_chttp2_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
-
-deps_server_chttp2_test: $(SERVER_CHTTP2_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(SERVER_CHTTP2_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
SERVER_SSL_TEST_SRC = \
test/core/handshake/server_ssl.cc \
test/core/handshake/server_ssl_common.cc \
@@ -17219,6 +17194,49 @@ endif
$(OBJDIR)/$(CONFIG)/test/cpp/server/server_builder_with_socket_mutator_test.o: $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/simple_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/simple_messages.grpc.pb.cc
+SERVER_CHTTP2_TEST_SRC = \
+ test/core/surface/server_chttp2_test.cc \
+
+SERVER_CHTTP2_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_CHTTP2_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/server_chttp2_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
+
+$(BINDIR)/$(CONFIG)/server_chttp2_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/server_chttp2_test: $(PROTOBUF_DEP) $(SERVER_CHTTP2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LDXX) $(LDFLAGS) $(SERVER_CHTTP2_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_chttp2_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/surface/server_chttp2_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a
+
+deps_server_chttp2_test: $(SERVER_CHTTP2_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(SERVER_CHTTP2_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
SERVER_CONTEXT_TEST_SPOUSE_TEST_SRC = \
test/cpp/test/server_context_test_spouse_test.cc \
diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml
index 9eb53b8e576..fac33c197a2 100644
--- a/build_autogenerated.yaml
+++ b/build_autogenerated.yaml
@@ -377,6 +377,7 @@ libs:
- src/core/ext/filters/client_channel/client_channel.h
- src/core/ext/filters/client_channel/client_channel_channelz.h
- src/core/ext/filters/client_channel/client_channel_factory.h
+ - src/core/ext/filters/client_channel/config_selector.h
- src/core/ext/filters/client_channel/connector.h
- src/core/ext/filters/client_channel/global_subchannel_pool.h
- src/core/ext/filters/client_channel/health/health_check_client.h
@@ -746,6 +747,7 @@ libs:
- src/core/ext/filters/client_channel/client_channel_channelz.cc
- src/core/ext/filters/client_channel/client_channel_factory.cc
- src/core/ext/filters/client_channel/client_channel_plugin.cc
+ - src/core/ext/filters/client_channel/config_selector.cc
- src/core/ext/filters/client_channel/global_subchannel_pool.cc
- src/core/ext/filters/client_channel/health/health_check_client.cc
- src/core/ext/filters/client_channel/http_connect_handshaker.cc
@@ -793,6 +795,7 @@ libs:
- src/core/ext/filters/client_channel/retry_throttle.cc
- src/core/ext/filters/client_channel/server_address.cc
- src/core/ext/filters/client_channel/service_config.cc
+ - src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
- src/core/ext/filters/client_channel/service_config_parser.cc
- src/core/ext/filters/client_channel/subchannel.cc
- src/core/ext/filters/client_channel/subchannel_pool_interface.cc
@@ -1300,6 +1303,7 @@ libs:
- src/core/ext/filters/client_channel/client_channel.h
- src/core/ext/filters/client_channel/client_channel_channelz.h
- src/core/ext/filters/client_channel/client_channel_factory.h
+ - src/core/ext/filters/client_channel/config_selector.h
- src/core/ext/filters/client_channel/connector.h
- src/core/ext/filters/client_channel/global_subchannel_pool.h
- src/core/ext/filters/client_channel/health/health_check_client.h
@@ -1605,6 +1609,7 @@ libs:
- src/core/ext/filters/client_channel/client_channel_channelz.cc
- src/core/ext/filters/client_channel/client_channel_factory.cc
- src/core/ext/filters/client_channel/client_channel_plugin.cc
+ - src/core/ext/filters/client_channel/config_selector.cc
- src/core/ext/filters/client_channel/global_subchannel_pool.cc
- src/core/ext/filters/client_channel/health/health_check_client.cc
- src/core/ext/filters/client_channel/http_connect_handshaker.cc
@@ -1652,6 +1657,7 @@ libs:
- src/core/ext/filters/client_channel/retry_throttle.cc
- src/core/ext/filters/client_channel/server_address.cc
- src/core/ext/filters/client_channel/service_config.cc
+ - src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
- src/core/ext/filters/client_channel/service_config_parser.cc
- src/core/ext/filters/client_channel/subchannel.cc
- src/core/ext/filters/client_channel/subchannel_pool_interface.cc
@@ -2203,6 +2209,7 @@ libs:
- src/cpp/thread_manager/thread_manager.h
src:
- src/cpp/client/channel_cc.cc
+ - src/cpp/client/client_callback.cc
- src/cpp/client/client_context.cc
- src/cpp/client/client_interceptor.cc
- src/cpp/client/create_channel.cc
@@ -2592,6 +2599,7 @@ libs:
- src/cpp/thread_manager/thread_manager.h
src:
- src/cpp/client/channel_cc.cc
+ - src/cpp/client/client_callback.cc
- src/cpp/client/client_context.cc
- src/cpp/client/client_interceptor.cc
- src/cpp/client/create_channel.cc
@@ -4134,18 +4142,6 @@ targets:
- gpr
- address_sorting
- upb
-- name: server_chttp2_test
- build: test
- language: c
- headers: []
- src:
- - test/core/surface/server_chttp2_test.cc
- deps:
- - grpc_test_util
- - grpc
- - gpr
- - address_sorting
- - upb
- name: server_ssl_test
build: test
language: c
@@ -6930,6 +6926,19 @@ targets:
- linux
- posix
- mac
+- name: server_chttp2_test
+ gtest: true
+ build: test
+ language: c++
+ headers: []
+ src:
+ - test/core/surface/server_chttp2_test.cc
+ deps:
+ - grpc_test_util
+ - grpc
+ - gpr
+ - address_sorting
+ - upb
- name: server_context_test_spouse_test
gtest: true
build: test
diff --git a/build_config.rb b/build_config.rb
index bbbf04812b2..ff432bd3392 100644
--- a/build_config.rb
+++ b/build_config.rb
@@ -13,5 +13,5 @@
# limitations under the License.
module GrpcBuildConfig
- CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-10.dll'
+ CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-11.dll'
end
diff --git a/build_handwritten.yaml b/build_handwritten.yaml
index f1e603ababb..15594c622da 100644
--- a/build_handwritten.yaml
+++ b/build_handwritten.yaml
@@ -12,7 +12,7 @@ settings:
'#08': Use "-preN" suffixes to identify pre-release versions
'#09': Per-language overrides are possible with (eg) ruby_version tag here
'#10': See the expand_version.py for all the quirks here
- core_version: 10.0.0
+ core_version: 11.0.0
csharp_major_version: 2
g_stands_for: galore
version: 1.31.0-dev
diff --git a/config.m4 b/config.m4
index cd1019abcd9..a6bf9a21b6c 100644
--- a/config.m4
+++ b/config.m4
@@ -45,6 +45,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/client_channel_channelz.cc \
src/core/ext/filters/client_channel/client_channel_factory.cc \
src/core/ext/filters/client_channel/client_channel_plugin.cc \
+ src/core/ext/filters/client_channel/config_selector.cc \
src/core/ext/filters/client_channel/global_subchannel_pool.cc \
src/core/ext/filters/client_channel/health/health_check_client.cc \
src/core/ext/filters/client_channel/http_connect_handshaker.cc \
@@ -92,6 +93,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
+ src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc \
src/core/ext/filters/client_channel/service_config_parser.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
diff --git a/config.w32 b/config.w32
index 8109f9103af..03cf0684684 100644
--- a/config.w32
+++ b/config.w32
@@ -14,6 +14,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\client_channel_channelz.cc " +
"src\\core\\ext\\filters\\client_channel\\client_channel_factory.cc " +
"src\\core\\ext\\filters\\client_channel\\client_channel_plugin.cc " +
+ "src\\core\\ext\\filters\\client_channel\\config_selector.cc " +
"src\\core\\ext\\filters\\client_channel\\global_subchannel_pool.cc " +
"src\\core\\ext\\filters\\client_channel\\health\\health_check_client.cc " +
"src\\core\\ext\\filters\\client_channel\\http_connect_handshaker.cc " +
@@ -61,6 +62,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\retry_throttle.cc " +
"src\\core\\ext\\filters\\client_channel\\server_address.cc " +
"src\\core\\ext\\filters\\client_channel\\service_config.cc " +
+ "src\\core\\ext\\filters\\client_channel\\service_config_channel_arg_filter.cc " +
"src\\core\\ext\\filters\\client_channel\\service_config_parser.cc " +
"src\\core\\ext\\filters\\client_channel\\subchannel.cc " +
"src\\core\\ext\\filters\\client_channel\\subchannel_pool_interface.cc " +
diff --git a/doc/PROTOCOL-WEB.md b/doc/PROTOCOL-WEB.md
index 66544543804..1ee93606f65 100644
--- a/doc/PROTOCOL-WEB.md
+++ b/doc/PROTOCOL-WEB.md
@@ -17,7 +17,7 @@ with the protocol details specified in the
For the gRPC-Web protocol, we have decided on the following design goals:
* adopt the same framing as “application/grpc” whenever possible
-* decouple from HTTP/2 framing which is not, and will never, be directly
+* decouple from HTTP/2 framing which is not, and will never be, directly
exposed by browsers
* support text streams (e.g. base64) in order to provide cross-browser
support (e.g. IE-10)
diff --git a/doc/core/combiner-explainer.md b/doc/core/combiner-explainer.md
index 9e9d077273e..20b7f8df189 100644
--- a/doc/core/combiner-explainer.md
+++ b/doc/core/combiner-explainer.md
@@ -41,9 +41,9 @@ Instead, get a new property:
class combiner {
mpscq q; // multi-producer single-consumer queue can be made non-blocking
state s; // is it empty or executing
-
+
run(f) {
- if (q.push(f)) {
+ if (q.push(f)) {
// q.push returns true if it's the first thing
while (q.pop(&f)) { // modulo some extra work to avoid races
f();
@@ -73,9 +73,9 @@ class combiner {
mpscq q; // multi-producer single-consumer queue can be made non-blocking
state s; // is it empty or executing
queue finally; // you can only do run_finally when you are already running something from the combiner
-
+
run(f) {
- if (q.push(f)) {
+ if (q.push(f)) {
// q.push returns true if it's the first thing
loop:
while (q.pop(&f)) { // modulo some extra work to avoid races
@@ -127,7 +127,7 @@ tries to spray events onto as many threads as possible to get as much concurrenc
So `offload` really does:
-```
+```
workqueue.run(continue_from_while_loop);
break;
```
diff --git a/doc/core/epoll-polling-engine.md b/doc/core/epoll-polling-engine.md
index e660a709384..8ce54a020d4 100644
--- a/doc/core/epoll-polling-engine.md
+++ b/doc/core/epoll-polling-engine.md
@@ -104,7 +104,7 @@ void grpc_use_signal(int signal_num)
If the calling application does not provide a signal number, then the gRPC library will relegate to using a model similar to the current implementation (where every thread does a blocking `poll()` on its `wakeup_fd` and the `epoll_fd`). The function` psi_wait() `in figure 2 implements this logic.
-**>> **(**NOTE**: Or alternatively, we can implement a turnstile polling (i.e having only one thread calling `epoll_wait()` on the epoll set at any time - which all other threads call poll on their `wakeup_fds`)
+**>> **(**NOTE**: Or alternatively, we can implement a turnstile polling (i.e having only one thread calling `epoll_wait()` on the epoll set at any time - which all other threads call poll on their `wakeup_fds`)
in case of not getting a signal number from the applications.
diff --git a/doc/core/grpc-client-server-polling-engine-usage.md b/doc/core/grpc-client-server-polling-engine-usage.md
index f66dcf09caa..3aa3cc16a78 100644
--- a/doc/core/grpc-client-server-polling-engine-usage.md
+++ b/doc/core/grpc-client-server-polling-engine-usage.md
@@ -7,7 +7,7 @@ This document talks about how polling engine is used in gRPC core (both on clien
## gRPC client
-### Relation between Call, Channel (sub-channels), Completion queue, `grpc_pollset`
+### Relation between Call, Channel (sub-channels), Completion queue, `grpc_pollset`
- A gRPC Call is tied to a channel (more specifically a sub-channel) and a completion queue for the lifetime of the call.
- Once a _sub-channel_ is picked for the call, the file-descriptor (socket fd in case of TCP channels) is added to the pollset corresponding to call's completion queue. (Recall that as per [grpc-cq](grpc-cq.md), a completion queue has a pollset by default)
diff --git a/doc/core/grpc-cq.md b/doc/core/grpc-cq.md
index b485c354566..e8338d880bb 100644
--- a/doc/core/grpc-cq.md
+++ b/doc/core/grpc-cq.md
@@ -61,4 +61,4 @@ grpc_cq_end_op(cq, tag) {
}
```
-
+
diff --git a/doc/core/moving-to-c++.md b/doc/core/moving-to-c++.md
index 49daf61aae3..410435c46a6 100644
--- a/doc/core/moving-to-c++.md
+++ b/doc/core/moving-to-c++.md
@@ -11,7 +11,7 @@ gRPC core was originally written in C89 for several reasons
support, etc). Over time, this was changed to C99 as all relevant
compilers in active use came to support C99 effectively.
-gRPC started allowing to use C++ with a couple of exceptions not to
+gRPC started allowing to use C++ with a couple of exceptions not to
have C++ library linked such as `libstdc++.so`.
(For more detail, see the [proposal](https://github.com/grpc/proposal/blob/master/L6-core-allow-cpp.md))
@@ -25,12 +25,12 @@ C++ compatible with
## Constraints
-- Most of features available in C++11 are allowed to use but there are some exceptions
+- Most of features available in C++11 are allowed to use but there are some exceptions
because gRPC should support old systems.
- Should be built with gcc 4.8, clang 3.3, and Visual C++ 2015.
- Should be run on Linux system with libstdc++ 6.0.9 to support
[manylinux1](https://www.python.org/dev/peps/pep-0513).
-- This would limit us not to use modern C++11 standard library such as `filesystem`.
+- This would limit us not to use modern C++11 standard library such as `filesystem`.
You can easily see whether PR is free from this issue by checking the result of
`Artifact Build Linux` test.
- `thread_local` is not allowed to use on Apple's products because their old OSes
diff --git a/doc/environment_variables.md b/doc/environment_variables.md
index ec1b4f86717..13b71878c6d 100644
--- a/doc/environment_variables.md
+++ b/doc/environment_variables.md
@@ -73,7 +73,7 @@ some configuration as environment variables that can be set.
completion queue
- pick_first - traces the pick first load balancing policy
- plugin_credentials - traces plugin credentials
- - pollable_refcount - traces reference counting of 'pollable' objects (only
+ - pollable_refcount - traces reference counting of 'pollable' objects (only
in DEBUG)
- priority_lb - traces priority LB policy
- resource_quota - trace resource quota objects internals
diff --git a/doc/fork_support.md b/doc/fork_support.md
index d0f59f25da3..ff1018ab2ea 100644
--- a/doc/fork_support.md
+++ b/doc/fork_support.md
@@ -25,7 +25,7 @@ A regression was noted in cases where users are doing fork/exec. This
was due to ```pthread_atfork()``` handler that was added in 1.7 to partially
support forking in gRPC. A deadlock can happen when pthread_atfork
handler is running, and an application thread is calling into gRPC.
-We have provided a workaround for this issue by allowing users to turn
+We have provided a workaround for this issue by allowing users to turn
off the handler using env flag ```GRPC_ENABLE_FORK_SUPPORT=False```.
This should be set whenever a user expects to always call exec
immediately following fork. It will disable the fork handlers.
diff --git a/doc/grpc_xds_features.md b/doc/grpc_xds_features.md
new file mode 100644
index 00000000000..3537db2b965
--- /dev/null
+++ b/doc/grpc_xds_features.md
@@ -0,0 +1,40 @@
+# xDS Features in gRPC
+
+This document lists the [xDS](https://github.com/envoyproxy/data-plane-api/tree/master/envoy/api/v2)
+features supported in various gRPC language implementations and versions.
+
+Note that a gRPC client will simply ignore the configuration of a feature it
+does not support. The gRPC client does not generate a log
+to indicate that some configuration was ignored. It is impractical to generate
+a log and keep it up-to-date because xDS has a large number of APIs that gRPC
+does not support and the APIs keep evolving too. We recommend reading the
+[first gRFC](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md)
+on xDS support in gRPC to understand the design philosophy.
+
+The EDS policy will *not* support
+[overprovisioning](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/overprovisioning),
+which is different from Envoy. Envoy takes the overprovisioning into
+account in both [locality-weighted load balancing](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/locality_weight)
+and [priority failover](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/priority),
+but gRPC assumes that the xDS server will update it to redirect traffic
+when this kind of graceful failover is needed. gRPC will send the
+[`envoy.lb.does_not_support_overprovisioning` client
+feature](https://github.com/envoyproxy/envoy/pull/10136) to the xDS
+server to tell the xDS server that it will not perform graceful failover;
+xDS server implementations may use this to decide whether to perform
+graceful failover themselves.
+
+The EDS policy will not support per-endpoint stats; it will report only
+per-locality stats.
+
+An [`lb_endpoint`](https://github.com/envoyproxy/envoy/blob/12a4bc430eaf440ceb0d11286cfbd4c16b79cdd1/api/envoy/api/v2/endpoint/endpoint_components.proto#L72)
+is ignored if the `health_status` is not HEALTHY or UNKNOWN.
+The optional `load_balancing_weight` is always ignored.
+
+Initially, only `google_default` channel creds will be supported
+to authenticate with the xDS server.
+
+Features | gRFCs | [C++, Python,
Ruby, PHP, C#](https://github.com/grpc/grpc/releases) | [Java](https://github.com/grpc/grpc-java/releases) | [Go](https://github.com/grpc/grpc-go/releases)
+---------|--------|--------------|------|------
+**xDS Infrastructure in gRPC client channel:**
LDS->RDS->CDS->EDS flow,
ADS stream, | [A27](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md) | v1.30.0 | v1.30.0 | v1.30.0 |
+**Load Balancing:**
Virtual host matching,
Only default path ("" or "/") matching,
Priority-based weighted round-robin locality picking,
Round-robin endpoint picking within locality,
Cluster route action,
Client-side Load reporting via [LRS](https://github.com/envoyproxy/data-plane-api/blob/master/envoy/service/load_stats/v2/lrs.proto)| [A27](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md) | v1.30.0 | v1.30.0 | v1.30.0 |
diff --git a/doc/health-checking.md b/doc/health-checking.md
index 22b6e1b4c09..0d866e3f4db 100644
--- a/doc/health-checking.md
+++ b/doc/health-checking.md
@@ -37,6 +37,7 @@ message HealthCheckResponse {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
+ SERVICE_UNKNOWN = 3; // Used only by the Watch method.
}
ServingStatus status = 1;
}
diff --git a/doc/http2-interop-test-descriptions.md b/doc/http2-interop-test-descriptions.md
index 435a8de709c..c596f7c1637 100644
--- a/doc/http2-interop-test-descriptions.md
+++ b/doc/http2-interop-test-descriptions.md
@@ -8,7 +8,7 @@ Server
------
The code for the custom http2 server can be found
[here](https://github.com/grpc/grpc/tree/master/test/http2_test).
-It is responsible for handling requests and sending responses, and also for
+It is responsible for handling requests and sending responses, and also for
fulfilling the behavior of each particular test case.
Server should accept these arguments:
@@ -51,7 +51,7 @@ the user application having to do a thing.
Client Procedure:
1. Client sends two UnaryCall requests (and sleeps for 1 second in-between).
TODO: resolve [9300](https://github.com/grpc/grpc/issues/9300) and remove the 1 second sleep
-
+
```
{
response_size: 314159
@@ -78,7 +78,7 @@ RST_STREAM immediately after sending headers to the client.
Procedure:
1. Client sends UnaryCall with:
-
+
```
{
response_size: 314159
@@ -93,7 +93,7 @@ Client asserts:
Server Procedure:
1. Server sends a RST_STREAM with error code 0 after sending headers to the client.
-
+
*At the moment the error code and message returned are not standardized throughout all
languages. Those checks will be added once all client languages behave the same way. [#9142](https://github.com/grpc/grpc/issues/9142) is in flight.*
@@ -104,7 +104,7 @@ RST_STREAM halfway through sending data to the client.
Procedure:
1. Client sends UnaryCall with:
-
+
```
{
response_size: 314159
@@ -118,7 +118,7 @@ Client asserts:
* Call was not successful.
Server Procedure:
- 1. Server sends a RST_STREAM with error code 0 after sending half of
+ 1. Server sends a RST_STREAM with error code 0 after sending half of
the requested data to the client.
### rst_after_data
@@ -128,7 +128,7 @@ RST_STREAM after sending all of the data to the client.
Procedure:
1. Client sends UnaryCall with:
-
+
```
{
response_size: 314159
@@ -156,7 +156,7 @@ server.
Procedure:
1. Client sends UnaryCall with:
-
+
```
{
response_size: 314159
@@ -165,16 +165,16 @@ Procedure:
}
}
```
-
+
Client asserts:
* call was successful.
* response payload body is 314159 bytes in size.
Server Procedure:
- 1. Server tracks the number of outstanding pings (i.e. +1 when it sends a ping, and -1
+ 1. Server tracks the number of outstanding pings (i.e. +1 when it sends a ping, and -1
when it receives an ack from the client).
2. Server sends pings before and after sending headers, also before and after sending data.
-
+
Server Asserts:
* Number of outstanding pings is 0 when the connection is lost.
@@ -185,10 +185,10 @@ This test verifies that the client observes the MAX_CONCURRENT_STREAMS limit set
Client Procedure:
1. Client sends initial UnaryCall to allow the server to update its MAX_CONCURRENT_STREAMS settings.
2. Client concurrently sends 10 UnaryCalls.
-
+
Client Asserts:
* All UnaryCalls were successful, and had the correct type and payload size.
-
+
Server Procedure:
1. Sets MAX_CONCURRENT_STREAMS to one after the connection is made.
diff --git a/doc/internationalization.md b/doc/internationalization.md
index 1b614cbd264..6ff5894c8ba 100644
--- a/doc/internationalization.md
+++ b/doc/internationalization.md
@@ -1,7 +1,7 @@
gRPC Internationalization
=========================
-As a universal RPC framework, gRPC needs to be fully usable within/across different international environments.
+As a universal RPC framework, gRPC needs to be fully usable within/across different international environments.
This document describes gRPC API and behavior specifics when used in a non-english environment.
## API Concepts
diff --git a/doc/interop-test-descriptions.md b/doc/interop-test-descriptions.md
index 978c422d470..f7fbb48148a 100755
--- a/doc/interop-test-descriptions.md
+++ b/doc/interop-test-descriptions.md
@@ -1007,21 +1007,21 @@ languages. Therefore they are not part of our interop matrix.
#### rpc_soak
-The client performs many large_unary RPCs in sequence over the same channel.
+The client performs many large_unary RPCs in sequence over the same channel.
The number of RPCs is configured by the experimental flag, `soak_iterations`.
#### channel_soak
-The client performs many large_unary RPCs in sequence. Before each RPC, it
-tears down and rebuilds the channel. The number of RPCs is configured by
+The client performs many large_unary RPCs in sequence. Before each RPC, it
+tears down and rebuilds the channel. The number of RPCs is configured by
the experimental flag, `soak_iterations`.
-This tests puts stress on several gRPC components; the resolver, the load
+This tests puts stress on several gRPC components; the resolver, the load
balancer, and the RPC hotpath.
#### long_lived_channel
-The client performs a number of large_unary RPCs over a single long-lived
+The client performs a number of large_unary RPCs over a single long-lived
channel with a fixed but configurable interval between each RPC.
### TODO Tests
diff --git a/doc/keepalive.md b/doc/keepalive.md
index c09c6e241c2..3bf1ab4d626 100644
--- a/doc/keepalive.md
+++ b/doc/keepalive.md
@@ -14,7 +14,7 @@ The keepalive ping is controlled by two important channel arguments -
The above two channel arguments should be sufficient for most users, but the following arguments can also be useful in certain use cases.
* **GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS**
- * This channel argument if set to 1 (0 : false; 1 : true), allows keepalive pings to be sent even if there are no calls in flight.
+ * This channel argument if set to 1 (0 : false; 1 : true), allows keepalive pings to be sent even if there are no calls in flight.
* **GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA**
* This channel argument controls the maximum number of pings that can be sent when there is no data/header frame to be sent. GRPC Core will not continue sending pings if we run over the limit. Setting it to 0 allows sending pings without such a restriction.
* **GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS**
diff --git a/doc/python/server_reflection.md b/doc/python/server_reflection.md
index 8bffdaa5866..5e963ad1f1b 100644
--- a/doc/python/server_reflection.md
+++ b/doc/python/server_reflection.md
@@ -6,7 +6,7 @@ and more examples how to use server reflection.
## Enable server reflection in Python servers
-gRPC Python Server Reflection is an add-on library. To use it, first install
+gRPC Python Server Reflection is an add-on library. To use it, first install
the [grpcio-reflection] PyPI package into your project.
Note that with Python you need to manually register the service
@@ -29,7 +29,7 @@ def serve():
server.start()
```
-Please see [greeter_server_with_reflection.py] in the examples directory for the full
+Please see [greeter_server_with_reflection.py] in the examples directory for the full
example, which extends the gRPC [Python `Greeter` example] on a reflection-enabled server.
After starting the server, you can verify that the server reflection
diff --git a/doc/python/sphinx/grpc.rst b/doc/python/sphinx/grpc.rst
index 67867a683e9..4717eb12332 100644
--- a/doc/python/sphinx/grpc.rst
+++ b/doc/python/sphinx/grpc.rst
@@ -6,8 +6,8 @@ gRPC
Tutorial
--------
-If you want to see gRPC in action first, visit the `Python Quickstart `_.
-Or, if you would like dive in with more extensive usage of gRPC Python, check `gRPC Basics - Python `_ out.
+If you want to see gRPC in action first, visit the `Python Quickstart `_.
+Or, if you would like dive in with more extensive usage of gRPC Python, check `gRPC Basics - Python `_ out.
Example
diff --git a/doc/security_audit.md b/doc/security_audit.md
index 313a9e6b914..a7b935a2d1d 100644
--- a/doc/security_audit.md
+++ b/doc/security_audit.md
@@ -1,6 +1,6 @@
# gRPC Security Audit
-A third-party security audit of gRPC C++ stack was performed by [Cure53](https://cure53.de) in October 2019. The full report can be found [here](https://github.com/grpc/grpc/tree/master/doc/grpc_security_audit.pdf).
+A third-party security audit of gRPC C++ stack was performed by [Cure53](https://cure53.de) in October 2019. The full report can be found [here](https://github.com/grpc/grpc/tree/master/doc/grpc_security_audit.pdf).
# Addressing grpc_security_audit
@@ -21,7 +21,7 @@ Below is a list of alternatives that gRPC team considered.
### Alternative #1: Rewrite gpr_free to take void\*\*
-One solution is to change the API of `gpr_free` so that it automatically nulls the given pointer after freeing it.
+One solution is to change the API of `gpr_free` so that it automatically nulls the given pointer after freeing it.
```
gpr_free (void** ptr) {
@@ -30,7 +30,7 @@ gpr_free (void** ptr) {
}
```
-This defensive programming pattern would help protect gRPC from the potential exploits and latent dangling pointer bugs mentioned in the security report.
+This defensive programming pattern would help protect gRPC from the potential exploits and latent dangling pointer bugs mentioned in the security report.
However, performance would be a significant concern as we are now unconditionally adding a store to every gpr_free call, and there are potentially hundreds of these per RPC. At the RPC layer, this can add up to prohibitive costs.
@@ -61,7 +61,7 @@ Because of performance and maintainability concerns, GRP-01-002 will be addresse
## GRP-01-003 Calls to malloc suffer from potential integer overflows
The vulnerability, as defined by the report, is that calls to `gpr_malloc` in the C-core codebase may suffer from potential integer overflow in cases where we multiply the array element size by the size of the array. The penetration testers did not identify a concrete place where this occurred, but rather emphasized that the coding pattern itself had potential to lead to vulnerabilities. The report’s suggested solution for GRP-01-003 was to create a `calloc(size_t nmemb, size_t size)` wrapper that contains integer overflow checks.
-However, gRPC team firmly believes that gRPC Core should only use integer overflow checks in the places where they’re needed; for example, any place where remote input influences the input to `gpr_malloc` in an unverified way. This is because bounds-checking is very expensive at the RPC layer.
+However, gRPC team firmly believes that gRPC Core should only use integer overflow checks in the places where they’re needed; for example, any place where remote input influences the input to `gpr_malloc` in an unverified way. This is because bounds-checking is very expensive at the RPC layer.
Determining exactly where bounds-checking is needed requires an audit of tracing each `gpr_malloc` (or `gpr_realloc` or `gpr_zalloc`) call up the stack to determine if the sufficient bounds-checking was performed. This kind of audit, done manually, is fairly expensive engineer-wise.
diff --git a/doc/unit_testing.md b/doc/unit_testing.md
index c301e7d4219..5672f7f65fd 100644
--- a/doc/unit_testing.md
+++ b/doc/unit_testing.md
@@ -75,7 +75,7 @@ grpc_proto_library(
```
-By adding such a flag now a header file `echo_mock.grpc.pb.h` containing the mocked stub will also be generated.
+By adding such a flag now a header file `echo_mock.grpc.pb.h` containing the mocked stub will also be generated.
This header file can then be included in test files along with a gmock dependency.
diff --git a/doc/versioning.md b/doc/versioning.md
index 79f573526ee..3d6849c2ce9 100644
--- a/doc/versioning.md
+++ b/doc/versioning.md
@@ -3,7 +3,7 @@
## Versioning Overview
All gRPC implementations use a three-part version number (`vX.Y.Z`) and follow [semantic versioning](https://semver.org/), which defines the semantics of major, minor and patch components of the version number. In addition to that, gRPC versions evolve according to these rules:
-- **Major version bumps** only happen on rare occasions. In order to qualify for a major version bump, certain criteria described later in this document need to be met. Most importantly, a major version increase must not break wire compatibility with other gRPC implementations so that existing gRPC libraries remain fully interoperable.
+- **Major version bumps** only happen on rare occasions. In order to qualify for a major version bump, certain criteria described later in this document need to be met. Most importantly, a major version increase must not break wire compatibility with other gRPC implementations so that existing gRPC libraries remain fully interoperable.
- **Minor version bumps** happen approx. every 6 weeks as part of the normal release cycle as defined by the gRPC release process. A new release branch named vMAJOR.MINOR.PATCH) is cut every 6 weeks based on the [release schedule](https://github.com/grpc/grpc/blob/master/doc/grpc_release_schedule.md).
- **Patch version bump** corresponds to bugfixes done on release branch.
@@ -24,7 +24,7 @@ There are also a few extra rules regarding adding new gRPC implementations (e.g.
To avoid user confusion and simplify reasoning, the gRPC releases in different languages try to stay synchronized in terms of major and minor version (all languages follow the same release schedule). Nevertheless, because we also strictly follow semantic versioning, there are circumstances in which a gRPC implementation needs to break the version synchronicity and do a major version bump independently of other languages.
### Situations when it's ok to do a major version bump
-- **change forced by the language ecosystem:** when the language itself or its standard libraries that we depend on make a breaking change (something which is out of our control), reacting with updating gRPC APIs may be the only adequate response.
+- **change forced by the language ecosystem:** when the language itself or its standard libraries that we depend on make a breaking change (something which is out of our control), reacting with updating gRPC APIs may be the only adequate response.
- **voluntary change:** Even in non-forced situations, there might be circumstances in which a breaking API change makes sense and represents a net win, but as a rule of thumb breaking changes are very disruptive for users, cause user fragmentation and incur high maintenance costs. Therefore, breaking API changes should be very rare events that need to be considered with extreme care and the bar for accepting such changes is intentionally set very high.
Example scenarios where a breaking API change might be adequate:
- fixing a security problem which requires changes to API (need to consider the non-breaking alternatives first)
diff --git a/doc/xds-test-descriptions.md b/doc/xds-test-descriptions.md
index 46414384e95..bd94bb4ce8d 100644
--- a/doc/xds-test-descriptions.md
+++ b/doc/xds-test-descriptions.md
@@ -90,7 +90,7 @@ This test verifies that every backend receives traffic.
Client parameters:
1. --num_channels=1
-1. --qps=10
+1. --qps=100
1. --fail_on_failed_rpc=true
Load balancer configuration:
@@ -109,7 +109,7 @@ robin policy.
Client parameters:
1. --num_channels=1
-1. --qps=10
+1. --qps=100
1. --fail_on_failed_rpc=true
Load balancer configuration:
@@ -129,7 +129,7 @@ of backends that is stopped and then resumed.
Client parameters:
1. --num_channels=1
-1. --qps=10
+1. --qps=100
Load balancer configuration:
@@ -161,7 +161,7 @@ all backends in the primary locality fail.
Client parameters:
1. --num_channels=1
-1. --qps=10
+1. --qps=100
Load balancer configuration:
@@ -197,7 +197,7 @@ changes to this test case.
Client parameters:
1. --num_channels=1
-1. --qps=10
+1. --qps=100
Load balancer configuration:
@@ -224,7 +224,7 @@ same zone receive traffic.
Client parameters:
1. --num_channels=1
-1. --qps=10
+1. --qps=100
1. --fail_on_failed_rpc=true
Load balancer configuration:
@@ -249,7 +249,7 @@ after removal of another instance group in the same zone.
Client parameters:
1. --num_channels=1
-1. --qps=10
+1. --qps=100
Load balancer configuration:
@@ -273,7 +273,7 @@ to the new backends.
Client parameters:
1. --num_channels=1
-1. --qps=10
+1. --qps=100
1. --fail_on_failed_rpc=true
Load balancer configuration:
@@ -291,3 +291,31 @@ Test driver asserts:
1. All RPCs are directed to the new backend service.
+### traffic_splitting
+
+This test verifies that the traffic will be distributed between backend
+services with the correct weights when route action is set to weighted
+backend services.
+
+Client parameters:
+
+1. --num_channels=1
+1. --qps=100
+
+Load balancer configuration:
+
+1. One MIG with one backend
+
+Assert:
+
+1. Once all backends receive at least one RPC, the following 1000 RPCs are
+all sent to MIG_a.
+
+The test driver adds a new MIG with 1 backend, and changes the route action
+to weighted backend services with {a: 20, b: 80}.
+
+Assert:
+
+1. Once all backends receive at least one RPC, the following 1000 RPCs are
+distributed across the 2 backends as a: 20, b: 80.
+
diff --git a/examples/cpp/README.md b/examples/cpp/README.md
index a0ff629b1a0..7c281de30c0 100644
--- a/examples/cpp/README.md
+++ b/examples/cpp/README.md
@@ -7,7 +7,7 @@
For information about the other examples in this directory, see their respective
README files.
-[gRPC Basics]: https://grpc.io/docs/tutorials/basic/cpp
+[gRPC Basics]: https://grpc.io/docs/languages/cpp/basics
[Hello World]: helloworld
-[Quick Start]: https://grpc.io/docs/quickstart/cpp
+[Quick Start]: https://grpc.io/docs/languages/cpp/quickstart
[Route Guide]: route_guide
diff --git a/examples/cpp/helloworld/README.md b/examples/cpp/helloworld/README.md
index e13c83281a7..a06cc8e3cb2 100644
--- a/examples/cpp/helloworld/README.md
+++ b/examples/cpp/helloworld/README.md
@@ -3,4 +3,4 @@
You can find a complete set of instructions for building gRPC and running the
Hello World app in the [C++ Quick Start][].
-[C++ Quick Start]: https://grpc.io/docs/quickstart/cpp
+[C++ Quick Start]: https://grpc.io/docs/languages/cpp/quickstart
diff --git a/examples/cpp/route_guide/README.md b/examples/cpp/route_guide/README.md
index 1d1956d275d..2b2376ca180 100644
--- a/examples/cpp/route_guide/README.md
+++ b/examples/cpp/route_guide/README.md
@@ -3,4 +3,4 @@
The files in this folder are the samples used in [gRPC Basics: C++][],
a detailed tutorial for using gRPC in C++.
-[gRPC Basics: C++]:https://grpc.io/docs/tutorials/basic/cpp
+[gRPC Basics: C++]:https://grpc.io/docs/languages/cpp/basics
diff --git a/examples/csharp/Helloworld/README.md b/examples/csharp/Helloworld/README.md
index e4771ee91a1..8897d4fc00c 100644
--- a/examples/csharp/Helloworld/README.md
+++ b/examples/csharp/Helloworld/README.md
@@ -36,4 +36,4 @@ Tutorial
You can find a more detailed tutorial about Grpc in [gRPC Basics: C#][]
[helloworld.proto]:../../protos/helloworld.proto
-[gRPC Basics: C#]:https://grpc.io/docs/tutorials/basic/csharp.html
+[gRPC Basics: C#]:https://grpc.io/docs/languages/csharp/basics
diff --git a/examples/csharp/HelloworldLegacyCsproj/README.md b/examples/csharp/HelloworldLegacyCsproj/README.md
index 4435faeb086..3f3889fe216 100644
--- a/examples/csharp/HelloworldLegacyCsproj/README.md
+++ b/examples/csharp/HelloworldLegacyCsproj/README.md
@@ -40,7 +40,7 @@ download all of the NuGet dependencies of gRPC.
Using these IDEs, a workaround is as follows:
* Obtain a nuget executable for your platform and update it with
- `nuget update -self`.
+ `nuget update -self`.
* Navigate to this directory and run `nuget restore`.
* Now that packages have been restored into their proper package folder, build the solution from your IDE.
@@ -71,4 +71,4 @@ Tutorial
You can find a more detailed tutorial in [gRPC Basics: C#][]
[helloworld.proto]:../../protos/helloworld.proto
-[gRPC Basics: C#]:https://grpc.io/docs/tutorials/basic/csharp.html
+[gRPC Basics: C#]:https://grpc.io/docs/languages/csharp/basics
diff --git a/examples/csharp/RouteGuide/README.md b/examples/csharp/RouteGuide/README.md
index 3cfb14ae9a9..bfdb9e14f06 100644
--- a/examples/csharp/RouteGuide/README.md
+++ b/examples/csharp/RouteGuide/README.md
@@ -3,4 +3,4 @@
The files in this folder are the samples used in [gRPC Basics: C#][],
a detailed tutorial for using gRPC in C#.
-[gRPC Basics: C#]:https://grpc.io/docs/tutorials/basic/csharp.html
+[gRPC Basics: C#]:https://grpc.io/docs/languages/csharp/basics
diff --git a/examples/node/README.md b/examples/node/README.md
index 0264e9d66b7..b45488b8b56 100644
--- a/examples/node/README.md
+++ b/examples/node/README.md
@@ -47,4 +47,4 @@ TUTORIAL
You can find a more detailed tutorial in [gRPC Basics: Node.js][]
[Install gRPC Node]:../../src/node
-[gRPC Basics: Node.js]:https://grpc.io/docs/tutorials/basic/node.html
+[gRPC Basics: Node.js]:https://grpc.io/docs/languages/node/basics
diff --git a/examples/node/dynamic_codegen/route_guide/README.md b/examples/node/dynamic_codegen/route_guide/README.md
index 7d6b0b7debe..fcd147054a6 100644
--- a/examples/node/dynamic_codegen/route_guide/README.md
+++ b/examples/node/dynamic_codegen/route_guide/README.md
@@ -2,4 +2,4 @@
The files in this folder are the samples used in [gRPC Basics: Node.js][], a detailed tutorial for using gRPC in Node.js.
-[gRPC Basics: Node.js]:https://grpc.io/docs/tutorials/basic/node.html
+[gRPC Basics: Node.js]:https://grpc.io/docs/languages/node/basics
diff --git a/examples/node/static_codegen/route_guide/README.md b/examples/node/static_codegen/route_guide/README.md
index 7d6b0b7debe..fcd147054a6 100644
--- a/examples/node/static_codegen/route_guide/README.md
+++ b/examples/node/static_codegen/route_guide/README.md
@@ -2,4 +2,4 @@
The files in this folder are the samples used in [gRPC Basics: Node.js][], a detailed tutorial for using gRPC in Node.js.
-[gRPC Basics: Node.js]:https://grpc.io/docs/tutorials/basic/node.html
+[gRPC Basics: Node.js]:https://grpc.io/docs/languages/node/basics
diff --git a/examples/objective-c/auth_sample/README.md b/examples/objective-c/auth_sample/README.md
index a0063de3f2f..6e90be39b16 100644
--- a/examples/objective-c/auth_sample/README.md
+++ b/examples/objective-c/auth_sample/README.md
@@ -1,3 +1,3 @@
# OAuth2 on gRPC: Objective-C
-This is the supporting code for the tutorial "[OAuth2 on gRPC: Objective-C](https://grpc.io/docs/tutorials/auth/oauth2-objective-c.html)."
+This is the supporting code for the tutorial "[OAuth2 on gRPC: Objective-C](https://grpc.io/docs/languages/objective-c/oauth2)."
diff --git a/examples/objective-c/helloworld/README.md b/examples/objective-c/helloworld/README.md
index c57e07ca931..2fa390dc917 100644
--- a/examples/objective-c/helloworld/README.md
+++ b/examples/objective-c/helloworld/README.md
@@ -104,4 +104,4 @@ $ bazel run :HelloWorld --ios_simulator_version='' --ios_sumlator_devic
## Tutorial
-You can find a more detailed tutorial in [gRPC Basics: Objective-C](https://grpc.io/docs/tutorials/basic/objective-c.html).
+You can find a more detailed tutorial in [gRPC Basics: Objective-C](https://grpc.io/docs/languages/objective-c/basics).
diff --git a/examples/objective-c/route_guide/README.md b/examples/objective-c/route_guide/README.md
index 60e5304651a..4cc57ceb58e 100644
--- a/examples/objective-c/route_guide/README.md
+++ b/examples/objective-c/route_guide/README.md
@@ -1,4 +1,4 @@
# gRPC Basics: Objective-C
-This is the supporting code for the tutorial "[gRPC Basics: Objective-C](https://grpc.io/docs/tutorials/basic/objective-c.html)."
+This is the supporting code for the tutorial "[gRPC Basics: Objective-C](https://grpc.io/docs/languages/objective-c/basics)."
diff --git a/examples/php/README.md b/examples/php/README.md
index 75b9e6fb829..2182e39628a 100644
--- a/examples/php/README.md
+++ b/examples/php/README.md
@@ -53,4 +53,4 @@ This requires `php` >= 5.5, `pecl`, `composer`
You can find a more detailed tutorial in [gRPC Basics: PHP][]
[Node]:https://github.com/grpc/grpc/tree/master/examples/node
-[gRPC Basics: PHP]:https://grpc.io/docs/tutorials/basic/php.html
+[gRPC Basics: PHP]:https://grpc.io/docs/languages/php/basics
diff --git a/examples/php/route_guide/README.md b/examples/php/route_guide/README.md
index 6bea70dea03..e5abfbba053 100644
--- a/examples/php/route_guide/README.md
+++ b/examples/php/route_guide/README.md
@@ -3,4 +3,4 @@
The files in this folder are the samples used in [gRPC Basics: PHP][],
a detailed tutorial for using gRPC in PHP.
-[gRPC Basics: PHP]:https://grpc.io/docs/tutorials/basic/php.html
+[gRPC Basics: PHP]:https://grpc.io/docs/languages/php/basics
diff --git a/examples/python/README.md b/examples/python/README.md
index 63d61e439b6..be57d89785d 100644
--- a/examples/python/README.md
+++ b/examples/python/README.md
@@ -1 +1 @@
-[This code's documentation lives on the grpc.io site.](https://grpc.io/docs/quickstart/python.html)
+[This code's documentation lives on the grpc.io site.](https://grpc.io/docs/languages/python/quickstart)
diff --git a/examples/python/helloworld/README.md b/examples/python/helloworld/README.md
index 63d61e439b6..be57d89785d 100644
--- a/examples/python/helloworld/README.md
+++ b/examples/python/helloworld/README.md
@@ -1 +1 @@
-[This code's documentation lives on the grpc.io site.](https://grpc.io/docs/quickstart/python.html)
+[This code's documentation lives on the grpc.io site.](https://grpc.io/docs/languages/python/quickstart)
diff --git a/examples/python/metadata/README.md b/examples/python/metadata/README.md
index 5aa75d504a8..26ffa44f6fa 100644
--- a/examples/python/metadata/README.md
+++ b/examples/python/metadata/README.md
@@ -2,5 +2,5 @@ An example showing how to add custom HTTP2 headers (or [metadata](https://grpc.i
HTTP2 supports initial headers and trailing headers, which gRPC utilizes both of them ([learn more](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md)).
-More complete documentation lives at [grpc.io](https://grpc.io/docs/tutorials/basic/python.html).
+More complete documentation lives at [grpc.io](https://grpc.io/docs/languages/python/basics).
For API reference please see [API](https://grpc.io/grpc/python/grpc.html).
diff --git a/examples/python/multiplex/README.md b/examples/python/multiplex/README.md
index 2316cd39e88..8afdb4dffeb 100644
--- a/examples/python/multiplex/README.md
+++ b/examples/python/multiplex/README.md
@@ -1,3 +1,3 @@
An example showing two stubs sharing a channel and two servicers sharing a server.
-More complete documentation lives at [grpc.io](https://grpc.io/docs/tutorials/basic/python.html).
+More complete documentation lives at [grpc.io](https://grpc.io/docs/languages/python/basics).
diff --git a/examples/python/route_guide/README.md b/examples/python/route_guide/README.md
index 890e66ebad0..6f7a2f0fdf0 100644
--- a/examples/python/route_guide/README.md
+++ b/examples/python/route_guide/README.md
@@ -1 +1 @@
-[This code's documentation lives on the grpc.io site.](https://grpc.io/docs/tutorials/basic/python.html)
+[This code's documentation lives on the grpc.io site.](https://grpc.io/docs/languages/python/basics)
diff --git a/examples/ruby/README.md b/examples/ruby/README.md
index c6af1a5a5e8..2a3dec338fe 100644
--- a/examples/ruby/README.md
+++ b/examples/ruby/README.md
@@ -60,4 +60,4 @@ You can find a more detailed tutorial in [gRPC Basics: Ruby][]
[helloworld.proto]:../protos/helloworld.proto
[RVM]:https://www.rvm.io/
[Install gRPC ruby]:../../src/ruby#installation
-[gRPC Basics: Ruby]:https://grpc.io/docs/tutorials/basic/ruby.html
+[gRPC Basics: Ruby]:https://grpc.io/docs/languages/ruby/basics
diff --git a/examples/ruby/route_guide/README.md b/examples/ruby/route_guide/README.md
index 12537c859e1..83501d4babf 100644
--- a/examples/ruby/route_guide/README.md
+++ b/examples/ruby/route_guide/README.md
@@ -3,4 +3,4 @@
The files in this folder are the samples used in [gRPC Basics: Ruby][],
a detailed tutorial for using gRPC in Ruby.
-[gRPC Basics: Ruby]:https://grpc.io/docs/tutorials/basic/ruby.html
+[gRPC Basics: Ruby]:https://grpc.io/docs/languages/ruby/basics
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index c786ae57a24..eb18e48a9d8 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -226,6 +226,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/client_channel.h',
'src/core/ext/filters/client_channel/client_channel_channelz.h',
'src/core/ext/filters/client_channel/client_channel_factory.h',
+ 'src/core/ext/filters/client_channel/config_selector.h',
'src/core/ext/filters/client_channel/connector.h',
'src/core/ext/filters/client_channel/global_subchannel_pool.h',
'src/core/ext/filters/client_channel/health/health_check_client.h',
@@ -615,6 +616,7 @@ Pod::Spec.new do |s|
'src/core/tsi/transport_security_grpc.h',
'src/core/tsi/transport_security_interface.h',
'src/cpp/client/channel_cc.cc',
+ 'src/cpp/client/client_callback.cc',
'src/cpp/client/client_context.cc',
'src/cpp/client/client_interceptor.cc',
'src/cpp/client/create_channel.cc',
@@ -685,6 +687,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/client_channel.h',
'src/core/ext/filters/client_channel/client_channel_channelz.h',
'src/core/ext/filters/client_channel/client_channel_factory.h',
+ 'src/core/ext/filters/client_channel/config_selector.h',
'src/core/ext/filters/client_channel/connector.h',
'src/core/ext/filters/client_channel/global_subchannel_pool.h',
'src/core/ext/filters/client_channel/health/health_check_client.h',
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 695768422c2..43a47a09fa7 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -195,6 +195,8 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/client_channel_factory.cc',
'src/core/ext/filters/client_channel/client_channel_factory.h',
'src/core/ext/filters/client_channel/client_channel_plugin.cc',
+ 'src/core/ext/filters/client_channel/config_selector.cc',
+ 'src/core/ext/filters/client_channel/config_selector.h',
'src/core/ext/filters/client_channel/connector.h',
'src/core/ext/filters/client_channel/global_subchannel_pool.cc',
'src/core/ext/filters/client_channel/global_subchannel_pool.h',
@@ -277,6 +279,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/service_config.cc',
'src/core/ext/filters/client_channel/service_config.h',
'src/core/ext/filters/client_channel/service_config_call_data.h',
+ 'src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc',
'src/core/ext/filters/client_channel/service_config_parser.cc',
'src/core/ext/filters/client_channel/service_config_parser.h',
'src/core/ext/filters/client_channel/subchannel.cc',
@@ -1051,6 +1054,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/client_channel.h',
'src/core/ext/filters/client_channel/client_channel_channelz.h',
'src/core/ext/filters/client_channel/client_channel_factory.h',
+ 'src/core/ext/filters/client_channel/config_selector.h',
'src/core/ext/filters/client_channel/connector.h',
'src/core/ext/filters/client_channel/global_subchannel_pool.h',
'src/core/ext/filters/client_channel/health/health_check_client.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index af04b9d9de4..72ec55f0c86 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -117,6 +117,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/client_channel_factory.cc )
s.files += %w( src/core/ext/filters/client_channel/client_channel_factory.h )
s.files += %w( src/core/ext/filters/client_channel/client_channel_plugin.cc )
+ s.files += %w( src/core/ext/filters/client_channel/config_selector.cc )
+ s.files += %w( src/core/ext/filters/client_channel/config_selector.h )
s.files += %w( src/core/ext/filters/client_channel/connector.h )
s.files += %w( src/core/ext/filters/client_channel/global_subchannel_pool.cc )
s.files += %w( src/core/ext/filters/client_channel/global_subchannel_pool.h )
@@ -199,6 +201,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/service_config.cc )
s.files += %w( src/core/ext/filters/client_channel/service_config.h )
s.files += %w( src/core/ext/filters/client_channel/service_config_call_data.h )
+ s.files += %w( src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc )
s.files += %w( src/core/ext/filters/client_channel/service_config_parser.cc )
s.files += %w( src/core/ext/filters/client_channel/service_config_parser.h )
s.files += %w( src/core/ext/filters/client_channel/subchannel.cc )
diff --git a/grpc.gyp b/grpc.gyp
index b80efd83534..587e6ba8d94 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -440,6 +440,7 @@
'src/core/ext/filters/client_channel/client_channel_channelz.cc',
'src/core/ext/filters/client_channel/client_channel_factory.cc',
'src/core/ext/filters/client_channel/client_channel_plugin.cc',
+ 'src/core/ext/filters/client_channel/config_selector.cc',
'src/core/ext/filters/client_channel/global_subchannel_pool.cc',
'src/core/ext/filters/client_channel/health/health_check_client.cc',
'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
@@ -487,6 +488,7 @@
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/service_config.cc',
+ 'src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc',
'src/core/ext/filters/client_channel/service_config_parser.cc',
'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
@@ -947,6 +949,7 @@
'src/core/ext/filters/client_channel/client_channel_channelz.cc',
'src/core/ext/filters/client_channel/client_channel_factory.cc',
'src/core/ext/filters/client_channel/client_channel_plugin.cc',
+ 'src/core/ext/filters/client_channel/config_selector.cc',
'src/core/ext/filters/client_channel/global_subchannel_pool.cc',
'src/core/ext/filters/client_channel/health/health_check_client.cc',
'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
@@ -994,6 +997,7 @@
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/service_config.cc',
+ 'src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc',
'src/core/ext/filters/client_channel/service_config_parser.cc',
'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
@@ -1313,6 +1317,7 @@
],
'sources': [
'src/cpp/client/channel_cc.cc',
+ 'src/cpp/client/client_callback.cc',
'src/cpp/client/client_context.cc',
'src/cpp/client/client_interceptor.cc',
'src/cpp/client/create_channel.cc',
@@ -1464,6 +1469,7 @@
],
'sources': [
'src/cpp/client/channel_cc.cc',
+ 'src/cpp/client/client_callback.cc',
'src/cpp/client/client_context.cc',
'src/cpp/client/client_interceptor.cc',
'src/cpp/client/create_channel.cc',
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index 725ecd244d2..aeb8f9c3ce1 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -674,8 +674,10 @@ typedef struct grpc_op {
const char** error_string;
} recv_status_on_client;
struct grpc_op_recv_close_on_server {
- /** out argument, set to 1 if the call failed in any way (seen as a
- cancellation on the server), or 0 if the call succeeded */
+ /** out argument, set to 1 if the call failed at the server for
+ a reason other than a non-OK status (cancel, deadline
+ exceeded, network failure, etc.), 0 otherwise (RPC processing ran to
+ completion and was able to provide any status from the server) */
int* cancelled;
} recv_close_on_server;
} data;
diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h
index 4f213ff5979..7436e644504 100644
--- a/include/grpc/impl/codegen/port_platform.h
+++ b/include/grpc/impl/codegen/port_platform.h
@@ -112,31 +112,6 @@
#define GPR_WINDOWS_ATOMIC 1
#define GPR_MSVC_TLS 1
#endif
-#elif defined(GPR_MANYLINUX1)
-// TODO(atash): manylinux1 is just another __linux__ but with ancient
-// libraries; it should be integrated with the `__linux__` definitions below.
-#define GPR_PLATFORM_STRING "manylinux"
-#define GPR_POSIX_CRASH_HANDLER 1
-#define GPR_CPU_POSIX 1
-#define GPR_GCC_ATOMIC 1
-#define GPR_GCC_TLS 1
-#define GPR_LINUX 1
-#define GPR_LINUX_LOG 1
-#define GPR_SUPPORT_CHANNELS_FROM_FD 1
-#define GPR_LINUX_ENV 1
-#define GPR_POSIX_TMPFILE 1
-#define GPR_POSIX_STRING 1
-#define GPR_POSIX_SUBPROCESS 1
-#define GPR_POSIX_SYNC 1
-#define GPR_POSIX_TIME 1
-#define GPR_HAS_PTHREAD_H 1
-#define GPR_GETPID_IN_UNISTD_H 1
-#ifdef _LP64
-#define GPR_ARCH_64 1
-#else /* _LP64 */
-#define GPR_ARCH_32 1
-#endif /* _LP64 */
-#include
#elif defined(ANDROID) || defined(__ANDROID__)
#define GPR_PLATFORM_STRING "android"
#define GPR_ANDROID 1
diff --git a/include/grpcpp/impl/codegen/client_callback_impl.h b/include/grpcpp/impl/codegen/client_callback_impl.h
index 8e683743e06..bed52fe6a80 100644
--- a/include/grpcpp/impl/codegen/client_callback_impl.h
+++ b/include/grpcpp/impl/codegen/client_callback_impl.h
@@ -101,6 +101,29 @@ class CallbackUnaryCallImpl {
call.PerformOps(ops);
}
};
+
+// Base class for public API classes.
+class ClientReactor {
+ public:
+ /// Called by the library when all operations associated with this RPC have
+ /// completed and all Holds have been removed. OnDone provides the RPC status
+ /// outcome for both successful and failed RPCs. If it is never called on an
+ /// RPC, it indicates an application-level problem (like failure to remove a
+ /// hold).
+ ///
+ /// \param[in] s The status outcome of this RPC
+ virtual void OnDone(const ::grpc::Status& /*s*/) = 0;
+
+ /// InternalScheduleOnDone is not part of the API and is not meant to be
+ /// overridden. It is virtual to allow successful builds for certain bazel
+ /// build users that only want to depend on gRPC codegen headers and not the
+ /// full library (although this is not a generally-supported option). Although
+ /// the virtual call is slower than a direct call, this function is
+ /// heavyweight and the cost of the virtual call is not much in comparison.
+ /// This function may be removed or devirtualized in the future.
+ virtual void InternalScheduleOnDone(::grpc::Status s);
+};
+
} // namespace internal
// Forward declarations
@@ -189,7 +212,7 @@ class ClientCallbackUnary {
/// \a ClientBidiReactor is the interface for a bidirectional streaming RPC.
template
-class ClientBidiReactor {
+class ClientBidiReactor : public internal::ClientReactor {
public:
virtual ~ClientBidiReactor() {}
@@ -282,7 +305,7 @@ class ClientBidiReactor {
/// (like failure to remove a hold).
///
/// \param[in] s The status outcome of this RPC
- virtual void OnDone(const ::grpc::Status& /*s*/) {}
+ void OnDone(const ::grpc::Status& /*s*/) override {}
/// Notifies the application that a read of initial metadata from the
/// server is done. If the application chooses not to implement this method,
@@ -327,7 +350,7 @@ class ClientBidiReactor {
/// \a ClientReadReactor is the interface for a server-streaming RPC.
/// All public methods behave as in ClientBidiReactor.
template
-class ClientReadReactor {
+class ClientReadReactor : public internal::ClientReactor {
public:
virtual ~ClientReadReactor() {}
@@ -341,7 +364,7 @@ class ClientReadReactor {
}
void RemoveHold() { reader_->RemoveHold(); }
- virtual void OnDone(const ::grpc::Status& /*s*/) {}
+ void OnDone(const ::grpc::Status& /*s*/) override {}
virtual void OnReadInitialMetadataDone(bool /*ok*/) {}
virtual void OnReadDone(bool /*ok*/) {}
@@ -354,7 +377,7 @@ class ClientReadReactor {
/// \a ClientWriteReactor is the interface for a client-streaming RPC.
/// All public methods behave as in ClientBidiReactor.
template
-class ClientWriteReactor {
+class ClientWriteReactor : public internal::ClientReactor {
public:
virtual ~ClientWriteReactor() {}
@@ -377,7 +400,7 @@ class ClientWriteReactor {
}
void RemoveHold() { writer_->RemoveHold(); }
- virtual void OnDone(const ::grpc::Status& /*s*/) {}
+ void OnDone(const ::grpc::Status& /*s*/) override {}
virtual void OnReadInitialMetadataDone(bool /*ok*/) {}
virtual void OnWriteDone(bool /*ok*/) {}
virtual void OnWritesDoneDone(bool /*ok*/) {}
@@ -385,6 +408,7 @@ class ClientWriteReactor {
private:
friend class ClientCallbackWriter;
void BindWriter(ClientCallbackWriter* writer) { writer_ = writer; }
+
ClientCallbackWriter* writer_;
};
@@ -399,12 +423,12 @@ class ClientWriteReactor {
/// call (that is part of the unary call itself) and there is no reactor object
/// being created as a result of this call, we keep a consistent 2-phase
/// initiation API among all the reactor flavors.
-class ClientUnaryReactor {
+class ClientUnaryReactor : public internal::ClientReactor {
public:
virtual ~ClientUnaryReactor() {}
void StartCall() { call_->StartCall(); }
- virtual void OnDone(const ::grpc::Status& /*s*/) {}
+ void OnDone(const ::grpc::Status& /*s*/) override {}
virtual void OnReadInitialMetadataDone(bool /*ok*/) {}
private:
@@ -444,93 +468,56 @@ class ClientCallbackReaderWriterImpl
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
- void MaybeFinish() {
- if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
- 1, std::memory_order_acq_rel) == 1)) {
- ::grpc::Status s = std::move(finish_status_);
- auto* reactor = reactor_;
- auto* call = call_.call();
- this->~ClientCallbackReaderWriterImpl();
- ::grpc::g_core_codegen_interface->grpc_call_unref(call);
- reactor->OnDone(s);
- }
- }
-
void StartCall() override {
// This call initiates two batches, plus any backlog, each with a callback
// 1. Send initial metadata (unless corked) + recv initial metadata
// 2. Any read backlog
// 3. Any write backlog
- // 4. Recv trailing metadata, on_completion callback
- started_ = true;
-
- start_tag_.Set(call_.call(),
- [this](bool ok) {
- reactor_->OnReadInitialMetadataDone(ok);
- MaybeFinish();
- },
- &start_ops_, /*can_inline=*/false);
+ // 4. Recv trailing metadata (unless corked)
if (!start_corked_) {
start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
context_->initial_metadata_flags());
}
- start_ops_.RecvInitialMetadata(context_);
- start_ops_.set_core_cq_tag(&start_tag_);
- call_.PerformOps(&start_ops_);
-
- // Also set up the read and write tags so that they don't have to be set up
- // each time
- write_tag_.Set(call_.call(),
- [this](bool ok) {
- reactor_->OnWriteDone(ok);
- MaybeFinish();
- },
- &write_ops_, /*can_inline=*/false);
- write_ops_.set_core_cq_tag(&write_tag_);
-
- read_tag_.Set(call_.call(),
- [this](bool ok) {
- reactor_->OnReadDone(ok);
- MaybeFinish();
- },
- &read_ops_, /*can_inline=*/false);
- read_ops_.set_core_cq_tag(&read_tag_);
- if (read_ops_at_start_) {
- call_.PerformOps(&read_ops_);
- }
- if (write_ops_at_start_) {
- call_.PerformOps(&write_ops_);
- }
+ call_.PerformOps(&start_ops_);
- if (writes_done_ops_at_start_) {
- call_.PerformOps(&writes_done_ops_);
+ {
+ grpc::internal::MutexLock lock(&start_mu_);
+
+ if (backlog_.read_ops) {
+ call_.PerformOps(&read_ops_);
+ }
+ if (backlog_.write_ops) {
+ call_.PerformOps(&write_ops_);
+ }
+ if (backlog_.writes_done_ops) {
+ call_.PerformOps(&writes_done_ops_);
+ }
+ call_.PerformOps(&finish_ops_);
+ // The last thing in this critical section is to set started_ so that it
+ // can be used lock-free as well.
+ started_.store(true, std::memory_order_release);
}
-
- finish_tag_.Set(call_.call(), [this](bool /*ok*/) { MaybeFinish(); },
- &finish_ops_, /*can_inline=*/false);
- finish_ops_.ClientRecvStatus(context_, &finish_status_);
- finish_ops_.set_core_cq_tag(&finish_tag_);
- call_.PerformOps(&finish_ops_);
+ // MaybeFinish outside the lock to make sure that destruction of this object
+ // doesn't take place while holding the lock (which would cause the lock to
+ // be released after destruction)
+ this->MaybeFinish(/*from_reaction=*/false);
}
void Read(Response* msg) override {
read_ops_.RecvMessage(msg);
callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
- if (started_) {
- call_.PerformOps(&read_ops_);
- } else {
- read_ops_at_start_ = true;
+ if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
+ grpc::internal::MutexLock lock(&start_mu_);
+ if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
+ backlog_.read_ops = true;
+ return;
+ }
}
+ call_.PerformOps(&read_ops_);
}
void Write(const Request* msg, ::grpc::WriteOptions options) override {
- if (start_corked_) {
- write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
- context_->initial_metadata_flags());
- start_corked_ = false;
- }
-
if (options.is_last_message()) {
options.set_buffer_hint();
write_ops_.ClientSendClose();
@@ -538,38 +525,50 @@ class ClientCallbackReaderWriterImpl
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg, options).ok());
callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
- if (started_) {
- call_.PerformOps(&write_ops_);
- } else {
- write_ops_at_start_ = true;
+ if (GPR_UNLIKELY(corked_write_needed_)) {
+ write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+ context_->initial_metadata_flags());
+ corked_write_needed_ = false;
+ }
+
+ if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
+ grpc::internal::MutexLock lock(&start_mu_);
+ if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
+ backlog_.write_ops = true;
+ return;
+ }
}
+ call_.PerformOps(&write_ops_);
}
void WritesDone() override {
- if (start_corked_) {
- writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
- context_->initial_metadata_flags());
- start_corked_ = false;
- }
writes_done_ops_.ClientSendClose();
writes_done_tag_.Set(call_.call(),
[this](bool ok) {
reactor_->OnWritesDoneDone(ok);
- MaybeFinish();
+ MaybeFinish(/*from_reaction=*/true);
},
&writes_done_ops_, /*can_inline=*/false);
writes_done_ops_.set_core_cq_tag(&writes_done_tag_);
callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
- if (started_) {
- call_.PerformOps(&writes_done_ops_);
- } else {
- writes_done_ops_at_start_ = true;
+ if (GPR_UNLIKELY(corked_write_needed_)) {
+ writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+ context_->initial_metadata_flags());
+ corked_write_needed_ = false;
+ }
+ if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
+ grpc::internal::MutexLock lock(&start_mu_);
+ if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
+ backlog_.writes_done_ops = true;
+ return;
+ }
}
+ call_.PerformOps(&writes_done_ops_);
}
void AddHold(int holds) override {
callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
}
- void RemoveHold() override { MaybeFinish(); }
+ void RemoveHold() override { MaybeFinish(/*from_reaction=*/false); }
private:
friend class ClientCallbackReaderWriterFactory;
@@ -580,8 +579,66 @@ class ClientCallbackReaderWriterImpl
: context_(context),
call_(call),
reactor_(reactor),
- start_corked_(context_->initial_metadata_corked_) {
+ start_corked_(context_->initial_metadata_corked_),
+ corked_write_needed_(start_corked_) {
this->BindReactor(reactor);
+
+ // Set up the unchanging parts of the start, read, and write tags and ops.
+ start_tag_.Set(call_.call(),
+ [this](bool ok) {
+ reactor_->OnReadInitialMetadataDone(ok);
+ MaybeFinish(/*from_reaction=*/true);
+ },
+ &start_ops_, /*can_inline=*/false);
+ start_ops_.RecvInitialMetadata(context_);
+ start_ops_.set_core_cq_tag(&start_tag_);
+
+ write_tag_.Set(call_.call(),
+ [this](bool ok) {
+ reactor_->OnWriteDone(ok);
+ MaybeFinish(/*from_reaction=*/true);
+ },
+ &write_ops_, /*can_inline=*/false);
+ write_ops_.set_core_cq_tag(&write_tag_);
+
+ read_tag_.Set(call_.call(),
+ [this](bool ok) {
+ reactor_->OnReadDone(ok);
+ MaybeFinish(/*from_reaction=*/true);
+ },
+ &read_ops_, /*can_inline=*/false);
+ read_ops_.set_core_cq_tag(&read_tag_);
+
+ // Also set up the Finish tag and op set.
+ finish_tag_.Set(
+ call_.call(),
+ [this](bool /*ok*/) { MaybeFinish(/*from_reaction=*/true); },
+ &finish_ops_,
+ /*can_inline=*/false);
+ finish_ops_.ClientRecvStatus(context_, &finish_status_);
+ finish_ops_.set_core_cq_tag(&finish_tag_);
+ }
+
+ // MaybeFinish can be called from reactions or from user-initiated operations
+ // like StartCall or RemoveHold. If this is the last operation or hold on this
+ // object, it will invoke the OnDone reaction. If MaybeFinish was called from
+ // a reaction, it can call OnDone directly. If not, it would need to schedule
+ // OnDone onto an executor thread to avoid the possibility of deadlocking with
+ // any locks in the user code that invoked it.
+ void MaybeFinish(bool from_reaction) {
+ if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
+ 1, std::memory_order_acq_rel) == 1)) {
+ ::grpc::Status s = std::move(finish_status_);
+ auto* reactor = reactor_;
+ auto* call = call_.call();
+ this->~ClientCallbackReaderWriterImpl();
+ ::grpc::g_core_codegen_interface->grpc_call_unref(call);
+ if (GPR_LIKELY(from_reaction)) {
+ reactor->OnDone(s);
+ } else {
+ reactor->InternalScheduleOnDone(std::move(s));
+ }
+ }
}
::grpc_impl::ClientContext* const context_;
@@ -592,7 +649,9 @@ class ClientCallbackReaderWriterImpl
grpc::internal::CallOpRecvInitialMetadata>
start_ops_;
grpc::internal::CallbackWithSuccessTag start_tag_;
- bool start_corked_;
+ const bool start_corked_;
+ bool corked_write_needed_; // no lock needed since only accessed in
+ // Write/WritesDone which cannot be concurrent
grpc::internal::CallOpSet finish_ops_;
grpc::internal::CallbackWithSuccessTag finish_tag_;
@@ -603,22 +662,27 @@ class ClientCallbackReaderWriterImpl
grpc::internal::CallOpClientSendClose>
write_ops_;
grpc::internal::CallbackWithSuccessTag write_tag_;
- bool write_ops_at_start_{false};
grpc::internal::CallOpSet
writes_done_ops_;
grpc::internal::CallbackWithSuccessTag writes_done_tag_;
- bool writes_done_ops_at_start_{false};
grpc::internal::CallOpSet>
read_ops_;
grpc::internal::CallbackWithSuccessTag read_tag_;
- bool read_ops_at_start_{false};
- // Minimum of 2 callbacks to pre-register for start and finish
- std::atomic callbacks_outstanding_{2};
- bool started_{false};
+ struct StartCallBacklog {
+ bool write_ops = false;
+ bool writes_done_ops = false;
+ bool read_ops = false;
+ };
+ StartCallBacklog backlog_ /* GUARDED_BY(start_mu_) */;
+
+ // Minimum of 3 callbacks to pre-register for start ops, StartCall, and finish
+ std::atomic callbacks_outstanding_{3};
+ std::atomic_bool started_{false};
+ grpc::internal::Mutex start_mu_;
};
template
@@ -654,29 +718,16 @@ class ClientCallbackReaderImpl : public ClientCallbackReader {
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
- void MaybeFinish() {
- if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
- 1, std::memory_order_acq_rel) == 1)) {
- ::grpc::Status s = std::move(finish_status_);
- auto* reactor = reactor_;
- auto* call = call_.call();
- this->~ClientCallbackReaderImpl();
- ::grpc::g_core_codegen_interface->grpc_call_unref(call);
- reactor->OnDone(s);
- }
- }
-
void StartCall() override {
// This call initiates two batches, plus any backlog, each with a callback
// 1. Send initial metadata (unless corked) + recv initial metadata
// 2. Any backlog
- // 3. Recv trailing metadata, on_completion callback
- started_ = true;
+ // 3. Recv trailing metadata
start_tag_.Set(call_.call(),
[this](bool ok) {
reactor_->OnReadInitialMetadataDone(ok);
- MaybeFinish();
+ MaybeFinish(/*from_reaction=*/true);
},
&start_ops_, /*can_inline=*/false);
start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
@@ -689,16 +740,23 @@ class ClientCallbackReaderImpl : public ClientCallbackReader {
read_tag_.Set(call_.call(),
[this](bool ok) {
reactor_->OnReadDone(ok);
- MaybeFinish();
+ MaybeFinish(/*from_reaction=*/true);
},
&read_ops_, /*can_inline=*/false);
read_ops_.set_core_cq_tag(&read_tag_);
- if (read_ops_at_start_) {
- call_.PerformOps(&read_ops_);
+
+ {
+ grpc::internal::MutexLock lock(&start_mu_);
+ if (backlog_.read_ops) {
+ call_.PerformOps(&read_ops_);
+ }
+ started_.store(true, std::memory_order_release);
}
- finish_tag_.Set(call_.call(), [this](bool /*ok*/) { MaybeFinish(); },
- &finish_ops_, /*can_inline=*/false);
+ finish_tag_.Set(
+ call_.call(),
+ [this](bool /*ok*/) { MaybeFinish(/*from_reaction=*/true); },
+ &finish_ops_, /*can_inline=*/false);
finish_ops_.ClientRecvStatus(context_, &finish_status_);
finish_ops_.set_core_cq_tag(&finish_tag_);
call_.PerformOps(&finish_ops_);
@@ -707,17 +765,20 @@ class ClientCallbackReaderImpl : public ClientCallbackReader {
void Read(Response* msg) override {
read_ops_.RecvMessage(msg);
callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
- if (started_) {
- call_.PerformOps(&read_ops_);
- } else {
- read_ops_at_start_ = true;
+ if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
+ grpc::internal::MutexLock lock(&start_mu_);
+ if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
+ backlog_.read_ops = true;
+ return;
+ }
}
+ call_.PerformOps(&read_ops_);
}
void AddHold(int holds) override {
callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
}
- void RemoveHold() override { MaybeFinish(); }
+ void RemoveHold() override { MaybeFinish(/*from_reaction=*/false); }
private:
friend class ClientCallbackReaderFactory;
@@ -734,6 +795,23 @@ class ClientCallbackReaderImpl : public ClientCallbackReader {
start_ops_.ClientSendClose();
}
+ // MaybeFinish behaves as in ClientCallbackReaderWriterImpl.
+ void MaybeFinish(bool from_reaction) {
+ if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
+ 1, std::memory_order_acq_rel) == 1)) {
+ ::grpc::Status s = std::move(finish_status_);
+ auto* reactor = reactor_;
+ auto* call = call_.call();
+ this->~ClientCallbackReaderImpl();
+ ::grpc::g_core_codegen_interface->grpc_call_unref(call);
+ if (GPR_LIKELY(from_reaction)) {
+ reactor->OnDone(s);
+ } else {
+ reactor->InternalScheduleOnDone(std::move(s));
+ }
+ }
+ }
+
::grpc_impl::ClientContext* const context_;
grpc::internal::Call call_;
ClientReadReactor* const reactor_;
@@ -752,11 +830,16 @@ class ClientCallbackReaderImpl : public ClientCallbackReader {
grpc::internal::CallOpSet>
read_ops_;
grpc::internal::CallbackWithSuccessTag read_tag_;
- bool read_ops_at_start_{false};
+
+ struct StartCallBacklog {
+ bool read_ops = false;
+ };
+ StartCallBacklog backlog_ /* GUARDED_BY(start_mu_) */;
// Minimum of 2 callbacks to pre-register for start and finish
std::atomic callbacks_outstanding_{2};
- bool started_{false};
+ std::atomic_bool started_{false};
+ grpc::internal::Mutex start_mu_;
};
template
@@ -793,110 +876,94 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter {
// there are no tests catching the compiler warning.
static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); }
- void MaybeFinish() {
- if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
- 1, std::memory_order_acq_rel) == 1)) {
- ::grpc::Status s = std::move(finish_status_);
- auto* reactor = reactor_;
- auto* call = call_.call();
- this->~ClientCallbackWriterImpl();
- ::grpc::g_core_codegen_interface->grpc_call_unref(call);
- reactor->OnDone(s);
- }
- }
-
void StartCall() override {
// This call initiates two batches, plus any backlog, each with a callback
// 1. Send initial metadata (unless corked) + recv initial metadata
// 2. Any backlog
- // 3. Recv trailing metadata, on_completion callback
- started_ = true;
+ // 3. Recv trailing metadata
- start_tag_.Set(call_.call(),
- [this](bool ok) {
- reactor_->OnReadInitialMetadataDone(ok);
- MaybeFinish();
- },
- &start_ops_, /*can_inline=*/false);
if (!start_corked_) {
start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
context_->initial_metadata_flags());
}
- start_ops_.RecvInitialMetadata(context_);
- start_ops_.set_core_cq_tag(&start_tag_);
call_.PerformOps(&start_ops_);
- // Also set up the read and write tags so that they don't have to be set up
- // each time
- write_tag_.Set(call_.call(),
- [this](bool ok) {
- reactor_->OnWriteDone(ok);
- MaybeFinish();
- },
- &write_ops_, /*can_inline=*/false);
- write_ops_.set_core_cq_tag(&write_tag_);
-
- if (write_ops_at_start_) {
- call_.PerformOps(&write_ops_);
+ {
+ grpc::internal::MutexLock lock(&start_mu_);
+
+ if (backlog_.write_ops) {
+ call_.PerformOps(&write_ops_);
+ }
+ if (backlog_.writes_done_ops) {
+ call_.PerformOps(&writes_done_ops_);
+ }
+ call_.PerformOps(&finish_ops_);
+ // The last thing in this critical section is to set started_ so that it
+ // can be used lock-free as well.
+ started_.store(true, std::memory_order_release);
}
-
- if (writes_done_ops_at_start_) {
- call_.PerformOps(&writes_done_ops_);
- }
-
- finish_tag_.Set(call_.call(), [this](bool /*ok*/) { MaybeFinish(); },
- &finish_ops_, /*can_inline=*/false);
- finish_ops_.ClientRecvStatus(context_, &finish_status_);
- finish_ops_.set_core_cq_tag(&finish_tag_);
- call_.PerformOps(&finish_ops_);
+ // MaybeFinish outside the lock to make sure that destruction of this object
+ // doesn't take place while holding the lock (which would cause the lock to
+ // be released after destruction)
+ this->MaybeFinish(/*from_reaction=*/false);
}
void Write(const Request* msg, ::grpc::WriteOptions options) override {
- if (start_corked_) {
- write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
- context_->initial_metadata_flags());
- start_corked_ = false;
- }
-
- if (options.is_last_message()) {
+ if (GPR_UNLIKELY(options.is_last_message())) {
options.set_buffer_hint();
write_ops_.ClientSendClose();
}
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg, options).ok());
callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
- if (started_) {
- call_.PerformOps(&write_ops_);
- } else {
- write_ops_at_start_ = true;
+
+ if (GPR_UNLIKELY(corked_write_needed_)) {
+ write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+ context_->initial_metadata_flags());
+ corked_write_needed_ = false;
}
+
+ if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
+ grpc::internal::MutexLock lock(&start_mu_);
+ if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
+ backlog_.write_ops = true;
+ return;
+ }
+ }
+ call_.PerformOps(&write_ops_);
}
+
void WritesDone() override {
- if (start_corked_) {
- writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
- context_->initial_metadata_flags());
- start_corked_ = false;
- }
writes_done_ops_.ClientSendClose();
writes_done_tag_.Set(call_.call(),
[this](bool ok) {
reactor_->OnWritesDoneDone(ok);
- MaybeFinish();
+ MaybeFinish(/*from_reaction=*/true);
},
&writes_done_ops_, /*can_inline=*/false);
writes_done_ops_.set_core_cq_tag(&writes_done_tag_);
callbacks_outstanding_.fetch_add(1, std::memory_order_relaxed);
- if (started_) {
- call_.PerformOps(&writes_done_ops_);
- } else {
- writes_done_ops_at_start_ = true;
+
+ if (GPR_UNLIKELY(corked_write_needed_)) {
+ writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+ context_->initial_metadata_flags());
+ corked_write_needed_ = false;
+ }
+
+ if (GPR_UNLIKELY(!started_.load(std::memory_order_acquire))) {
+ grpc::internal::MutexLock lock(&start_mu_);
+ if (GPR_LIKELY(!started_.load(std::memory_order_relaxed))) {
+ backlog_.writes_done_ops = true;
+ return;
+ }
}
+ call_.PerformOps(&writes_done_ops_);
}
void AddHold(int holds) override {
callbacks_outstanding_.fetch_add(holds, std::memory_order_relaxed);
}
- void RemoveHold() override { MaybeFinish(); }
+ void RemoveHold() override { MaybeFinish(/*from_reaction=*/false); }
private:
friend class ClientCallbackWriterFactory;
@@ -909,10 +976,55 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter {
: context_(context),
call_(call),
reactor_(reactor),
- start_corked_(context_->initial_metadata_corked_) {
+ start_corked_(context_->initial_metadata_corked_),
+ corked_write_needed_(start_corked_) {
this->BindReactor(reactor);
+
+ // Set up the unchanging parts of the start and write tags and ops.
+ start_tag_.Set(call_.call(),
+ [this](bool ok) {
+ reactor_->OnReadInitialMetadataDone(ok);
+ MaybeFinish(/*from_reaction=*/true);
+ },
+ &start_ops_, /*can_inline=*/false);
+ start_ops_.RecvInitialMetadata(context_);
+ start_ops_.set_core_cq_tag(&start_tag_);
+
+ write_tag_.Set(call_.call(),
+ [this](bool ok) {
+ reactor_->OnWriteDone(ok);
+ MaybeFinish(/*from_reaction=*/true);
+ },
+ &write_ops_, /*can_inline=*/false);
+ write_ops_.set_core_cq_tag(&write_tag_);
+
+ // Also set up the Finish tag and op set.
finish_ops_.RecvMessage(response);
finish_ops_.AllowNoMessage();
+ finish_tag_.Set(
+ call_.call(),
+ [this](bool /*ok*/) { MaybeFinish(/*from_reaction=*/true); },
+ &finish_ops_,
+ /*can_inline=*/false);
+ finish_ops_.ClientRecvStatus(context_, &finish_status_);
+ finish_ops_.set_core_cq_tag(&finish_tag_);
+ }
+
+ // MaybeFinish behaves as in ClientCallbackReaderWriterImpl.
+ void MaybeFinish(bool from_reaction) {
+ if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
+ 1, std::memory_order_acq_rel) == 1)) {
+ ::grpc::Status s = std::move(finish_status_);
+ auto* reactor = reactor_;
+ auto* call = call_.call();
+ this->~ClientCallbackWriterImpl();
+ ::grpc::g_core_codegen_interface->grpc_call_unref(call);
+ if (GPR_LIKELY(from_reaction)) {
+ reactor->OnDone(s);
+ } else {
+ reactor->InternalScheduleOnDone(std::move(s));
+ }
+ }
}
::grpc_impl::ClientContext* const context_;
@@ -923,7 +1035,9 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter {
grpc::internal::CallOpRecvInitialMetadata>
start_ops_;
grpc::internal::CallbackWithSuccessTag start_tag_;
- bool start_corked_;
+ const bool start_corked_;
+ bool corked_write_needed_; // no lock needed since only accessed in
+ // Write/WritesDone which cannot be concurrent
grpc::internal::CallOpSet
@@ -936,17 +1050,22 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter {
grpc::internal::CallOpClientSendClose>
write_ops_;
grpc::internal::CallbackWithSuccessTag write_tag_;
- bool write_ops_at_start_{false};
grpc::internal::CallOpSet
writes_done_ops_;
grpc::internal::CallbackWithSuccessTag writes_done_tag_;
- bool writes_done_ops_at_start_{false};
- // Minimum of 2 callbacks to pre-register for start and finish
- std::atomic callbacks_outstanding_{2};
- bool started_{false};
+ struct StartCallBacklog {
+ bool write_ops = false;
+ bool writes_done_ops = false;
+ };
+ StartCallBacklog backlog_ /* GUARDED_BY(start_mu_) */;
+
+ // Minimum of 3 callbacks to pre-register for start ops, StartCall, and finish
+ std::atomic callbacks_outstanding_{3};
+ std::atomic_bool started_{false};
+ grpc::internal::Mutex start_mu_;
};
template
@@ -985,7 +1104,6 @@ class ClientCallbackUnaryImpl final : public ClientCallbackUnary {
// This call initiates two batches, each with a callback
// 1. Send initial metadata + write + writes done + recv initial metadata
// 2. Read message, recv trailing metadata
- started_ = true;
start_tag_.Set(call_.call(),
[this](bool ok) {
@@ -1000,24 +1118,13 @@ class ClientCallbackUnaryImpl final : public ClientCallbackUnary {
call_.PerformOps(&start_ops_);
finish_tag_.Set(call_.call(), [this](bool /*ok*/) { MaybeFinish(); },
- &finish_ops_, /*can_inline=*/false);
+ &finish_ops_,
+ /*can_inline=*/false);
finish_ops_.ClientRecvStatus(context_, &finish_status_);
finish_ops_.set_core_cq_tag(&finish_tag_);
call_.PerformOps(&finish_ops_);
}
- void MaybeFinish() {
- if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
- 1, std::memory_order_acq_rel) == 1)) {
- ::grpc::Status s = std::move(finish_status_);
- auto* reactor = reactor_;
- auto* call = call_.call();
- this->~ClientCallbackUnaryImpl();
- ::grpc::g_core_codegen_interface->grpc_call_unref(call);
- reactor->OnDone(s);
- }
- }
-
private:
friend class ClientCallbackUnaryFactory;
@@ -1034,6 +1141,21 @@ class ClientCallbackUnaryImpl final : public ClientCallbackUnary {
finish_ops_.AllowNoMessage();
}
+ // In the unary case, MaybeFinish is only ever invoked from a
+ // library-initiated reaction, so it will just directly call OnDone if this is
+ // the last reaction for this RPC.
+ void MaybeFinish() {
+ if (GPR_UNLIKELY(callbacks_outstanding_.fetch_sub(
+ 1, std::memory_order_acq_rel) == 1)) {
+ ::grpc::Status s = std::move(finish_status_);
+ auto* reactor = reactor_;
+ auto* call = call_.call();
+ this->~ClientCallbackUnaryImpl();
+ ::grpc::g_core_codegen_interface->grpc_call_unref(call);
+ reactor->OnDone(s);
+ }
+ }
+
::grpc_impl::ClientContext* const context_;
grpc::internal::Call call_;
ClientUnaryReactor* const reactor_;
@@ -1053,7 +1175,6 @@ class ClientCallbackUnaryImpl final : public ClientCallbackUnary {
// This call will have 2 callbacks: start and finish
std::atomic callbacks_outstanding_{2};
- bool started_{false};
};
class ClientCallbackUnaryFactory {
diff --git a/include/grpcpp/impl/codegen/server_context_impl.h b/include/grpcpp/impl/codegen/server_context_impl.h
index c5b874aa351..77d1c026b5d 100644
--- a/include/grpcpp/impl/codegen/server_context_impl.h
+++ b/include/grpcpp/impl/codegen/server_context_impl.h
@@ -174,6 +174,14 @@ class ServerContextBase {
/// ASCII-Value -> 1*( %x20-%x7E ) ; space and printable ASCII
void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
+ /// Return whether this RPC failed before the server could provide its status
+ /// back to the client. This could be because of explicit API cancellation
+ /// from the client-side or server-side, because of deadline exceeded, network
+ /// connection reset, HTTP/2 parameter configuration (e.g., max message size,
+ /// max connection age), etc. It does NOT include failure due to a non-OK
+ /// status return from the server application's request handler, including
+ /// Status::CANCELLED.
+ ///
/// IsCancelled is always safe to call when using sync or callback API.
/// When using async API, it is only safe to call IsCancelled after
/// the AsyncNotifyWhenDone tag has been delivered. Thread-safe.
@@ -181,10 +189,9 @@ class ServerContextBase {
/// 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.
+ /// 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.
@@ -192,6 +199,9 @@ class ServerContextBase {
/// error status code, it is ok to not return Status::CANCELLED even if
/// TryCancel() was called.
///
+ /// For reasons such as the above, it is generally preferred to explicitly
+ /// finish an RPC by returning Status::CANCELLED rather than using TryCancel.
+ ///
/// Note that TryCancel() does not change any of the tags that are pending
/// on the completion queue. All pending tags will still be delivered
/// (though their ok result may reflect the effect of cancellation).
diff --git a/package.xml b/package.xml
index 0166a778789..7553fe27739 100644
--- a/package.xml
+++ b/package.xml
@@ -97,6 +97,8 @@
+
+
@@ -179,6 +181,7 @@
+
diff --git a/requirements.bazel.txt b/requirements.bazel.txt
index 4d52beb9e11..09f161ab711 100644
--- a/requirements.bazel.txt
+++ b/requirements.bazel.txt
@@ -2,11 +2,11 @@
coverage>=4.0
cython>=0.29.8
enum34>=1.0.4
-protobuf>=3.5.0.post1
+protobuf>=3.5.0.post1, < 4.0dev
six>=1.10
wheel>=0.29
futures>=2.2.0
-google-auth>=1.0.0
+google-auth>=1.17.2
oauth2client==4.1.0
requests>=2.14.2
urllib3>=1.23
diff --git a/requirements.txt b/requirements.txt
index 27dd7d9f63b..00d91d3c13d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,6 +2,6 @@
coverage>=4.0
cython>=0.29.8
enum34>=1.0.4
-protobuf>=3.5.0.post1
+protobuf>=3.5.0.post1, < 4.0dev
six>=1.10
wheel>=0.29
diff --git a/setup.py b/setup.py
index 2379703eb7d..807d005899d 100644
--- a/setup.py
+++ b/setup.py
@@ -355,6 +355,9 @@ INSTALL_REQUIRES = (
"futures>=2.2.0; python_version<'3.2'",
"enum34>=1.0.4; python_version<'3.4'",
)
+EXTRAS_REQUIRES = {
+ 'protobuf': 'grpcio-tools>={version}'.format(version=grpc_version.VERSION),
+}
SETUP_REQUIRES = INSTALL_REQUIRES + (
'Sphinx~=1.8.1',
@@ -417,6 +420,7 @@ setuptools.setup(
package_dir=PACKAGE_DIRECTORIES,
package_data=PACKAGE_DATA,
install_requires=INSTALL_REQUIRES,
+ extras_require=EXTRAS_REQUIRES,
setup_requires=SETUP_REQUIRES,
cmdclass=COMMAND_CLASS,
)
diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc
index 2738a733d1f..5a5fa0e4082 100644
--- a/src/compiler/objective_c_plugin.cc
+++ b/src/compiler/objective_c_plugin.cc
@@ -52,15 +52,16 @@ inline ::grpc::string ImportProtoHeaders(
::grpc::string base_name = header;
grpc_generator::StripPrefix(&base_name, "google/protobuf/");
+ ::grpc::string file_name = "GPB" + base_name;
// create the import code snippet
::grpc::string framework_header =
- ::grpc::string(ProtobufLibraryFrameworkName) + "/" + base_name;
+ ::grpc::string(ProtobufLibraryFrameworkName) + "/" + file_name;
static const ::grpc::string kFrameworkImportsCondition =
"GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS";
return PreprocIfElse(kFrameworkImportsCondition,
indent + SystemImport(framework_header),
- indent + LocalImport(header));
+ indent + LocalImport(file_name));
}
} // namespace
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index d8af25d8f2f..8533be0fe2b 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -40,6 +40,7 @@
#include "src/core/ext/filters/client_channel/backend_metric.h"
#include "src/core/ext/filters/client_channel/backup_poller.h"
+#include "src/core/ext/filters/client_channel/config_selector.h"
#include "src/core/ext/filters/client_channel/global_subchannel_pool.h"
#include "src/core/ext/filters/client_channel/http_connect_handshaker.h"
#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
@@ -149,12 +150,16 @@ class ChannelData {
bool received_service_config_data() const {
return received_service_config_data_;
}
+ grpc_error* resolver_transient_failure_error() const {
+ return resolver_transient_failure_error_;
+ }
RefCountedPtr retry_throttle_data() const {
return retry_throttle_data_;
}
RefCountedPtr service_config() const {
return service_config_;
}
+ ConfigSelector* config_selector() const { return config_selector_.get(); }
WorkSerializer* work_serializer() const { return work_serializer_.get(); }
RefCountedPtr GetConnectedSubchannelInDataPlane(
@@ -234,6 +239,29 @@ class ChannelData {
Atomic done_{false};
};
+ class ChannelConfigHelper
+ : public ResolvingLoadBalancingPolicy::ChannelConfigHelper {
+ public:
+ explicit ChannelConfigHelper(ChannelData* chand) : chand_(chand) {}
+
+ ApplyServiceConfigResult ApplyServiceConfig(
+ const Resolver::Result& result) override;
+
+ void ApplyConfigSelector(
+ bool service_config_changed,
+ RefCountedPtr config_selector) override;
+
+ void ResolverTransientFailure(grpc_error* error) override;
+
+ private:
+ static void ProcessLbPolicy(
+ const Resolver::Result& resolver_result,
+ const internal::ClientChannelGlobalParsedConfig* parsed_service_config,
+ RefCountedPtr* lb_policy_config);
+
+ ChannelData* chand_;
+ };
+
ChannelData(grpc_channel_element_args* args, grpc_error** error);
~ChannelData();
@@ -241,30 +269,20 @@ class ChannelData {
grpc_connectivity_state state, const char* reason,
std::unique_ptr picker);
- void UpdateServiceConfigLocked(
- RefCountedPtr retry_throttle_data,
- RefCountedPtr service_config);
+ void UpdateServiceConfigInDataPlaneLocked(
+ bool service_config_changed,
+ RefCountedPtr config_selector);
void CreateResolvingLoadBalancingPolicyLocked();
void DestroyResolvingLoadBalancingPolicyLocked();
- static bool ProcessResolverResultLocked(
- void* arg, const Resolver::Result& result,
- RefCountedPtr* lb_policy_config,
- grpc_error** service_config_error, bool* no_valid_service_config);
-
grpc_error* DoPingLocked(grpc_transport_op* op);
void StartTransportOpLocked(grpc_transport_op* op);
void TryToConnectLocked();
- void ProcessLbPolicy(
- const Resolver::Result& resolver_result,
- const internal::ClientChannelGlobalParsedConfig* parsed_service_config,
- RefCountedPtr* lb_policy_config);
-
//
// Fields set at construction and never modified.
//
@@ -278,6 +296,7 @@ class ChannelData {
grpc_core::UniquePtr server_name_;
grpc_core::UniquePtr target_uri_;
channelz::ChannelNode* channelz_node_;
+ ChannelConfigHelper channel_config_helper_;
//
// Fields used in the data plane. Guarded by data_plane_mu.
@@ -286,9 +305,11 @@ class ChannelData {
std::unique_ptr picker_;
QueuedPick* queued_picks_ = nullptr; // Linked list of queued picks.
// Data from service config.
+ grpc_error* resolver_transient_failure_error_ = GRPC_ERROR_NONE;
bool received_service_config_data_ = false;
RefCountedPtr retry_throttle_data_;
RefCountedPtr service_config_;
+ RefCountedPtr config_selector_;
//
// Fields used in the control plane. Guarded by work_serializer.
@@ -300,6 +321,7 @@ class ChannelData {
ConnectivityStateTracker state_tracker_;
grpc_core::UniquePtr health_check_service_name_;
RefCountedPtr saved_service_config_;
+ RefCountedPtr saved_config_selector_;
bool received_first_resolver_result_ = false;
// The number of SubchannelWrapper instances referencing a given Subchannel.
std::map subchannel_refcount_map_;
@@ -352,9 +374,6 @@ class CallData {
RefCountedPtr subchannel_call() { return subchannel_call_; }
- // Invoked by channel for queued picks once resolver results are available.
- void MaybeApplyServiceConfigToCallLocked(grpc_call_element* elem);
-
// Invoked by channel for queued picks when the picker is updated.
static void PickSubchannel(void* arg, grpc_error* error);
@@ -742,13 +761,17 @@ class CallData {
void CreateSubchannelCall(grpc_call_element* elem);
// Invoked when a pick is completed, on both success or failure.
static void PickDone(void* arg, grpc_error* error);
- // Removes the call from the channel's list of queued picks.
- void RemoveCallFromQueuedPicksLocked(grpc_call_element* elem);
- // Adds the call to the channel's list of queued picks.
- void AddCallToQueuedPicksLocked(grpc_call_element* elem);
+ // Removes the call from the channel's list of queued picks if present.
+ void MaybeRemoveCallFromQueuedPicksLocked(grpc_call_element* elem);
+ // Adds the call to the channel's list of queued picks if not already present.
+ void MaybeAddCallToQueuedPicksLocked(grpc_call_element* elem);
// Applies service config to the call. Must be invoked once we know
// that the resolver has returned results to the channel.
- void ApplyServiceConfigToCallLocked(grpc_call_element* elem);
+ // If an error is returned, the error indicates the status with which
+ // the call should be failed.
+ grpc_error* ApplyServiceConfigToCallLocked(
+ grpc_call_element* elem, grpc_metadata_batch* initial_metadata);
+ void MaybeInvokeConfigSelectorCommitCallback();
// State for handling deadlines.
// The code in deadline_filter.c requires this to be the first field.
@@ -769,6 +792,7 @@ class CallData {
RefCountedPtr retry_throttle_data_;
const ClientChannelMethodParsedConfig* method_params_ = nullptr;
std::map call_attributes_;
+ std::function on_call_committed_;
RefCountedPtr subchannel_call_;
@@ -1335,6 +1359,180 @@ class ChannelData::ClientChannelControlHelper
ChannelData* chand_;
};
+//
+// ChannelData::ChannelConfigHelper
+//
+
+// Synchronous callback from ResolvingLoadBalancingPolicy to process a
+// resolver result update.
+ChannelData::ChannelConfigHelper::ApplyServiceConfigResult
+ChannelData::ChannelConfigHelper::ApplyServiceConfig(
+ const Resolver::Result& result) {
+ ApplyServiceConfigResult service_config_result;
+ RefCountedPtr service_config;
+ // If resolver did not return a service config or returned an invalid service
+ // config, we need a fallback service config.
+ if (result.service_config_error != GRPC_ERROR_NONE) {
+ // If the service config was invalid, then fallback to the saved service
+ // config. If there is no saved config either, use the default service
+ // config.
+ if (chand_->saved_service_config_ != nullptr) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
+ gpr_log(GPR_INFO,
+ "chand=%p: resolver returned invalid service config. "
+ "Continuing to use previous service config.",
+ chand_);
+ }
+ service_config = chand_->saved_service_config_;
+ } else if (chand_->default_service_config_ != nullptr) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
+ gpr_log(GPR_INFO,
+ "chand=%p: resolver returned invalid service config. Using "
+ "default service config provided by client API.",
+ chand_);
+ }
+ service_config = chand_->default_service_config_;
+ }
+ } else if (result.service_config == nullptr) {
+ if (chand_->default_service_config_ != nullptr) {
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
+ gpr_log(GPR_INFO,
+ "chand=%p: resolver returned no service config. Using default "
+ "service config provided by client API.",
+ chand_);
+ }
+ service_config = chand_->default_service_config_;
+ }
+ } else {
+ service_config = result.service_config;
+ }
+ service_config_result.service_config_error =
+ GRPC_ERROR_REF(result.service_config_error);
+ if (service_config == nullptr &&
+ result.service_config_error != GRPC_ERROR_NONE) {
+ service_config_result.no_valid_service_config = true;
+ return service_config_result;
+ }
+ // Process service config.
+ grpc_core::UniquePtr service_config_json;
+ const internal::ClientChannelGlobalParsedConfig* parsed_service_config =
+ nullptr;
+ if (service_config != nullptr) {
+ parsed_service_config =
+ static_cast(
+ service_config->GetGlobalParsedConfig(
+ internal::ClientChannelServiceConfigParser::ParserIndex()));
+ }
+ // Check if the config has changed.
+ service_config_result.service_config_changed =
+ ((service_config == nullptr) !=
+ (chand_->saved_service_config_ == nullptr)) ||
+ (service_config != nullptr &&
+ service_config->json_string() !=
+ chand_->saved_service_config_->json_string());
+ if (service_config_result.service_config_changed) {
+ service_config_json.reset(gpr_strdup(
+ service_config != nullptr ? service_config->json_string().c_str()
+ : ""));
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
+ gpr_log(GPR_INFO,
+ "chand=%p: resolver returned updated service config: \"%s\"",
+ chand_, service_config_json.get());
+ }
+ // Save health check service name.
+ if (service_config != nullptr) {
+ chand_->health_check_service_name_.reset(
+ gpr_strdup(parsed_service_config->health_check_service_name()));
+ } else {
+ chand_->health_check_service_name_.reset();
+ }
+ // Update health check service name used by existing subchannel wrappers.
+ for (auto* subchannel_wrapper : chand_->subchannel_wrappers_) {
+ subchannel_wrapper->UpdateHealthCheckServiceName(
+ grpc_core::UniquePtr(
+ gpr_strdup(chand_->health_check_service_name_.get())));
+ }
+ // Save service config.
+ chand_->saved_service_config_ = std::move(service_config);
+ }
+ // Find LB policy config.
+ ProcessLbPolicy(result, parsed_service_config,
+ &service_config_result.lb_policy_config);
+ grpc_core::UniquePtr lb_policy_name(
+ gpr_strdup((service_config_result.lb_policy_config)->name()));
+ // Swap out the data used by GetChannelInfo().
+ {
+ MutexLock lock(&chand_->info_mu_);
+ chand_->info_lb_policy_name_ = std::move(lb_policy_name);
+ if (service_config_json != nullptr) {
+ chand_->info_service_config_json_ = std::move(service_config_json);
+ }
+ }
+ // Return results.
+ return service_config_result;
+}
+
+void ChannelData::ChannelConfigHelper::ApplyConfigSelector(
+ bool service_config_changed,
+ RefCountedPtr config_selector) {
+ chand_->UpdateServiceConfigInDataPlaneLocked(service_config_changed,
+ std::move(config_selector));
+}
+
+void ChannelData::ChannelConfigHelper::ResolverTransientFailure(
+ grpc_error* error) {
+ MutexLock lock(&chand_->data_plane_mu_);
+ GRPC_ERROR_UNREF(chand_->resolver_transient_failure_error_);
+ chand_->resolver_transient_failure_error_ = error;
+}
+
+void ChannelData::ChannelConfigHelper::ProcessLbPolicy(
+ const Resolver::Result& resolver_result,
+ const internal::ClientChannelGlobalParsedConfig* parsed_service_config,
+ RefCountedPtr* lb_policy_config) {
+ // Prefer the LB policy config found in the service config.
+ if (parsed_service_config != nullptr &&
+ parsed_service_config->parsed_lb_config() != nullptr) {
+ *lb_policy_config = parsed_service_config->parsed_lb_config();
+ return;
+ }
+ // Try the deprecated LB policy name from the service config.
+ // If not, try the setting from channel args.
+ const char* policy_name = nullptr;
+ if (parsed_service_config != nullptr &&
+ !parsed_service_config->parsed_deprecated_lb_policy().empty()) {
+ policy_name = parsed_service_config->parsed_deprecated_lb_policy().c_str();
+ } else {
+ const grpc_arg* channel_arg =
+ grpc_channel_args_find(resolver_result.args, GRPC_ARG_LB_POLICY_NAME);
+ policy_name = grpc_channel_arg_get_string(channel_arg);
+ }
+ // Use pick_first if nothing was specified and we didn't select grpclb
+ // above.
+ if (policy_name == nullptr) policy_name = "pick_first";
+ // Now that we have the policy name, construct an empty config for it.
+ Json config_json = Json::Array{Json::Object{
+ {policy_name, Json::Object{}},
+ }};
+ grpc_error* parse_error = GRPC_ERROR_NONE;
+ *lb_policy_config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
+ config_json, &parse_error);
+ // The policy name came from one of three places:
+ // - The deprecated loadBalancingPolicy field in the service config,
+ // in which case the code in ClientChannelServiceConfigParser
+ // already verified that the policy does not require a config.
+ // - One of the hard-coded values here, all of which are known to not
+ // require a config.
+ // - A channel arg, in which case the application did something that
+ // is a misuse of our API.
+ // In the first two cases, these assertions will always be true. In
+ // the last case, this is probably fine for now.
+ // TODO(roth): If the last case becomes a problem, add better error
+ // handling here.
+ GPR_ASSERT(*lb_policy_config != nullptr);
+ GPR_ASSERT(parse_error == GRPC_ERROR_NONE);
+}
+
//
// ChannelData implementation
//
@@ -1393,6 +1591,7 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error)
client_channel_factory_(
ClientChannelFactory::GetFromChannelArgs(args->channel_args)),
channelz_node_(GetChannelzNode(args->channel_args)),
+ channel_config_helper_(this),
work_serializer_(std::make_shared()),
interested_parties_(grpc_pollset_set_create()),
subchannel_pool_(GetSubchannelPool(args->channel_args)),
@@ -1461,6 +1660,7 @@ ChannelData::~ChannelData() {
}
DestroyResolvingLoadBalancingPolicyLocked();
grpc_channel_args_destroy(channel_args_);
+ GRPC_ERROR_UNREF(resolver_transient_failure_error_);
// Stop backup polling.
grpc_client_channel_stop_backup_polling(interested_parties_);
grpc_pollset_set_destroy(interested_parties_);
@@ -1475,6 +1675,7 @@ void ChannelData::UpdateStateAndPickerLocked(
if (picker_ == nullptr) {
health_check_service_name_.reset();
saved_service_config_.reset();
+ saved_config_selector_.reset();
received_first_resolver_result_ = false;
}
// Update connectivity state.
@@ -1497,9 +1698,11 @@ void ChannelData::UpdateStateAndPickerLocked(
// - refs to subchannel wrappers in the keys of pending_subchannel_updates_
// - ref stored in retry_throttle_data_
// - ref stored in service_config_
+ // - ref stored in config_selector_
// - ownership of the existing picker in picker_
RefCountedPtr retry_throttle_data_to_unref;
RefCountedPtr service_config_to_unref;
+ RefCountedPtr config_selector_to_unref;
{
MutexLock lock(&data_plane_mu_);
// Handle subchannel updates.
@@ -1524,6 +1727,7 @@ void ChannelData::UpdateStateAndPickerLocked(
// Note: We save the objects to unref until after the lock is released.
retry_throttle_data_to_unref = std::move(retry_throttle_data_);
service_config_to_unref = std::move(service_config_);
+ config_selector_to_unref = std::move(config_selector_);
}
// Re-process queued picks.
for (QueuedPick* pick = queued_picks_; pick != nullptr; pick = pick->next) {
@@ -1540,24 +1744,72 @@ void ChannelData::UpdateStateAndPickerLocked(
pending_subchannel_updates_.clear();
}
-void ChannelData::UpdateServiceConfigLocked(
- RefCountedPtr retry_throttle_data,
- RefCountedPtr service_config) {
+void ChannelData::UpdateServiceConfigInDataPlaneLocked(
+ bool service_config_changed,
+ RefCountedPtr config_selector) {
+ // Check if ConfigSelector has changed.
+ const bool config_selector_changed =
+ saved_config_selector_ != config_selector;
+ saved_config_selector_ = config_selector;
+ // We want to set the service config at least once, even if the
+ // resolver does not return a config, because that ensures that we
+ // disable retries if they are not enabled in the service config.
+ // TODO(roth): Consider removing the received_first_resolver_result_ check
+ // when we implement transparent retries.
+ if (!service_config_changed && !config_selector_changed &&
+ received_first_resolver_result_) {
+ return;
+ }
+ received_first_resolver_result_ = true;
+ // Get retry throttle data from service config.
+ RefCountedPtr retry_throttle_data;
+ if (saved_service_config_ != nullptr) {
+ const internal::ClientChannelGlobalParsedConfig* parsed_service_config =
+ static_cast(
+ saved_service_config_->GetGlobalParsedConfig(
+ internal::ClientChannelServiceConfigParser::ParserIndex()));
+ if (parsed_service_config != nullptr) {
+ absl::optional
+ retry_throttle_config = parsed_service_config->retry_throttling();
+ if (retry_throttle_config.has_value()) {
+ retry_throttle_data =
+ internal::ServerRetryThrottleMap::GetDataForServer(
+ server_name_.get(),
+ retry_throttle_config.value().max_milli_tokens,
+ retry_throttle_config.value().milli_token_ratio);
+ }
+ }
+ }
+ // Create default config selector if not provided by resolver.
+ if (config_selector == nullptr) {
+ config_selector =
+ MakeRefCounted(saved_service_config_);
+ }
// Grab data plane lock to update service config.
//
// We defer unreffing the old values (and deallocating memory) until
// after releasing the lock to keep the critical section small.
+ RefCountedPtr service_config_to_unref = saved_service_config_;
+ RefCountedPtr config_selector_to_unref =
+ std::move(config_selector);
{
MutexLock lock(&data_plane_mu_);
+ GRPC_ERROR_UNREF(resolver_transient_failure_error_);
+ resolver_transient_failure_error_ = GRPC_ERROR_NONE;
// Update service config.
received_service_config_data_ = true;
// Old values will be unreffed after lock is released.
retry_throttle_data_.swap(retry_throttle_data);
- service_config_.swap(service_config);
- // Apply service config to queued picks.
+ service_config_.swap(service_config_to_unref);
+ config_selector_.swap(config_selector_to_unref);
+ // Re-process queued picks.
for (QueuedPick* pick = queued_picks_; pick != nullptr; pick = pick->next) {
- CallData* calld = static_cast(pick->elem->call_data);
- calld->MaybeApplyServiceConfigToCallLocked(pick->elem);
+ grpc_call_element* elem = pick->elem;
+ CallData* calld = static_cast(elem->call_data);
+ grpc_error* error = GRPC_ERROR_NONE;
+ if (calld->PickSubchannelLocked(elem, &error)) {
+ calld->AsyncPickDone(elem, error);
+ }
}
}
// Old values will be unreffed after lock is released when they go out
@@ -1574,7 +1826,7 @@ void ChannelData::CreateResolvingLoadBalancingPolicyLocked() {
grpc_core::UniquePtr target_uri(gpr_strdup(target_uri_.get()));
resolving_lb_policy_.reset(new ResolvingLoadBalancingPolicy(
std::move(lb_args), &grpc_client_channel_routing_trace,
- std::move(target_uri), ProcessResolverResultLocked, this));
+ std::move(target_uri), &channel_config_helper_));
grpc_pollset_set_add_pollset_set(resolving_lb_policy_->interested_parties(),
interested_parties_);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
@@ -1591,180 +1843,6 @@ void ChannelData::DestroyResolvingLoadBalancingPolicyLocked() {
}
}
-void ChannelData::ProcessLbPolicy(
- const Resolver::Result& resolver_result,
- const internal::ClientChannelGlobalParsedConfig* parsed_service_config,
- RefCountedPtr* lb_policy_config) {
- // Prefer the LB policy config found in the service config.
- if (parsed_service_config != nullptr &&
- parsed_service_config->parsed_lb_config() != nullptr) {
- *lb_policy_config = parsed_service_config->parsed_lb_config();
- return;
- }
- // Try the deprecated LB policy name from the service config.
- // If not, try the setting from channel args.
- const char* policy_name = nullptr;
- if (parsed_service_config != nullptr &&
- !parsed_service_config->parsed_deprecated_lb_policy().empty()) {
- policy_name = parsed_service_config->parsed_deprecated_lb_policy().c_str();
- } else {
- const grpc_arg* channel_arg =
- grpc_channel_args_find(resolver_result.args, GRPC_ARG_LB_POLICY_NAME);
- policy_name = grpc_channel_arg_get_string(channel_arg);
- }
- // Use pick_first if nothing was specified and we didn't select grpclb
- // above.
- if (policy_name == nullptr) policy_name = "pick_first";
- // Now that we have the policy name, construct an empty config for it.
- Json config_json = Json::Array{Json::Object{
- {policy_name, Json::Object{}},
- }};
- grpc_error* parse_error = GRPC_ERROR_NONE;
- *lb_policy_config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(
- config_json, &parse_error);
- // The policy name came from one of three places:
- // - The deprecated loadBalancingPolicy field in the service config,
- // in which case the code in ClientChannelServiceConfigParser
- // already verified that the policy does not require a config.
- // - One of the hard-coded values here, all of which are known to not
- // require a config.
- // - A channel arg, in which case the application did something that
- // is a misuse of our API.
- // In the first two cases, these assertions will always be true. In
- // the last case, this is probably fine for now.
- // TODO(roth): If the last case becomes a problem, add better error
- // handling here.
- GPR_ASSERT(*lb_policy_config != nullptr);
- GPR_ASSERT(parse_error == GRPC_ERROR_NONE);
-}
-
-// Synchronous callback from ResolvingLoadBalancingPolicy to process a
-// resolver result update.
-bool ChannelData::ProcessResolverResultLocked(
- void* arg, const Resolver::Result& result,
- RefCountedPtr* lb_policy_config,
- grpc_error** service_config_error, bool* no_valid_service_config) {
- ChannelData* chand = static_cast(arg);
- RefCountedPtr service_config;
- // If resolver did not return a service config or returned an invalid service
- // config, we need a fallback service config.
- if (result.service_config_error != GRPC_ERROR_NONE) {
- // If the service config was invalid, then fallback to the saved service
- // config. If there is no saved config either, use the default service
- // config.
- if (chand->saved_service_config_ != nullptr) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p: resolver returned invalid service config. "
- "Continuing to use previous service config.",
- chand);
- }
- service_config = chand->saved_service_config_;
- } else if (chand->default_service_config_ != nullptr) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p: resolver returned invalid service config. Using "
- "default service config provided by client API.",
- chand);
- }
- service_config = chand->default_service_config_;
- }
- } else if (result.service_config == nullptr) {
- if (chand->default_service_config_ != nullptr) {
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p: resolver returned no service config. Using default "
- "service config provided by client API.",
- chand);
- }
- service_config = chand->default_service_config_;
- }
- } else {
- service_config = result.service_config;
- }
- *service_config_error = GRPC_ERROR_REF(result.service_config_error);
- if (service_config == nullptr &&
- result.service_config_error != GRPC_ERROR_NONE) {
- *no_valid_service_config = true;
- return false;
- }
- // Process service config.
- grpc_core::UniquePtr service_config_json;
- const internal::ClientChannelGlobalParsedConfig* parsed_service_config =
- nullptr;
- if (service_config != nullptr) {
- parsed_service_config =
- static_cast(
- service_config->GetGlobalParsedConfig(
- internal::ClientChannelServiceConfigParser::ParserIndex()));
- }
- // Check if the config has changed.
- const bool service_config_changed =
- ((service_config == nullptr) !=
- (chand->saved_service_config_ == nullptr)) ||
- (service_config != nullptr &&
- service_config->json_string() !=
- chand->saved_service_config_->json_string());
- if (service_config_changed) {
- service_config_json.reset(gpr_strdup(
- service_config != nullptr ? service_config->json_string().c_str()
- : ""));
- if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
- gpr_log(GPR_INFO,
- "chand=%p: resolver returned updated service config: \"%s\"",
- chand, service_config_json.get());
- }
- // Save health check service name.
- if (service_config != nullptr) {
- chand->health_check_service_name_.reset(
- gpr_strdup(parsed_service_config->health_check_service_name()));
- } else {
- chand->health_check_service_name_.reset();
- }
- // Update health check service name used by existing subchannel wrappers.
- for (auto* subchannel_wrapper : chand->subchannel_wrappers_) {
- subchannel_wrapper->UpdateHealthCheckServiceName(
- grpc_core::UniquePtr(
- gpr_strdup(chand->health_check_service_name_.get())));
- }
- // Save service config.
- chand->saved_service_config_ = std::move(service_config);
- }
- // We want to set the service config at least once. This should not really be
- // needed, but we are doing it as a defensive approach. This can be removed,
- // if we feel it is unnecessary.
- if (service_config_changed || !chand->received_first_resolver_result_) {
- chand->received_first_resolver_result_ = true;
- RefCountedPtr retry_throttle_data;
- if (parsed_service_config != nullptr) {
- absl::optional
- retry_throttle_config = parsed_service_config->retry_throttling();
- if (retry_throttle_config.has_value()) {
- retry_throttle_data =
- internal::ServerRetryThrottleMap::GetDataForServer(
- chand->server_name_.get(),
- retry_throttle_config.value().max_milli_tokens,
- retry_throttle_config.value().milli_token_ratio);
- }
- }
- chand->UpdateServiceConfigLocked(std::move(retry_throttle_data),
- chand->saved_service_config_);
- }
- chand->ProcessLbPolicy(result, parsed_service_config, lb_policy_config);
- grpc_core::UniquePtr lb_policy_name(
- gpr_strdup((*lb_policy_config)->name()));
- // Swap out the data used by GetChannelInfo().
- {
- MutexLock lock(&chand->info_mu_);
- chand->info_lb_policy_name_ = std::move(lb_policy_name);
- if (service_config_json != nullptr) {
- chand->info_service_config_json_ = std::move(service_config_json);
- }
- }
- // Return results.
- return service_config_changed;
-}
-
grpc_error* ChannelData::DoPingLocked(grpc_transport_op* op) {
if (state_tracker_.state() != GRPC_CHANNEL_READY) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("channel not connected");
@@ -2807,6 +2885,7 @@ void CallData::RecvInitialMetadataReady(void* arg, grpc_error* error) {
}
// Received valid initial metadata, so commit the call.
calld->RetryCommit(elem, retry_state);
+ calld->MaybeInvokeConfigSelectorCommitCallback();
// Invoke the callback to return the result to the surface.
// Manually invoking a callback function; it does not take ownership of error.
calld->InvokeRecvInitialMetadataCallback(batch_data, error);
@@ -2893,6 +2972,7 @@ void CallData::RecvMessageReady(void* arg, grpc_error* error) {
}
// Received a valid message, so commit the call.
calld->RetryCommit(elem, retry_state);
+ calld->MaybeInvokeConfigSelectorCommitCallback();
// Invoke the callback to return the result to the surface.
// Manually invoking a callback function; it does not take ownership of error.
calld->InvokeRecvMessageCallback(batch_data, error);
@@ -3094,6 +3174,7 @@ void CallData::RecvTrailingMetadataReady(void* arg, grpc_error* error) {
}
// Not retrying, so commit the call.
calld->RetryCommit(elem, retry_state);
+ calld->MaybeInvokeConfigSelectorCommitCallback();
// Run any necessary closures.
calld->RunClosuresForCompletedCall(batch_data, GRPC_ERROR_REF(error));
}
@@ -3716,7 +3797,7 @@ class CallData::QueuedPickCanceller {
}
if (calld->pick_canceller_ == self && error != GRPC_ERROR_NONE) {
// Remove pick from list of queued picks.
- calld->RemoveCallFromQueuedPicksLocked(self->elem_);
+ calld->MaybeRemoveCallFromQueuedPicksLocked(self->elem_);
// Fail pending batches on the call.
calld->PendingBatchesFail(self->elem_, GRPC_ERROR_REF(error),
YieldCallCombinerIfPendingBatchesFound);
@@ -3729,7 +3810,8 @@ class CallData::QueuedPickCanceller {
grpc_closure closure_;
};
-void CallData::RemoveCallFromQueuedPicksLocked(grpc_call_element* elem) {
+void CallData::MaybeRemoveCallFromQueuedPicksLocked(grpc_call_element* elem) {
+ if (!pick_queued_) return;
auto* chand = static_cast(elem->channel_data);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
gpr_log(GPR_INFO, "chand=%p calld=%p: removing from queued picks list",
@@ -3741,7 +3823,8 @@ void CallData::RemoveCallFromQueuedPicksLocked(grpc_call_element* elem) {
pick_canceller_ = nullptr;
}
-void CallData::AddCallToQueuedPicksLocked(grpc_call_element* elem) {
+void CallData::MaybeAddCallToQueuedPicksLocked(grpc_call_element* elem) {
+ if (pick_queued_) return;
auto* chand = static_cast(elem->channel_data);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
gpr_log(GPR_INFO, "chand=%p calld=%p: adding to queued picks list", chand,
@@ -3754,23 +3837,29 @@ void CallData::AddCallToQueuedPicksLocked(grpc_call_element* elem) {
pick_canceller_ = new QueuedPickCanceller(elem);
}
-void CallData::ApplyServiceConfigToCallLocked(grpc_call_element* elem) {
+grpc_error* CallData::ApplyServiceConfigToCallLocked(
+ grpc_call_element* elem, grpc_metadata_batch* initial_metadata) {
ChannelData* chand = static_cast(elem->channel_data);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call",
chand, this);
}
+ ConfigSelector* config_selector = chand->config_selector();
auto service_config = chand->service_config();
if (service_config != nullptr) {
+ // Use the ConfigSelector to determine the config for the call.
+ ConfigSelector::CallConfig call_config =
+ config_selector->GetCallConfig({&path_, initial_metadata});
+ if (call_config.error != GRPC_ERROR_NONE) return call_config.error;
+ call_attributes_ = std::move(call_config.call_attributes);
+ on_call_committed_ = std::move(call_config.on_call_committed);
// Create a ServiceConfigCallData for the call. This stores a ref to the
// ServiceConfig and caches the right set of parsed configs to use for
// the call. The MethodConfig will store itself in the call context,
// so that it can be accessed by filters in the subchannel, and it
// will be cleaned up when the call ends.
- const auto* method_params_vector =
- service_config->GetMethodParsedConfigVector(path_);
auto* service_config_call_data = arena_->New(
- std::move(service_config), method_params_vector, call_context_);
+ std::move(service_config), call_config.method_configs, call_context_);
// Apply our own method params to the call.
method_params_ = static_cast(
service_config_call_data->GetMethodParsedConfig(
@@ -3812,16 +3901,13 @@ void CallData::ApplyServiceConfigToCallLocked(grpc_call_element* elem) {
if (method_params_ == nullptr || method_params_->retry_policy() == nullptr) {
enable_retries_ = false;
}
+ return GRPC_ERROR_NONE;
}
-void CallData::MaybeApplyServiceConfigToCallLocked(grpc_call_element* elem) {
- ChannelData* chand = static_cast(elem->channel_data);
- // Apply service config data to the call only once, and only if the
- // channel has the data available.
- if (GPR_LIKELY(chand->received_service_config_data() &&
- !service_config_applied_)) {
- service_config_applied_ = true;
- ApplyServiceConfigToCallLocked(elem);
+void CallData::MaybeInvokeConfigSelectorCommitCallback() {
+ if (on_call_committed_ != nullptr) {
+ on_call_committed_();
+ on_call_committed_ = nullptr;
}
}
@@ -3882,11 +3968,45 @@ bool CallData::PickSubchannelLocked(grpc_call_element* elem,
GRPC_ERROR_NONE);
// Queue the pick, so that it will be attempted once the channel
// becomes connected.
- AddCallToQueuedPicksLocked(elem);
+ MaybeAddCallToQueuedPicksLocked(elem);
+ return false;
+ }
+ grpc_metadata_batch* initial_metadata_batch =
+ seen_send_initial_metadata_
+ ? &send_initial_metadata_
+ : pending_batches_[0]
+ .batch->payload->send_initial_metadata.send_initial_metadata;
+ // Grab initial metadata flags so that we can check later if the call has
+ // wait_for_ready enabled.
+ const uint32_t send_initial_metadata_flags =
+ seen_send_initial_metadata_ ? send_initial_metadata_flags_
+ : pending_batches_[0]
+ .batch->payload->send_initial_metadata
+ .send_initial_metadata_flags;
+ // Avoid picking if we haven't yet received service config data.
+ if (GPR_UNLIKELY(!chand->received_service_config_data())) {
+ // If the resolver returned transient failure before returning the
+ // first service config, fail any non-wait_for_ready calls.
+ grpc_error* resolver_error = chand->resolver_transient_failure_error();
+ if (resolver_error != GRPC_ERROR_NONE &&
+ (send_initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) ==
+ 0) {
+ MaybeRemoveCallFromQueuedPicksLocked(elem);
+ *error = GRPC_ERROR_REF(resolver_error);
+ return true;
+ }
+ // Either the resolver has not yet returned a result, or it has
+ // returned transient failure but the call is wait_for_ready. In
+ // either case, queue the call.
+ MaybeAddCallToQueuedPicksLocked(elem);
return false;
}
- // Apply service config to call if needed.
- MaybeApplyServiceConfigToCallLocked(elem);
+ // Apply service config to call if not yet applied.
+ if (GPR_LIKELY(!service_config_applied_)) {
+ service_config_applied_ = true;
+ *error = ApplyServiceConfigToCallLocked(elem, initial_metadata_batch);
+ if (*error != GRPC_ERROR_NONE) return true;
+ }
// If this is a retry, use the send_initial_metadata payload that
// we've cached; otherwise, use the pending batch. The
// send_initial_metadata batch will be the first pending batch in the
@@ -3899,20 +4019,8 @@ bool CallData::PickSubchannelLocked(grpc_call_element* elem,
// attempt) to the LB policy instead the one from the parent channel.
LoadBalancingPolicy::PickArgs pick_args;
pick_args.call_state = &lb_call_state_;
- Metadata initial_metadata(
- this,
- seen_send_initial_metadata_
- ? &send_initial_metadata_
- : pending_batches_[0]
- .batch->payload->send_initial_metadata.send_initial_metadata);
+ Metadata initial_metadata(this, initial_metadata_batch);
pick_args.initial_metadata = &initial_metadata;
- // Grab initial metadata flags so that we can check later if the call has
- // wait_for_ready enabled.
- const uint32_t send_initial_metadata_flags =
- seen_send_initial_metadata_ ? send_initial_metadata_flags_
- : pending_batches_[0]
- .batch->payload->send_initial_metadata
- .send_initial_metadata_flags;
// Attempt pick.
auto result = chand->picker()->Pick(pick_args);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
@@ -3927,7 +4035,8 @@ bool CallData::PickSubchannelLocked(grpc_call_element* elem,
grpc_error* disconnect_error = chand->disconnect_error();
if (disconnect_error != GRPC_ERROR_NONE) {
GRPC_ERROR_UNREF(result.error);
- if (pick_queued_) RemoveCallFromQueuedPicksLocked(elem);
+ MaybeRemoveCallFromQueuedPicksLocked(elem);
+ MaybeInvokeConfigSelectorCommitCallback();
*error = GRPC_ERROR_REF(disconnect_error);
return true;
}
@@ -3948,8 +4057,9 @@ bool CallData::PickSubchannelLocked(grpc_call_element* elem,
"Failed to pick subchannel", &result.error, 1);
GRPC_ERROR_UNREF(result.error);
*error = new_error;
+ MaybeInvokeConfigSelectorCommitCallback();
}
- if (pick_queued_) RemoveCallFromQueuedPicksLocked(elem);
+ MaybeRemoveCallFromQueuedPicksLocked(elem);
return !retried;
}
// If wait_for_ready is true, then queue to retry when we get a new
@@ -3958,22 +4068,24 @@ bool CallData::PickSubchannelLocked(grpc_call_element* elem,
}
// Fallthrough
case LoadBalancingPolicy::PickResult::PICK_QUEUE:
- if (!pick_queued_) AddCallToQueuedPicksLocked(elem);
+ MaybeAddCallToQueuedPicksLocked(elem);
return false;
default: // PICK_COMPLETE
- if (pick_queued_) RemoveCallFromQueuedPicksLocked(elem);
+ MaybeRemoveCallFromQueuedPicksLocked(elem);
// Handle drops.
if (GPR_UNLIKELY(result.subchannel == nullptr)) {
result.error = grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Call dropped by load balancing policy"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
+ MaybeInvokeConfigSelectorCommitCallback();
} else {
// Grab a ref to the connected subchannel while we're still
// holding the data plane mutex.
connected_subchannel_ =
chand->GetConnectedSubchannelInDataPlane(result.subchannel.get());
GPR_ASSERT(connected_subchannel_ != nullptr);
+ if (retry_committed_) MaybeInvokeConfigSelectorCommitCallback();
}
lb_recv_trailing_metadata_ready_ = result.recv_trailing_metadata_ready;
*error = result.error;
diff --git a/src/core/ext/filters/client_channel/config_selector.cc b/src/core/ext/filters/client_channel/config_selector.cc
new file mode 100644
index 00000000000..e5d2a3f0be3
--- /dev/null
+++ b/src/core/ext/filters/client_channel/config_selector.cc
@@ -0,0 +1,62 @@
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include
+
+#include "src/core/ext/filters/client_channel/config_selector.h"
+
+#include "src/core/lib/channel/channel_args.h"
+
+// Channel arg key for ConfigSelector.
+#define GRPC_ARG_CONFIG_SELECTOR "grpc.internal.config_selector"
+
+namespace grpc_core {
+
+namespace {
+
+void* ConfigSelectorArgCopy(void* p) {
+ ConfigSelector* config_selector = static_cast(p);
+ config_selector->Ref().release();
+ return p;
+}
+
+void ConfigSelectorArgDestroy(void* p) {
+ ConfigSelector* config_selector = static_cast(p);
+ config_selector->Unref();
+}
+
+int ConfigSelectorArgCmp(void* p, void* q) { return GPR_ICMP(p, q); }
+
+const grpc_arg_pointer_vtable kChannelArgVtable = {
+ ConfigSelectorArgCopy, ConfigSelectorArgDestroy, ConfigSelectorArgCmp};
+
+} // namespace
+
+grpc_arg ConfigSelector::MakeChannelArg() const {
+ return grpc_channel_arg_pointer_create(
+ const_cast(GRPC_ARG_CONFIG_SELECTOR),
+ const_cast(this), &kChannelArgVtable);
+}
+
+RefCountedPtr ConfigSelector::GetFromChannelArgs(
+ const grpc_channel_args& args) {
+ ConfigSelector* config_selector =
+ grpc_channel_args_find_pointer(&args,
+ GRPC_ARG_CONFIG_SELECTOR);
+ return config_selector != nullptr ? config_selector->Ref() : nullptr;
+}
+
+} // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/config_selector.h b/src/core/ext/filters/client_channel/config_selector.h
new file mode 100644
index 00000000000..efd27341fa5
--- /dev/null
+++ b/src/core/ext/filters/client_channel/config_selector.h
@@ -0,0 +1,91 @@
+//
+// Copyright 2020 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONFIG_SELECTOR_H
+#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CONFIG_SELECTOR_H
+
+#include
+
+#include
+#include