diff --git a/BUILD b/BUILD
index b3c97ca5e2a..4fc1091b635 100644
--- a/BUILD
+++ b/BUILD
@@ -956,6 +956,7 @@ grpc_cc_library(
external_deps = [
"madler_zlib",
"absl/container:inlined_vector",
+ "absl/status",
"absl/types:optional",
],
language = "c++",
diff --git a/BUILD.gn b/BUILD.gn
index 035d6bddde6..b38ffc2301b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -991,6 +991,7 @@ config("grpc_config") {
":upb",
":absl/types:optional",
":absl/strings:strings",
+ ":absl/status:status",
":absl/container:inlined_vector",
"//third_party/cares",
":address_sorting",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ce8a7e338c0..d7fb543e242 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -111,23 +111,32 @@ set(gRPC_ABSL_USED_TARGETS
absl_civil_time
absl_compressed_tuple
absl_config
+ absl_cord
absl_core_headers
+ absl_debugging_internal
+ absl_demangle_internal
absl_dynamic_annotations
absl_endian
absl_errno_saver
+ absl_fixed_array
+ absl_function_ref
absl_inlined_vector
absl_inlined_vector_internal
absl_int128
absl_log_severity
+ absl_malloc_internal
absl_memory
absl_optional
absl_raw_logging_internal
absl_span
absl_spinlock_wait
+ absl_stacktrace
+ absl_status
absl_str_format
absl_str_format_internal
absl_strings
absl_strings_internal
+ absl_symbolize
absl_throw_delegate
absl_time
absl_time_zone
@@ -1793,6 +1802,7 @@ target_link_libraries(grpc
upb
absl::optional
absl::strings
+ absl::status
absl::inlined_vector
)
if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
@@ -2395,6 +2405,7 @@ target_link_libraries(grpc_unsecure
upb
absl::optional
absl::strings
+ absl::status
absl::inlined_vector
)
if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC)
@@ -15546,7 +15557,7 @@ generate_pkgconfig(
"high performance general RPC framework"
"${gRPC_CORE_VERSION}"
"gpr openssl"
- "-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz -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"
+ "-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz -labsl_status -labsl_cord -labsl_symbolize -labsl_demangle_internal -labsl_malloc_internal -labsl_stacktrace -labsl_debugging_internal -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"
""
"grpc.pc")
@@ -15556,7 +15567,7 @@ generate_pkgconfig(
"high performance general RPC framework without SSL"
"${gRPC_CORE_VERSION}"
"gpr"
- "-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"
+ "-lgrpc_unsecure -labsl_status -labsl_cord -labsl_symbolize -labsl_demangle_internal -labsl_malloc_internal -labsl_stacktrace -labsl_debugging_internal -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"
""
"grpc_unsecure.pc")
@@ -15566,7 +15577,7 @@ generate_pkgconfig(
"C++ wrapper for gRPC"
"${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"
+ "-lgrpc++ -labsl_status -labsl_cord -labsl_symbolize -labsl_demangle_internal -labsl_malloc_internal -labsl_stacktrace -labsl_debugging_internal -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"
""
"grpc++.pc")
@@ -15576,6 +15587,6 @@ generate_pkgconfig(
"C++ wrapper for gRPC without SSL"
"${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"
+ "-lgrpc++_unsecure -labsl_status -labsl_cord -labsl_symbolize -labsl_demangle_internal -labsl_malloc_internal -labsl_stacktrace -labsl_debugging_internal -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"
""
"grpc++_unsecure.pc")
diff --git a/Makefile b/Makefile
index b86df824e22..fcb70c554dc 100644
--- a/Makefile
+++ b/Makefile
@@ -6236,6 +6236,7 @@ endif
LIBGRPC_ABSEIL_SRC = \
third_party/abseil-cpp/absl/base/dynamic_annotations.cc \
third_party/abseil-cpp/absl/base/internal/cycleclock.cc \
+ third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc \
third_party/abseil-cpp/absl/base/internal/raw_logging.cc \
third_party/abseil-cpp/absl/base/internal/spinlock.cc \
third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc \
@@ -6244,9 +6245,18 @@ LIBGRPC_ABSEIL_SRC = \
third_party/abseil-cpp/absl/base/internal/throw_delegate.cc \
third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc \
third_party/abseil-cpp/absl/base/log_severity.cc \
+ third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc \
+ third_party/abseil-cpp/absl/debugging/internal/demangle.cc \
+ third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc \
+ third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc \
+ third_party/abseil-cpp/absl/debugging/stacktrace.cc \
+ third_party/abseil-cpp/absl/debugging/symbolize.cc \
third_party/abseil-cpp/absl/numeric/int128.cc \
+ third_party/abseil-cpp/absl/status/status.cc \
+ third_party/abseil-cpp/absl/status/status_payload_printer.cc \
third_party/abseil-cpp/absl/strings/ascii.cc \
third_party/abseil-cpp/absl/strings/charconv.cc \
+ third_party/abseil-cpp/absl/strings/cord.cc \
third_party/abseil-cpp/absl/strings/escaping.cc \
third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc \
third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc \
diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml
index 23a3e3c0554..8720ff88b96 100644
--- a/build_autogenerated.yaml
+++ b/build_autogenerated.yaml
@@ -1163,6 +1163,7 @@ libs:
- upb
- absl/types:optional
- absl/strings:strings
+ - absl/status:status
- absl/container:inlined_vector
baselib: true
deps_linkage: static
@@ -1952,6 +1953,7 @@ libs:
- upb
- absl/types:optional
- absl/strings:strings
+ - absl/status:status
- absl/container:inlined_vector
baselib: true
deps_linkage: static
diff --git a/config.m4 b/config.m4
index 8cf43fc8a52..bc75131dc70 100644
--- a/config.m4
+++ b/config.m4
@@ -509,6 +509,7 @@ if test "$PHP_GRPC" != "no"; then
src/php/ext/grpc/timeval.c \
third_party/abseil-cpp/absl/base/dynamic_annotations.cc \
third_party/abseil-cpp/absl/base/internal/cycleclock.cc \
+ third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc \
third_party/abseil-cpp/absl/base/internal/raw_logging.cc \
third_party/abseil-cpp/absl/base/internal/spinlock.cc \
third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc \
@@ -517,9 +518,18 @@ if test "$PHP_GRPC" != "no"; then
third_party/abseil-cpp/absl/base/internal/throw_delegate.cc \
third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc \
third_party/abseil-cpp/absl/base/log_severity.cc \
+ third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc \
+ third_party/abseil-cpp/absl/debugging/internal/demangle.cc \
+ third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc \
+ third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc \
+ third_party/abseil-cpp/absl/debugging/stacktrace.cc \
+ third_party/abseil-cpp/absl/debugging/symbolize.cc \
third_party/abseil-cpp/absl/numeric/int128.cc \
+ third_party/abseil-cpp/absl/status/status.cc \
+ third_party/abseil-cpp/absl/status/status_payload_printer.cc \
third_party/abseil-cpp/absl/strings/ascii.cc \
third_party/abseil-cpp/absl/strings/charconv.cc \
+ third_party/abseil-cpp/absl/strings/cord.cc \
third_party/abseil-cpp/absl/strings/escaping.cc \
third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc \
third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc \
@@ -971,7 +981,10 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/base)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/base/internal)
+ PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/debugging)
+ PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/debugging/internal)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/numeric)
+ PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/status)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/strings)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/strings/internal)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/abseil-cpp/absl/strings/internal/str_format)
diff --git a/config.w32 b/config.w32
index 8f027adf682..de58a2c5bea 100644
--- a/config.w32
+++ b/config.w32
@@ -477,6 +477,7 @@ if (PHP_GRPC != "no") {
"src\\php\\ext\\grpc\\timeval.c " +
"third_party\\abseil-cpp\\absl\\base\\dynamic_annotations.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\cycleclock.cc " +
+ "third_party\\abseil-cpp\\absl\\base\\internal\\low_level_alloc.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\raw_logging.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\spinlock.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\spinlock_wait.cc " +
@@ -485,9 +486,18 @@ if (PHP_GRPC != "no") {
"third_party\\abseil-cpp\\absl\\base\\internal\\throw_delegate.cc " +
"third_party\\abseil-cpp\\absl\\base\\internal\\unscaledcycleclock.cc " +
"third_party\\abseil-cpp\\absl\\base\\log_severity.cc " +
+ "third_party\\abseil-cpp\\absl\\debugging\\internal\\address_is_readable.cc " +
+ "third_party\\abseil-cpp\\absl\\debugging\\internal\\demangle.cc " +
+ "third_party\\abseil-cpp\\absl\\debugging\\internal\\elf_mem_image.cc " +
+ "third_party\\abseil-cpp\\absl\\debugging\\internal\\vdso_support.cc " +
+ "third_party\\abseil-cpp\\absl\\debugging\\stacktrace.cc " +
+ "third_party\\abseil-cpp\\absl\\debugging\\symbolize.cc " +
"third_party\\abseil-cpp\\absl\\numeric\\int128.cc " +
+ "third_party\\abseil-cpp\\absl\\status\\status.cc " +
+ "third_party\\abseil-cpp\\absl\\status\\status_payload_printer.cc " +
"third_party\\abseil-cpp\\absl\\strings\\ascii.cc " +
"third_party\\abseil-cpp\\absl\\strings\\charconv.cc " +
+ "third_party\\abseil-cpp\\absl\\strings\\cord.cc " +
"third_party\\abseil-cpp\\absl\\strings\\escaping.cc " +
"third_party\\abseil-cpp\\absl\\strings\\internal\\charconv_bigint.cc " +
"third_party\\abseil-cpp\\absl\\strings\\internal\\charconv_parse.cc " +
@@ -1007,7 +1017,10 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\base");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\base\\internal");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\debugging");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\debugging\\internal");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\numeric");
+ FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\status");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\strings");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\strings\\internal");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\third_party\\abseil-cpp\\absl\\strings\\internal\\str_format");
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index a0844acf9a9..c74f5fa8e95 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -210,6 +210,7 @@ Pod::Spec.new do |s|
abseil_version = '1.20200225.0'
ss.dependency 'abseil/container/inlined_vector', abseil_version
ss.dependency 'abseil/memory/memory', abseil_version
+ ss.dependency 'abseil/status/status', abseil_version
ss.dependency 'abseil/strings/str_format', abseil_version
ss.dependency 'abseil/strings/strings', abseil_version
ss.dependency 'abseil/time/time', abseil_version
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 9ac673e2c3d..869def405bb 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -176,6 +176,7 @@ Pod::Spec.new do |s|
abseil_version = '1.20200225.0'
ss.dependency 'abseil/container/inlined_vector', abseil_version
ss.dependency 'abseil/memory/memory', abseil_version
+ ss.dependency 'abseil/status/status', abseil_version
ss.dependency 'abseil/strings/str_format', abseil_version
ss.dependency 'abseil/strings/strings', abseil_version
ss.dependency 'abseil/time/time', abseil_version
diff --git a/grpc.gemspec b/grpc.gemspec
index 5b84d4ecf26..157b8dc766c 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -969,12 +969,15 @@ Gem::Specification.new do |s|
s.files += %w( third_party/abseil-cpp/absl/base/internal/bits.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/cycleclock.cc )
s.files += %w( third_party/abseil-cpp/absl/base/internal/cycleclock.h )
+ s.files += %w( third_party/abseil-cpp/absl/base/internal/direct_mmap.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/endian.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/errno_saver.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/hide_ptr.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/identity.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/inline_variable.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/invoke.h )
+ s.files += %w( third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc )
+ s.files += %w( third_party/abseil-cpp/absl/base/internal/low_level_alloc.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/per_thread_tls.h )
s.files += %w( third_party/abseil-cpp/absl/base/internal/raw_logging.cc )
@@ -1007,19 +1010,52 @@ Gem::Specification.new do |s|
s.files += %w( third_party/abseil-cpp/absl/base/policy_checks.h )
s.files += %w( third_party/abseil-cpp/absl/base/port.h )
s.files += %w( third_party/abseil-cpp/absl/base/thread_annotations.h )
+ s.files += %w( third_party/abseil-cpp/absl/container/fixed_array.h )
s.files += %w( third_party/abseil-cpp/absl/container/inlined_vector.h )
s.files += %w( third_party/abseil-cpp/absl/container/internal/compressed_tuple.h )
s.files += %w( third_party/abseil-cpp/absl/container/internal/inlined_vector.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/address_is_readable.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/demangle.cc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/demangle.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/symbolize.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/internal/vdso_support.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/stacktrace.cc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/stacktrace.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize.cc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize.h )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize_elf.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize_unimplemented.inc )
+ s.files += %w( third_party/abseil-cpp/absl/debugging/symbolize_win32.inc )
+ s.files += %w( third_party/abseil-cpp/absl/functional/function_ref.h )
+ s.files += %w( third_party/abseil-cpp/absl/functional/internal/function_ref.h )
s.files += %w( third_party/abseil-cpp/absl/memory/memory.h )
s.files += %w( third_party/abseil-cpp/absl/meta/type_traits.h )
s.files += %w( third_party/abseil-cpp/absl/numeric/int128.cc )
s.files += %w( third_party/abseil-cpp/absl/numeric/int128.h )
s.files += %w( third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc )
s.files += %w( third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc )
+ s.files += %w( third_party/abseil-cpp/absl/status/status.cc )
+ s.files += %w( third_party/abseil-cpp/absl/status/status.h )
+ s.files += %w( third_party/abseil-cpp/absl/status/status_payload_printer.cc )
+ s.files += %w( third_party/abseil-cpp/absl/status/status_payload_printer.h )
s.files += %w( third_party/abseil-cpp/absl/strings/ascii.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/ascii.h )
s.files += %w( third_party/abseil-cpp/absl/strings/charconv.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/charconv.h )
+ s.files += %w( third_party/abseil-cpp/absl/strings/cord.cc )
+ s.files += %w( third_party/abseil-cpp/absl/strings/cord.h )
s.files += %w( third_party/abseil-cpp/absl/strings/escaping.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/escaping.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/char_map.h )
@@ -1027,6 +1063,7 @@ Gem::Specification.new do |s|
s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_parse.h )
+ s.files += %w( third_party/abseil-cpp/absl/strings/internal/cord_internal.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/escaping.cc )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/escaping.h )
s.files += %w( third_party/abseil-cpp/absl/strings/internal/memutil.cc )
diff --git a/grpc.gyp b/grpc.gyp
index a7cae5e3f8b..f0ff7c76d25 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -432,6 +432,7 @@
'upb',
'absl/types:optional',
'absl/strings:strings',
+ 'absl/status:status',
'absl/container:inlined_vector',
],
'sources': [
@@ -941,6 +942,7 @@
'upb',
'absl/types:optional',
'absl/strings:strings',
+ 'absl/status:status',
'absl/container:inlined_vector',
],
'sources': [
diff --git a/package.xml b/package.xml
index 36399edc3e1..2d755e4d7dc 100644
--- a/package.xml
+++ b/package.xml
@@ -971,12 +971,15 @@
+
+
+
@@ -1009,19 +1012,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1029,6 +1065,7 @@
+
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index 2028c8ebb99..1b48d6a4d37 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -214,7 +214,8 @@ class ChannelData {
grpc_closure* on_complete,
bool cancel);
- void Notify(grpc_connectivity_state state) override;
+ void Notify(grpc_connectivity_state state,
+ const absl::Status& /* status */) override;
void Cancel();
@@ -260,7 +261,8 @@ class ChannelData {
~ChannelData();
void UpdateStateAndPickerLocked(
- grpc_connectivity_state state, const char* reason,
+ grpc_connectivity_state state, const absl::Status& status,
+ const char* reason,
std::unique_ptr picker);
void UpdateServiceConfigInDataPlaneLocked(
@@ -1212,7 +1214,7 @@ void ChannelData::ExternalConnectivityWatcher::
}
void ChannelData::ExternalConnectivityWatcher::Notify(
- grpc_connectivity_state state) {
+ grpc_connectivity_state state, const absl::Status& /* status */) {
bool done = false;
if (!done_.CompareExchangeStrong(&done, true, MemoryOrder::RELAXED,
MemoryOrder::RELAXED)) {
@@ -1352,19 +1354,21 @@ class ChannelData::ClientChannelControlHelper
}
void UpdateState(
- grpc_connectivity_state state,
+ grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override {
grpc_error* disconnect_error = chand_->disconnect_error();
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
const char* extra = disconnect_error == GRPC_ERROR_NONE
? ""
: " (ignoring -- channel shutting down)";
- gpr_log(GPR_INFO, "chand=%p: update: state=%s picker=%p%s", chand_,
- ConnectivityStateName(state), picker.get(), extra);
+ gpr_log(GPR_INFO, "chand=%p: update: state=%s status=(%s) picker=%p%s",
+ chand_, ConnectivityStateName(state), status.ToString().c_str(),
+ picker.get(), extra);
}
// Do update only if not shutting down.
if (disconnect_error == GRPC_ERROR_NONE) {
- chand_->UpdateStateAndPickerLocked(state, "helper", std::move(picker));
+ chand_->UpdateStateAndPickerLocked(state, status, "helper",
+ std::move(picker));
}
}
@@ -1701,7 +1705,8 @@ ChannelData::~ChannelData() {
}
void ChannelData::UpdateStateAndPickerLocked(
- grpc_connectivity_state state, const char* reason,
+ grpc_connectivity_state state, const absl::Status& status,
+ const char* reason,
std::unique_ptr picker) {
// Clean the control plane when entering IDLE.
if (picker_ == nullptr) {
@@ -1711,7 +1716,7 @@ void ChannelData::UpdateStateAndPickerLocked(
received_first_resolver_result_ = false;
}
// Update connectivity state.
- state_tracker_.SetState(state, reason);
+ state_tracker_.SetState(state, status, reason);
if (channelz_node_ != nullptr) {
channelz_node_->SetConnectivityState(state);
channelz_node_->AddTraceEvent(
@@ -1938,8 +1943,8 @@ void ChannelData::StartTransportOpLocked(grpc_transport_op* op) {
static_cast(value) == GRPC_CHANNEL_IDLE) {
if (disconnect_error() == GRPC_ERROR_NONE) {
// Enter IDLE state.
- UpdateStateAndPickerLocked(GRPC_CHANNEL_IDLE, "channel entering IDLE",
- nullptr);
+ UpdateStateAndPickerLocked(GRPC_CHANNEL_IDLE, absl::Status(),
+ "channel entering IDLE", nullptr);
}
GRPC_ERROR_UNREF(op->disconnect_with_error);
} else {
@@ -1948,7 +1953,7 @@ void ChannelData::StartTransportOpLocked(grpc_transport_op* op) {
GRPC_ERROR_NONE);
disconnect_error_.Store(op->disconnect_with_error, MemoryOrder::RELEASE);
UpdateStateAndPickerLocked(
- GRPC_CHANNEL_SHUTDOWN, "shutdown from API",
+ GRPC_CHANNEL_SHUTDOWN, absl::Status(), "shutdown from API",
absl::make_unique(
GRPC_ERROR_REF(op->disconnect_with_error)));
}
diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc
index e708a59c571..5d65293af29 100644
--- a/src/core/ext/filters/client_channel/health/health_check_client.cc
+++ b/src/core/ext/filters/client_channel/health/health_check_client.cc
@@ -91,7 +91,11 @@ void HealthCheckClient::SetHealthStatusLocked(grpc_connectivity_state state,
gpr_log(GPR_INFO, "HealthCheckClient %p: setting state=%s reason=%s", this,
ConnectivityStateName(state), reason);
}
- if (watcher_ != nullptr) watcher_->Notify(state);
+ if (watcher_ != nullptr)
+ watcher_->Notify(state,
+ state == GRPC_CHANNEL_TRANSIENT_FAILURE
+ ? absl::Status(absl::StatusCode::kUnavailable, reason)
+ : absl::Status());
}
void HealthCheckClient::Orphan() {
diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h
index 6a290a3f51b..81f5bb33b20 100644
--- a/src/core/ext/filters/client_channel/lb_policy.h
+++ b/src/core/ext/filters/client_channel/lb_policy.h
@@ -24,6 +24,7 @@
#include
#include
+#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "src/core/ext/filters/client_channel/server_address.h"
@@ -283,6 +284,7 @@ class LoadBalancingPolicy : public InternallyRefCounted {
/// Sets the connectivity state and returns a new picker to be used
/// by the client channel.
virtual void UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr) = 0;
/// Requests that the resolver re-resolve.
diff --git a/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc b/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc
index 8d8003d185a..1464c718602 100644
--- a/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc
@@ -45,7 +45,7 @@ class ChildPolicyHandler::Helper
return parent_->channel_control_helper()->CreateSubchannel(args);
}
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override {
if (parent_->shutting_down_) return;
// If this request is from the pending child policy, ignore it until
@@ -55,8 +55,9 @@ class ChildPolicyHandler::Helper
if (GRPC_TRACE_FLAG_ENABLED(*(parent_->tracer_))) {
gpr_log(GPR_INFO,
"[child_policy_handler %p] helper %p: pending child policy %p "
- "reports state=%s",
- parent_.get(), this, child_, ConnectivityStateName(state));
+ "reports state=%s (%s)",
+ parent_.get(), this, child_, ConnectivityStateName(state),
+ status.ToString().c_str());
}
if (state == GRPC_CHANNEL_CONNECTING) return;
grpc_pollset_set_del_pollset_set(
@@ -67,7 +68,8 @@ class ChildPolicyHandler::Helper
// This request is from an outdated child, so ignore it.
return;
}
- parent_->channel_control_helper()->UpdateState(state, std::move(picker));
+ parent_->channel_control_helper()->UpdateState(state, status,
+ std::move(picker));
}
void RequestReresolution() override {
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
index e4248a6f556..878951866ee 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
@@ -304,7 +304,7 @@ class GrpcLb : public LoadBalancingPolicy {
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@@ -323,15 +323,16 @@ class GrpcLb : public LoadBalancingPolicy {
~StateWatcher() { parent_.reset(DEBUG_LOCATION, "StateWatcher"); }
private:
- void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& status) override {
if (parent_->fallback_at_startup_checks_pending_ &&
new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
// In TRANSIENT_FAILURE. Cancel the fallback timer and go into
// fallback mode immediately.
gpr_log(GPR_INFO,
- "[grpclb %p] balancer channel in state TRANSIENT_FAILURE; "
+ "[grpclb %p] balancer channel in state:TRANSIENT_FAILURE (%s); "
"entering fallback mode",
- parent_.get());
+ parent_.get(), status.ToString().c_str());
parent_->fallback_at_startup_checks_pending_ = false;
grpc_timer_cancel(&parent_->lb_fallback_timer_);
parent_->fallback_mode_ = true;
@@ -660,6 +661,7 @@ RefCountedPtr GrpcLb::Helper::CreateSubchannel(
}
void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) {
if (parent_->shutting_down_) return;
// Record whether child policy reports READY.
@@ -690,16 +692,22 @@ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
state != GRPC_CHANNEL_READY)) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
gpr_log(GPR_INFO,
- "[grpclb %p helper %p] state=%s passing child picker %p as-is",
- parent_.get(), this, ConnectivityStateName(state), picker.get());
+ "[grpclb %p helper %p] state=%s (%s) passing "
+ "child picker %p as-is",
+ parent_.get(), this, ConnectivityStateName(state),
+ status.ToString().c_str(), picker.get());
}
- parent_->channel_control_helper()->UpdateState(state, std::move(picker));
+ parent_->channel_control_helper()->UpdateState(state, status,
+ std::move(picker));
return;
}
// Cases 2 and 3a: wrap picker from the child in our own picker.
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
- gpr_log(GPR_INFO, "[grpclb %p helper %p] state=%s wrapping child picker %p",
- parent_.get(), this, ConnectivityStateName(state), picker.get());
+ gpr_log(GPR_INFO,
+ "[grpclb %p helper %p] state=%s (%s) wrapping child "
+ "picker %p",
+ parent_.get(), this, ConnectivityStateName(state),
+ status.ToString().c_str(), picker.get());
}
RefCountedPtr client_stats;
if (parent_->lb_calld_ != nullptr &&
@@ -707,7 +715,7 @@ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
client_stats = parent_->lb_calld_->client_stats()->Ref();
}
parent_->channel_control_helper()->UpdateState(
- state,
+ state, status,
absl::make_unique(parent_.get(), parent_->serverlist_,
std::move(picker), std::move(client_stats)));
}
diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
index 246b15a3549..4a1f006cf64 100644
--- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
@@ -30,6 +30,7 @@
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/transport/connectivity_state.h"
+#include "src/core/lib/transport/error_utils.h"
namespace grpc_core {
@@ -200,7 +201,7 @@ void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() {
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
return;
}
@@ -318,12 +319,13 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
"selected subchannel failed; switching to pending update"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
} else {
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_CONNECTING, absl::make_unique(p->Ref(
- DEBUG_LOCATION, "QueuePicker")));
+ GRPC_CHANNEL_CONNECTING, absl::Status(),
+ absl::make_unique(
+ p->Ref(DEBUG_LOCATION, "QueuePicker")));
}
} else {
if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
@@ -338,20 +340,22 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
p->selected_ = nullptr;
p->subchannel_list_.reset();
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_IDLE, absl::make_unique(
- p->Ref(DEBUG_LOCATION, "QueuePicker")));
+ GRPC_CHANNEL_IDLE, absl::Status(),
+ absl::make_unique(
+ p->Ref(DEBUG_LOCATION, "QueuePicker")));
} else {
// This is unlikely but can happen when a subchannel has been asked
// to reconnect by a different channel and this channel has dropped
// some connectivity state notifications.
if (connectivity_state == GRPC_CHANNEL_READY) {
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_READY,
+ GRPC_CHANNEL_READY, absl::Status(),
absl::make_unique(subchannel()->Ref()));
} else { // CONNECTING
p->channel_control_helper()->UpdateState(
- connectivity_state, absl::make_unique(
- p->Ref(DEBUG_LOCATION, "QueuePicker")));
+ connectivity_state, absl::Status(),
+ absl::make_unique(
+ p->Ref(DEBUG_LOCATION, "QueuePicker")));
}
}
}
@@ -394,7 +398,7 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
"failed to connect to all addresses"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
}
}
@@ -406,8 +410,9 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
// Only update connectivity state in case 1.
if (subchannel_list() == p->subchannel_list_.get()) {
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_CONNECTING, absl::make_unique(p->Ref(
- DEBUG_LOCATION, "QueuePicker")));
+ GRPC_CHANNEL_CONNECTING, absl::Status(),
+ absl::make_unique(
+ p->Ref(DEBUG_LOCATION, "QueuePicker")));
}
break;
}
@@ -446,7 +451,8 @@ void PickFirst::PickFirstSubchannelData::ProcessUnselectedReadyLocked() {
}
p->selected_ = this;
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_READY, absl::make_unique(subchannel()->Ref()));
+ GRPC_CHANNEL_READY, absl::Status(),
+ absl::make_unique(subchannel()->Ref()));
for (size_t i = 0; i < subchannel_list()->num_subchannels(); ++i) {
if (i != Index()) {
subchannel_list()->subchannel(i)->ShutdownLocked();
diff --git a/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc b/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
index 19fc45f4f87..6b0489ceb16 100644
--- a/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
@@ -20,6 +20,7 @@
#include
#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
#include
@@ -33,6 +34,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
+#include "src/core/lib/transport/error_utils.h"
namespace grpc_core {
@@ -113,6 +115,11 @@ class PriorityLb : public LoadBalancingPolicy {
grpc_connectivity_state connectivity_state() const {
return connectivity_state_;
}
+
+ const absl::Status& connectivity_status() const {
+ return connectivity_status_;
+ }
+
bool failover_timer_callback_pending() const {
return failover_timer_callback_pending_;
}
@@ -150,6 +157,7 @@ class PriorityLb : public LoadBalancingPolicy {
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@@ -164,7 +172,7 @@ class PriorityLb : public LoadBalancingPolicy {
const grpc_channel_args* args);
void OnConnectivityStateUpdateLocked(
- grpc_connectivity_state state,
+ grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker);
void StartFailoverTimerLocked();
@@ -180,6 +188,7 @@ class PriorityLb : public LoadBalancingPolicy {
OrphanablePtr child_policy_;
grpc_connectivity_state connectivity_state_ = GRPC_CHANNEL_CONNECTING;
+ absl::Status connectivity_status_;
RefCountedPtr picker_wrapper_;
// States for delayed removal.
@@ -334,6 +343,7 @@ void PriorityLb::HandleChildConnectivityStateChangeLocked(
// If it's still READY or IDLE, we stick with this child, so pass
// the new picker up to our parent.
channel_control_helper()->UpdateState(child->connectivity_state(),
+ child->connectivity_status(),
child->GetPicker());
} else {
// If it's no longer READY or IDLE, we should stop using it.
@@ -380,6 +390,7 @@ void PriorityLb::HandleChildConnectivityStateChangeLocked(
// The current priority has returned a new picker, so pass it up to
// our parent.
channel_control_helper()->UpdateState(child->connectivity_state(),
+ child->connectivity_status(),
child->GetPicker());
}
@@ -409,7 +420,7 @@ void PriorityLb::TryNextPriorityLocked(bool report_connecting) {
if (child == nullptr) {
if (report_connecting) {
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_CONNECTING,
+ GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique(Ref(DEBUG_LOCATION, "QueuePicker")));
}
child = MakeOrphanable(
@@ -436,7 +447,7 @@ void PriorityLb::TryNextPriorityLocked(bool report_connecting) {
}
if (report_connecting) {
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_CONNECTING,
+ GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique(Ref(DEBUG_LOCATION, "QueuePicker")));
}
return;
@@ -456,7 +467,7 @@ void PriorityLb::TryNextPriorityLocked(bool report_connecting) {
GRPC_ERROR_CREATE_FROM_STATIC_STRING("no ready priority"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
}
@@ -476,6 +487,7 @@ void PriorityLb::SelectPriorityLocked(uint32_t priority) {
// Update picker.
auto& child = children_[config_->priorities()[priority]];
channel_control_helper()->UpdateState(child->connectivity_state(),
+ child->connectivity_status(),
child->GetPicker());
}
@@ -584,15 +596,18 @@ void PriorityLb::ChildPriority::ResetBackoffLocked() {
}
void PriorityLb::ChildPriority::OnConnectivityStateUpdateLocked(
- grpc_connectivity_state state, std::unique_ptr picker) {
+ grpc_connectivity_state state, const absl::Status& status,
+ std::unique_ptr picker) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) {
gpr_log(GPR_INFO,
- "[priority_lb %p] child %s (%p): state update: %s, picker %p",
+ "[priority_lb %p] child %s (%p): state update: %s (%s) picker %p",
priority_policy_.get(), name_.c_str(), this,
- ConnectivityStateName(state), picker.get());
+ ConnectivityStateName(state), status.ToString().c_str(),
+ picker.get());
}
// Store the state and picker.
connectivity_state_ = state;
+ connectivity_status_ = status;
picker_wrapper_ = MakeRefCounted(std::move(picker));
// If READY or TRANSIENT_FAILURE, cancel failover timer.
if (state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
@@ -646,7 +661,10 @@ void PriorityLb::ChildPriority::OnFailoverTimerLocked(grpc_error* error) {
priority_policy_.get(), name_.c_str(), this);
}
failover_timer_callback_pending_ = false;
- OnConnectivityStateUpdateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, nullptr);
+ OnConnectivityStateUpdateLocked(
+ GRPC_CHANNEL_TRANSIENT_FAILURE,
+ absl::Status(absl::StatusCode::kUnavailable, "failover timer fired"),
+ nullptr);
}
Unref(DEBUG_LOCATION, "ChildPriority+OnFailoverTimerLocked");
GRPC_ERROR_UNREF(error);
@@ -725,10 +743,11 @@ PriorityLb::ChildPriority::Helper::CreateSubchannel(
}
void PriorityLb::ChildPriority::Helper::UpdateState(
- grpc_connectivity_state state, std::unique_ptr picker) {
+ grpc_connectivity_state state, const absl::Status& status,
+ std::unique_ptr picker) {
if (priority_->priority_policy_->shutting_down_) return;
// Notify the priority.
- priority_->OnConnectivityStateUpdateLocked(state, std::move(picker));
+ priority_->OnConnectivityStateUpdateLocked(state, status, std::move(picker));
}
void PriorityLb::ChildPriority::Helper::AddTraceEvent(
diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
index 56b71b69dfc..d1ad2ca35e7 100644
--- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
@@ -40,6 +40,7 @@
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/transport/connectivity_state.h"
+#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/static_metadata.h"
namespace grpc_core {
@@ -322,11 +323,11 @@ void RoundRobin::RoundRobinSubchannelList::
if (num_ready_ > 0) {
/* 1) READY */
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_READY, absl::make_unique(p, this));
+ GRPC_CHANNEL_READY, absl::Status(), absl::make_unique(p, this));
} else if (num_connecting_ > 0) {
/* 2) CONNECTING */
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_CONNECTING,
+ GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique(p->Ref(DEBUG_LOCATION, "QueuePicker")));
} else if (num_transient_failure_ == num_subchannels()) {
/* 3) TRANSIENT_FAILURE */
@@ -335,7 +336,7 @@ void RoundRobin::RoundRobinSubchannelList::
"connections to all backends failing"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
p->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
}
}
@@ -452,7 +453,7 @@ void RoundRobin::UpdateLocked(UpdateArgs args) {
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
subchannel_list_ = std::move(latest_pending_subchannel_list_);
} else if (subchannel_list_ == nullptr) {
diff --git a/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc b/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
index 96491b68642..83bc6cc9a54 100644
--- a/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
@@ -36,6 +36,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
+#include "src/core/lib/transport/error_utils.h"
namespace grpc_core {
@@ -146,6 +147,7 @@ class WeightedTargetLb : public LoadBalancingPolicy {
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@@ -160,7 +162,7 @@ class WeightedTargetLb : public LoadBalancingPolicy {
const grpc_channel_args* args);
void OnConnectivityStateUpdateLocked(
- grpc_connectivity_state state,
+ grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker);
static void OnDelayedRemovalTimer(void* arg, grpc_error* error);
@@ -375,6 +377,7 @@ void WeightedTargetLb::UpdateStateLocked() {
this, ConnectivityStateName(connectivity_state));
}
std::unique_ptr picker;
+ absl::Status status;
switch (connectivity_state) {
case GRPC_CHANNEL_READY:
picker = absl::make_unique(std::move(picker_list));
@@ -385,11 +388,15 @@ void WeightedTargetLb::UpdateStateLocked() {
absl::make_unique(Ref(DEBUG_LOCATION, "QueuePicker"));
break;
default:
- picker = absl::make_unique(
+ grpc_error* error = grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "weighted_target: all children report state TRANSIENT_FAILURE"));
+ "weighted_target: all children report state TRANSIENT_FAILURE"),
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
+ status = grpc_error_to_absl_status(error);
+ picker = absl::make_unique(error);
}
- channel_control_helper()->UpdateState(connectivity_state, std::move(picker));
+ channel_control_helper()->UpdateState(connectivity_state, status,
+ std::move(picker));
}
//
@@ -508,15 +515,17 @@ void WeightedTargetLb::WeightedChild::ResetBackoffLocked() {
}
void WeightedTargetLb::WeightedChild::OnConnectivityStateUpdateLocked(
- grpc_connectivity_state state, std::unique_ptr picker) {
+ grpc_connectivity_state state, const absl::Status& status,
+ std::unique_ptr picker) {
// Cache the picker in the WeightedChild.
picker_wrapper_ = MakeRefCounted(std::move(picker));
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_weighted_target_trace)) {
gpr_log(GPR_INFO,
"[weighted_target_lb %p] WeightedChild %p %s: connectivity "
- "state update: state=%s picker_wrapper=%p",
+ "state update: state=%s (%s) picker_wrapper=%p",
weighted_target_policy_.get(), this, name_.c_str(),
- ConnectivityStateName(state), picker_wrapper_.get());
+ ConnectivityStateName(state), status.ToString().c_str(),
+ picker_wrapper_.get());
}
// If the child reports IDLE, immediately tell it to exit idle.
if (state == GRPC_CHANNEL_IDLE) child_policy_->ExitIdleLocked();
@@ -589,9 +598,11 @@ WeightedTargetLb::WeightedChild::Helper::CreateSubchannel(
}
void WeightedTargetLb::WeightedChild::Helper::UpdateState(
- grpc_connectivity_state state, std::unique_ptr picker) {
+ grpc_connectivity_state state, const absl::Status& status,
+ std::unique_ptr picker) {
if (weighted_child_->weighted_target_policy_->shutting_down_) return;
- weighted_child_->OnConnectivityStateUpdateLocked(state, std::move(picker));
+ weighted_child_->OnConnectivityStateUpdateLocked(state, status,
+ std::move(picker));
}
void WeightedTargetLb::WeightedChild::Helper::RequestReresolution() {
diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc b/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
index 500f1ac056b..fb161fcb26c 100644
--- a/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
@@ -29,6 +29,7 @@
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/transport/error_utils.h"
namespace grpc_core {
@@ -79,7 +80,7 @@ class CdsLb : public LoadBalancingPolicy {
explicit Helper(RefCountedPtr parent) : parent_(std::move(parent)) {}
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@@ -209,7 +210,7 @@ void CdsLb::ClusterWatcher::OnError(grpc_error* error) {
// we keep running with the data we had previously.
if (parent_->child_policy_ == nullptr) {
parent_->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
} else {
GRPC_ERROR_UNREF(error);
@@ -221,13 +222,15 @@ void CdsLb::ClusterWatcher::OnResourceDoesNotExist() {
"[cdslb %p] CDS resource for %s does not exist -- reporting "
"TRANSIENT_FAILURE",
parent_.get(), parent_->config_->cluster().c_str());
+ grpc_error* error = grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat("CDS resource \"", parent_->config_->cluster(),
+ "\" does not exist")
+ .c_str()),
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
parent_->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
- absl::make_unique(
- GRPC_ERROR_CREATE_FROM_COPIED_STRING(
- absl::StrCat("CDS resource \"", parent_->config_->cluster(),
- "\" does not exist")
- .c_str())));
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
+ absl::make_unique(error));
parent_->MaybeDestroyChildPolicyLocked();
}
@@ -242,13 +245,16 @@ RefCountedPtr CdsLb::Helper::CreateSubchannel(
}
void CdsLb::Helper::UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) {
if (parent_->shutting_down_ || parent_->child_policy_ == nullptr) return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) {
- gpr_log(GPR_INFO, "[cdslb %p] state updated by child: %s", this,
- ConnectivityStateName(state));
+ gpr_log(GPR_INFO,
+ "[cdslb %p] state updated by child: %s message_state: (%s)", this,
+ ConnectivityStateName(state), status.ToString().c_str());
}
- parent_->channel_control_helper()->UpdateState(state, std::move(picker));
+ parent_->channel_control_helper()->UpdateState(state, status,
+ std::move(picker));
}
void CdsLb::Helper::RequestReresolution() {
diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc b/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
index c1bbf742cee..da9d0aaff7d 100644
--- a/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
@@ -40,6 +40,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
+#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/uri/uri_parser.h"
#define GRPC_EDS_DEFAULT_FALLBACK_TIMEOUT 10000
@@ -133,7 +134,7 @@ class EdsLb : public LoadBalancingPolicy {
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override;
// This is a no-op, because we get the addresses from the xds
// client, which is a watch-based API.
@@ -214,6 +215,7 @@ class EdsLb : public LoadBalancingPolicy {
// The latest state and picker returned from the child policy.
grpc_connectivity_state child_state_;
+ absl::Status child_status_;
RefCountedPtr child_picker_;
};
@@ -265,16 +267,21 @@ RefCountedPtr EdsLb::Helper::CreateSubchannel(
}
void EdsLb::Helper::UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) {
if (eds_policy_->shutting_down_ || eds_policy_->child_policy_ == nullptr) {
return;
}
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_eds_trace)) {
- gpr_log(GPR_INFO, "[edslb %p] child policy updated state=%s picker=%p",
- eds_policy_.get(), ConnectivityStateName(state), picker.get());
+ gpr_log(GPR_INFO,
+ "[edslb %p] child policy updated state=%s (%s) "
+ "picker=%p",
+ eds_policy_.get(), ConnectivityStateName(state),
+ status.ToString().c_str(), picker.get());
}
// Save the state and picker.
eds_policy_->child_state_ = state;
+ eds_policy_->child_status_ = status;
eds_policy_->child_picker_ =
MakeRefCounted(std::move(picker));
// Wrap the picker in a DropPicker and pass it up.
@@ -339,7 +346,7 @@ class EdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
// we keep running with the data we had previously.
if (eds_policy_->child_policy_ == nullptr) {
eds_policy_->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
} else {
GRPC_ERROR_UNREF(error);
@@ -351,11 +358,12 @@ class EdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
GPR_ERROR,
"[edslb %p] EDS resource does not exist -- reporting TRANSIENT_FAILURE",
eds_policy_.get());
+ grpc_error* error = grpc_error_set_int(
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("EDS resource does not exist"),
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
eds_policy_->channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
- absl::make_unique(
- GRPC_ERROR_CREATE_FROM_STATIC_STRING(
- "EDS resource does not exist")));
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
+ absl::make_unique(error));
eds_policy_->MaybeDestroyChildPolicyLocked();
}
@@ -688,7 +696,7 @@ EdsLb::CreateChildPolicyConfigLocked() {
error),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_INTERNAL);
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique(error));
return nullptr;
}
@@ -769,13 +777,13 @@ void EdsLb::MaybeUpdateDropPickerLocked() {
// If we're dropping all calls, report READY, regardless of what (or
// whether) the child has reported.
if (drop_config_ != nullptr && drop_config_->drop_all()) {
- channel_control_helper()->UpdateState(GRPC_CHANNEL_READY,
+ channel_control_helper()->UpdateState(GRPC_CHANNEL_READY, absl::Status(),
absl::make_unique(this));
return;
}
// Update only if we have a child picker.
if (child_picker_ != nullptr) {
- channel_control_helper()->UpdateState(child_state_,
+ channel_control_helper()->UpdateState(child_state_, child_status_,
absl::make_unique(this));
}
}
diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc b/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
index 0aca12dfed2..51027574b32 100644
--- a/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
@@ -120,7 +120,7 @@ class LrsLb : public LoadBalancingPolicy {
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@@ -157,6 +157,7 @@ class LrsLb : public LoadBalancingPolicy {
// Latest state and picker reported by the child policy.
grpc_connectivity_state state_ = GRPC_CHANNEL_IDLE;
+ absl::Status status_;
RefCountedPtr picker_;
};
@@ -266,10 +267,14 @@ void LrsLb::MaybeUpdatePickerLocked() {
auto lrs_picker =
absl::make_unique(picker_, locality_stats_);
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) {
- gpr_log(GPR_INFO, "[lrs_lb %p] updating connectivity: state=%s picker=%p",
- this, ConnectivityStateName(state_), lrs_picker.get());
+ gpr_log(
+ GPR_INFO,
+ "[lrs_lb %p] updating connectivity: state=%s status=(%s) picker=%p",
+ this, ConnectivityStateName(state_), status_.ToString().c_str(),
+ lrs_picker.get());
}
- channel_control_helper()->UpdateState(state_, std::move(lrs_picker));
+ channel_control_helper()->UpdateState(state_, status_,
+ std::move(lrs_picker));
}
}
@@ -325,15 +330,19 @@ RefCountedPtr LrsLb::Helper::CreateSubchannel(
}
void LrsLb::Helper::UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) {
if (lrs_policy_->shutting_down_) return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_lrs_trace)) {
- gpr_log(GPR_INFO,
- "[lrs_lb %p] child connectivity state update: state=%s picker=%p",
- lrs_policy_.get(), ConnectivityStateName(state), picker.get());
+ gpr_log(
+ GPR_INFO,
+ "[lrs_lb %p] child connectivity state update: state=%s (%s) picker=%p",
+ lrs_policy_.get(), ConnectivityStateName(state),
+ status.ToString().c_str(), picker.get());
}
// Save the state and picker.
lrs_policy_->state_ = state;
+ lrs_policy_->status_ = status;
lrs_policy_->picker_ = MakeRefCounted(std::move(picker));
// Wrap the picker and return it to the channel.
lrs_policy_->MaybeUpdatePickerLocked();
diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc b/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
index 2adc7cd9551..a3672e14bce 100644
--- a/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
@@ -42,6 +42,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/work_serializer.h"
+#include "src/core/lib/transport/error_utils.h"
#define GRPC_XDS_ROUTING_CHILD_RETENTION_INTERVAL_MS (15 * 60 * 1000)
@@ -165,6 +166,7 @@ class XdsRoutingLb : public LoadBalancingPolicy {
RefCountedPtr CreateSubchannel(
const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state,
+ const absl::Status& status,
std::unique_ptr picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@@ -464,6 +466,7 @@ void XdsRoutingLb::UpdateStateLocked() {
ConnectivityStateName(connectivity_state));
}
std::unique_ptr picker;
+ absl::Status status;
switch (connectivity_state) {
case GRPC_CHANNEL_READY: {
RoutePicker::RouteTable route_table;
@@ -493,12 +496,15 @@ void XdsRoutingLb::UpdateStateLocked() {
absl::make_unique(Ref(DEBUG_LOCATION, "QueuePicker"));
break;
default:
- picker = absl::make_unique(grpc_error_set_int(
+ grpc_error* error = grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"TRANSIENT_FAILURE from XdsRoutingLb"),
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
+ status = grpc_error_to_absl_status(error);
+ picker = absl::make_unique(error);
}
- channel_control_helper()->UpdateState(connectivity_state, std::move(picker));
+ channel_control_helper()->UpdateState(connectivity_state, status,
+ std::move(picker));
}
//
@@ -654,13 +660,15 @@ XdsRoutingLb::XdsRoutingChild::Helper::CreateSubchannel(
}
void XdsRoutingLb::XdsRoutingChild::Helper::UpdateState(
- grpc_connectivity_state state, std::unique_ptr picker) {
+ grpc_connectivity_state state, const absl::Status& status,
+ std::unique_ptr picker) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_routing_lb_trace)) {
gpr_log(GPR_INFO,
- "[xds_routing_lb %p] child %s: received update: state=%s picker=%p",
+ "[xds_routing_lb %p] child %s: received update: state=%s (%s) "
+ "picker=%p",
xds_routing_child_->xds_routing_policy_.get(),
xds_routing_child_->name_.c_str(), ConnectivityStateName(state),
- picker.get());
+ status.ToString().c_str(), picker.get());
}
if (xds_routing_child_->xds_routing_policy_->shutting_down_) return;
// Cache the picker in the XdsRoutingChild.
diff --git a/src/core/ext/filters/client_channel/resolving_lb_policy.cc b/src/core/ext/filters/client_channel/resolving_lb_policy.cc
index 356123c50ae..ce204f030e7 100644
--- a/src/core/ext/filters/client_channel/resolving_lb_policy.cc
+++ b/src/core/ext/filters/client_channel/resolving_lb_policy.cc
@@ -114,10 +114,11 @@ class ResolvingLoadBalancingPolicy::ResolvingControlHelper
return parent_->channel_control_helper()->CreateSubchannel(args);
}
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override {
if (parent_->resolver_ == nullptr) return; // Shutting down.
- parent_->channel_control_helper()->UpdateState(state, std::move(picker));
+ parent_->channel_control_helper()->UpdateState(state, status,
+ std::move(picker));
}
void RequestReresolution() override {
@@ -160,7 +161,7 @@ ResolvingLoadBalancingPolicy::ResolvingLoadBalancingPolicy(
if (GRPC_TRACE_FLAG_ENABLED(*tracer_)) {
gpr_log(GPR_INFO, "resolving_lb=%p: starting name resolution", this);
}
- channel_control_helper()->UpdateState(GRPC_CHANNEL_CONNECTING,
+ channel_control_helper()->UpdateState(GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique(Ref()));
resolver_->StartLocked();
}
@@ -214,7 +215,7 @@ void ResolvingLoadBalancingPolicy::OnResolverError(grpc_error* error) {
"Resolver transient failure", &error, 1);
helper_->ResolverTransientFailure(GRPC_ERROR_REF(state_error));
channel_control_helper()->UpdateState(
- GRPC_CHANNEL_TRANSIENT_FAILURE,
+ GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(state_error),
absl::make_unique(state_error));
}
GRPC_ERROR_UNREF(error);
diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc
index 89a13a3ef74..26bc7f8549f 100644
--- a/src/core/ext/filters/client_channel/subchannel.cc
+++ b/src/core/ext/filters/client_channel/subchannel.cc
@@ -26,6 +26,8 @@
#include
#include
+#include "absl/strings/str_format.h"
+
#include
#include
@@ -325,7 +327,8 @@ class Subchannel::ConnectedSubchannelStateWatcher
}
private:
- void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& status) override {
Subchannel* c = subchannel_;
MutexLock lock(&c->mu_);
switch (new_state) {
@@ -343,7 +346,15 @@ class Subchannel::ConnectedSubchannelStateWatcher
if (c->channelz_node() != nullptr) {
c->channelz_node()->SetChildSocket(nullptr);
}
- c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE);
+ // We need to construct our own status if the underlying state was
+ // shutdown since the accompanying status will be StatusCode::OK
+ // otherwise.
+ c->SetConnectivityStateLocked(
+ GRPC_CHANNEL_TRANSIENT_FAILURE,
+ new_state == GRPC_CHANNEL_SHUTDOWN
+ ? absl::Status(absl::StatusCode::kUnavailable,
+ "Subchannel has disconnected.")
+ : status);
c->backoff_begun_ = false;
c->backoff_.Reset();
}
@@ -354,7 +365,7 @@ class Subchannel::ConnectedSubchannelStateWatcher
// a callback for READY, because that was the state we started
// this watch from. And a connected subchannel should never go
// from READY to CONNECTING or IDLE.
- c->SetConnectivityStateLocked(new_state);
+ c->SetConnectivityStateLocked(new_state, status);
}
}
}
@@ -368,14 +379,15 @@ class Subchannel::AsyncWatcherNotifierLocked {
public:
AsyncWatcherNotifierLocked(
RefCountedPtr watcher,
- Subchannel* subchannel, grpc_connectivity_state state)
+ Subchannel* subchannel, grpc_connectivity_state state,
+ const absl::Status& status)
: watcher_(std::move(watcher)) {
RefCountedPtr connected_subchannel;
if (state == GRPC_CHANNEL_READY) {
connected_subchannel = subchannel->connected_subchannel_;
}
watcher_->PushConnectivityStateChange(
- {state, std::move(connected_subchannel)});
+ {state, status, std::move(connected_subchannel)});
ExecCtx::Run(
DEBUG_LOCATION,
GRPC_CLOSURE_INIT(&closure_,
@@ -409,9 +421,10 @@ void Subchannel::ConnectivityStateWatcherList::RemoveWatcherLocked(
}
void Subchannel::ConnectivityStateWatcherList::NotifyLocked(
- Subchannel* subchannel, grpc_connectivity_state state) {
+ Subchannel* subchannel, grpc_connectivity_state state,
+ const absl::Status& status) {
for (const auto& p : watchers_) {
- new AsyncWatcherNotifierLocked(p.second, subchannel, state);
+ new AsyncWatcherNotifierLocked(p.second, subchannel, state, status);
}
}
@@ -450,7 +463,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
grpc_connectivity_state initial_state,
RefCountedPtr watcher) {
if (state_ != initial_state) {
- new AsyncWatcherNotifierLocked(watcher, subchannel_, state_);
+ new AsyncWatcherNotifierLocked(watcher, subchannel_, state_, status_);
}
watcher_list_.AddWatcherLocked(std::move(watcher));
}
@@ -462,7 +475,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
bool HasWatchers() const { return !watcher_list_.empty(); }
- void NotifyLocked(grpc_connectivity_state state) {
+ void NotifyLocked(grpc_connectivity_state state, const absl::Status& status) {
if (state == GRPC_CHANNEL_READY) {
// If we had not already notified for CONNECTING state, do so now.
// (We may have missed this earlier, because if the transition
@@ -470,13 +483,15 @@ class Subchannel::HealthWatcherMap::HealthWatcher
// subchannel may not have sent us a notification for CONNECTING.)
if (state_ != GRPC_CHANNEL_CONNECTING) {
state_ = GRPC_CHANNEL_CONNECTING;
- watcher_list_.NotifyLocked(subchannel_, state_);
+ status_ = status;
+ watcher_list_.NotifyLocked(subchannel_, state_, status);
}
// If we've become connected, start health checking.
StartHealthCheckingLocked();
} else {
state_ = state;
- watcher_list_.NotifyLocked(subchannel_, state_);
+ status_ = status;
+ watcher_list_.NotifyLocked(subchannel_, state_, status);
// We're not connected, so stop health checking.
health_check_client_.reset();
}
@@ -489,11 +504,13 @@ class Subchannel::HealthWatcherMap::HealthWatcher
}
private:
- void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& status) override {
MutexLock lock(&subchannel_->mu_);
if (new_state != GRPC_CHANNEL_SHUTDOWN && health_check_client_ != nullptr) {
state_ = new_state;
- watcher_list_.NotifyLocked(subchannel_, new_state);
+ status_ = status;
+ watcher_list_.NotifyLocked(subchannel_, new_state, status);
}
}
@@ -508,6 +525,7 @@ class Subchannel::HealthWatcherMap::HealthWatcher
grpc_core::UniquePtr health_check_service_name_;
OrphanablePtr health_check_client_;
grpc_connectivity_state state_;
+ absl::Status status_;
ConnectivityStateWatcherList watcher_list_;
};
@@ -547,9 +565,10 @@ void Subchannel::HealthWatcherMap::RemoveWatcherLocked(
if (!it->second->HasWatchers()) map_.erase(it);
}
-void Subchannel::HealthWatcherMap::NotifyLocked(grpc_connectivity_state state) {
+void Subchannel::HealthWatcherMap::NotifyLocked(grpc_connectivity_state state,
+ const absl::Status& status) {
for (const auto& p : map_) {
- p.second->NotifyLocked(state);
+ p.second->NotifyLocked(state, status);
}
}
@@ -826,7 +845,7 @@ void Subchannel::WatchConnectivityState(
}
if (health_check_service_name == nullptr) {
if (state_ != initial_state) {
- new AsyncWatcherNotifierLocked(watcher, this, state_);
+ new AsyncWatcherNotifierLocked(watcher, this, state_, status_);
}
watcher_list_.AddWatcherLocked(std::move(watcher));
} else {
@@ -928,8 +947,10 @@ const char* SubchannelConnectivityStateChangeString(
} // namespace
// Note: Must be called with a state that is different from the current state.
-void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state) {
+void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state,
+ const absl::Status& status) {
state_ = state;
+ status_ = status;
if (channelz_node_ != nullptr) {
channelz_node_->UpdateConnectivityState(state);
channelz_node_->AddTraceEvent(
@@ -938,9 +959,9 @@ void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state) {
SubchannelConnectivityStateChangeString(state)));
}
// Notify non-health watchers.
- watcher_list_.NotifyLocked(this, state);
+ watcher_list_.NotifyLocked(this, state, status);
// Notify health watchers.
- health_watcher_map_.NotifyLocked(state);
+ health_watcher_map_.NotifyLocked(state, status);
}
void Subchannel::MaybeStartConnectingLocked() {
@@ -1012,7 +1033,7 @@ void Subchannel::ContinueConnectingLocked() {
next_attempt_deadline_ = backoff_.NextAttemptTime();
args.deadline = std::max(next_attempt_deadline_, min_deadline);
args.channel_args = args_;
- SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING);
+ SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING, absl::Status());
connector_->Connect(args, &connecting_result_, &on_connecting_finished_);
}
@@ -1031,7 +1052,8 @@ void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) {
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
} else {
gpr_log(GPR_INFO, "Connect failed: %s", grpc_error_string(error));
- c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE);
+ c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE,
+ grpc_error_to_absl_status(error));
GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting");
}
}
@@ -1091,7 +1113,7 @@ bool Subchannel::PublishTransportLocked() {
connected_subchannel_->StartWatch(
pollset_set_, MakeOrphanable(this));
// Report initial state.
- SetConnectivityStateLocked(GRPC_CHANNEL_READY);
+ SetConnectivityStateLocked(GRPC_CHANNEL_READY, absl::Status());
return true;
}
diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h
index 9478fa7340c..e615c18c944 100644
--- a/src/core/ext/filters/client_channel/subchannel.h
+++ b/src/core/ext/filters/client_channel/subchannel.h
@@ -182,6 +182,7 @@ class Subchannel {
public:
struct ConnectivityStateChange {
grpc_connectivity_state state;
+ absl::Status status;
RefCountedPtr connected_subchannel;
};
@@ -306,7 +307,8 @@ class Subchannel {
void RemoveWatcherLocked(ConnectivityStateWatcherInterface* watcher);
// Notifies all watchers in the list about a change to state.
- void NotifyLocked(Subchannel* subchannel, grpc_connectivity_state state);
+ void NotifyLocked(Subchannel* subchannel, grpc_connectivity_state state,
+ const absl::Status& status);
void Clear() { watchers_.clear(); }
@@ -339,7 +341,8 @@ class Subchannel {
ConnectivityStateWatcherInterface* watcher);
// Notifies the watcher when the subchannel's state changes.
- void NotifyLocked(grpc_connectivity_state state);
+ void NotifyLocked(grpc_connectivity_state state,
+ const absl::Status& status);
grpc_connectivity_state CheckConnectivityStateLocked(
Subchannel* subchannel, const char* health_check_service_name);
@@ -357,7 +360,8 @@ class Subchannel {
class AsyncWatcherNotifierLocked;
// Sets the subchannel's connectivity state to \a state.
- void SetConnectivityStateLocked(grpc_connectivity_state state);
+ void SetConnectivityStateLocked(grpc_connectivity_state state,
+ const absl::Status& status);
// Methods for connection.
void MaybeStartConnectingLocked();
@@ -400,6 +404,7 @@ class Subchannel {
// Connectivity state tracking.
grpc_connectivity_state state_ = GRPC_CHANNEL_IDLE;
+ absl::Status status_;
// The list of watchers without a health check service name.
ConnectivityStateWatcherList watcher_list_;
// The map of watchers with health check service names.
diff --git a/src/core/ext/filters/client_channel/xds/xds_client.cc b/src/core/ext/filters/client_channel/xds/xds_client.cc
index 3010c6b23d0..88e335087e1 100644
--- a/src/core/ext/filters/client_channel/xds/xds_client.cc
+++ b/src/core/ext/filters/client_channel/xds/xds_client.cc
@@ -398,13 +398,15 @@ class XdsClient::ChannelState::StateWatcher
parent_(std::move(parent)) {}
private:
- void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& status) override {
if (!parent_->shutting_down_ &&
new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
// In TRANSIENT_FAILURE. Notify all watchers of error.
gpr_log(GPR_INFO,
- "[xds_client %p] xds channel in state TRANSIENT_FAILURE",
- parent_->xds_client());
+ "[xds_client %p] xds channel in state:TRANSIENT_FAILURE "
+ "status_message:(%s)",
+ parent_->xds_client(), status.ToString().c_str());
parent_->xds_client()->NotifyOnError(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"xds channel in TRANSIENT_FAILURE"));
}
diff --git a/src/core/ext/filters/max_age/max_age_filter.cc b/src/core/ext/filters/max_age/max_age_filter.cc
index 0cf6f542414..ef59d675770 100644
--- a/src/core/ext/filters/max_age/max_age_filter.cc
+++ b/src/core/ext/filters/max_age/max_age_filter.cc
@@ -229,7 +229,8 @@ class ConnectivityWatcher : public AsyncConnectivityStateWatcherInterface {
}
private:
- void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& /* status */) override {
if (new_state != GRPC_CHANNEL_SHUTDOWN) return;
{
MutexLock lock(&chand_->max_age_timer_mu);
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
index 87d0aacd159..bc45e4d69f6 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
@@ -20,6 +20,8 @@
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "absl/strings/str_format.h"
+
#include
#include
#include
@@ -31,7 +33,6 @@
#include
#include
-#include "absl/strings/str_format.h"
#include "src/core/ext/transport/chttp2/transport/context_list.h"
#include "src/core/ext/transport/chttp2/transport/frame_data.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
@@ -127,6 +128,7 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t);
static void connectivity_state_set(grpc_chttp2_transport* t,
grpc_connectivity_state state,
+ const absl::Status& status,
const char* reason);
static void benign_reclaimer(void* t, grpc_error* error);
@@ -562,7 +564,8 @@ static void close_transport_locked(grpc_chttp2_transport* t,
}
GPR_ASSERT(error != GRPC_ERROR_NONE);
t->closed_with_error = GRPC_ERROR_REF(error);
- connectivity_state_set(t, GRPC_CHANNEL_SHUTDOWN, "close_transport");
+ connectivity_state_set(t, GRPC_CHANNEL_SHUTDOWN, absl::Status(),
+ "close_transport");
if (t->ping_state.is_delayed_ping_timer_set) {
grpc_timer_cancel(&t->ping_state.delayed_ping_timer);
}
@@ -1105,9 +1108,11 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
: static_cast(current_keepalive_time_ms *
KEEPALIVE_TIME_BACKOFF_MULTIPLIER);
}
+ absl::Status status = grpc_error_to_absl_status(t->goaway_error);
/* lie: use transient failure from the transport to indicate goaway has been
* received */
- connectivity_state_set(t, GRPC_CHANNEL_TRANSIENT_FAILURE, "got_goaway");
+ connectivity_state_set(t, GRPC_CHANNEL_TRANSIENT_FAILURE, status,
+ "got_goaway");
}
static void maybe_start_some_streams(grpc_chttp2_transport* t) {
@@ -1142,6 +1147,8 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t) {
if (t->next_stream_id >= MAX_CLIENT_STREAM_ID) {
connectivity_state_set(t, GRPC_CHANNEL_TRANSIENT_FAILURE,
+ absl::Status(absl::StatusCode::kUnavailable,
+ "Transport Stream IDs exhausted"),
"no_more_stream_ids");
}
@@ -2919,10 +2926,11 @@ static void keepalive_watchdog_fired_locked(void* arg, grpc_error* error) {
static void connectivity_state_set(grpc_chttp2_transport* t,
grpc_connectivity_state state,
+ const absl::Status& status,
const char* reason) {
GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_INFO, "transport %p set connectivity_state=%d", t, state));
- t->state_tracker.SetState(state, reason);
+ t->state_tracker.SetState(state, status, reason);
}
/*******************************************************************************
diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc
index 49b9bf093ba..d40bffd6d09 100644
--- a/src/core/ext/transport/inproc/inproc_transport.cc
+++ b/src/core/ext/transport/inproc/inproc_transport.cc
@@ -1132,7 +1132,8 @@ void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
void close_transport_locked(inproc_transport* t) {
INPROC_LOG(GPR_INFO, "close_transport %p %d", t, t->is_closed);
- t->state_tracker.SetState(GRPC_CHANNEL_SHUTDOWN, "close transport");
+ t->state_tracker.SetState(GRPC_CHANNEL_SHUTDOWN, absl::Status(),
+ "close transport");
if (!t->is_closed) {
t->is_closed = true;
/* Also end all streams on this transport */
diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc
index cab0cd56c40..9b7c2262137 100644
--- a/src/core/lib/surface/server.cc
+++ b/src/core/lib/surface/server.cc
@@ -1271,7 +1271,8 @@ class ConnectivityWatcher : public AsyncConnectivityStateWatcherInterface {
}
private:
- void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
+ void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& /* status */) override {
// Don't do anything until we are being shut down.
if (new_state != GRPC_CHANNEL_SHUTDOWN) return;
// Shut down channel.
diff --git a/src/core/lib/transport/connectivity_state.cc b/src/core/lib/transport/connectivity_state.cc
index 2d34f52e635..c2008ab82b7 100644
--- a/src/core/lib/transport/connectivity_state.cc
+++ b/src/core/lib/transport/connectivity_state.cc
@@ -58,9 +58,9 @@ const char* ConnectivityStateName(grpc_connectivity_state state) {
class AsyncConnectivityStateWatcherInterface::Notifier {
public:
Notifier(RefCountedPtr watcher,
- grpc_connectivity_state state,
+ grpc_connectivity_state state, const absl::Status& status,
const std::shared_ptr& work_serializer)
- : watcher_(std::move(watcher)), state_(state) {
+ : watcher_(std::move(watcher)), state_(state), status_(status) {
if (work_serializer != nullptr) {
work_serializer->Run(
[this]() { SendNotification(this, GRPC_ERROR_NONE); },
@@ -76,21 +76,24 @@ class AsyncConnectivityStateWatcherInterface::Notifier {
static void SendNotification(void* arg, grpc_error* /*ignored*/) {
Notifier* self = static_cast(arg);
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
- gpr_log(GPR_INFO, "watcher %p: delivering async notification for %s",
- self->watcher_.get(), ConnectivityStateName(self->state_));
+ gpr_log(GPR_INFO, "watcher %p: delivering async notification for %s (%s)",
+ self->watcher_.get(), ConnectivityStateName(self->state_),
+ self->status_.ToString().c_str());
}
- self->watcher_->OnConnectivityStateChange(self->state_);
+ self->watcher_->OnConnectivityStateChange(self->state_, self->status_);
delete self;
}
RefCountedPtr watcher_;
const grpc_connectivity_state state_;
+ const absl::Status status_;
grpc_closure closure_;
};
void AsyncConnectivityStateWatcherInterface::Notify(
- grpc_connectivity_state state) {
- new Notifier(Ref(), state, work_serializer_); // Deletes itself when done.
+ grpc_connectivity_state state, const absl::Status& status) {
+ new Notifier(Ref(), state, status,
+ work_serializer_); // Deletes itself when done.
}
//
@@ -107,7 +110,7 @@ ConnectivityStateTracker::~ConnectivityStateTracker() {
name_, this, p.first, ConnectivityStateName(current_state),
ConnectivityStateName(GRPC_CHANNEL_SHUTDOWN));
}
- p.second->Notify(GRPC_CHANNEL_SHUTDOWN);
+ p.second->Notify(GRPC_CHANNEL_SHUTDOWN, absl::Status());
}
}
@@ -126,7 +129,7 @@ void ConnectivityStateTracker::AddWatcher(
name_, this, watcher.get(), ConnectivityStateName(initial_state),
ConnectivityStateName(current_state));
}
- watcher->Notify(current_state);
+ watcher->Notify(current_state, status_);
}
// If we're in state SHUTDOWN, don't add the watcher, so that it will
// be orphaned immediately.
@@ -145,15 +148,17 @@ void ConnectivityStateTracker::RemoveWatcher(
}
void ConnectivityStateTracker::SetState(grpc_connectivity_state state,
+ const absl::Status& status,
const char* reason) {
grpc_connectivity_state current_state = state_.Load(MemoryOrder::RELAXED);
if (state == current_state) return;
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
- gpr_log(GPR_INFO, "ConnectivityStateTracker %s[%p]: %s -> %s (%s)", name_,
- this, ConnectivityStateName(current_state),
- ConnectivityStateName(state), reason);
+ gpr_log(GPR_INFO, "ConnectivityStateTracker %s[%p]: %s -> %s (%s, %s)",
+ name_, this, ConnectivityStateName(current_state),
+ ConnectivityStateName(state), reason, status.ToString().c_str());
}
state_.Store(state, MemoryOrder::RELAXED);
+ status_ = status;
for (const auto& p : watchers_) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
gpr_log(GPR_INFO,
@@ -161,7 +166,7 @@ void ConnectivityStateTracker::SetState(grpc_connectivity_state state,
name_, this, p.first, ConnectivityStateName(current_state),
ConnectivityStateName(state));
}
- p.second->Notify(state);
+ p.second->Notify(state, status);
}
// If the new state is SHUTDOWN, orphan all of the watchers. This
// avoids the need for the callers to explicitly cancel them.
diff --git a/src/core/lib/transport/connectivity_state.h b/src/core/lib/transport/connectivity_state.h
index 5ab62bed40c..f8a945eb035 100644
--- a/src/core/lib/transport/connectivity_state.h
+++ b/src/core/lib/transport/connectivity_state.h
@@ -21,6 +21,8 @@
#include
+#include "absl/status/status.h"
+
#include
#include "src/core/lib/debug/trace.h"
@@ -49,7 +51,8 @@ class ConnectivityStateWatcherInterface
virtual ~ConnectivityStateWatcherInterface() = default;
// Notifies the watcher that the state has changed to new_state.
- virtual void Notify(grpc_connectivity_state new_state) = 0;
+ virtual void Notify(grpc_connectivity_state new_state,
+ const absl::Status& status) = 0;
void Orphan() override { Unref(); }
};
@@ -64,7 +67,8 @@ class AsyncConnectivityStateWatcherInterface
// Schedules a closure on the ExecCtx to invoke
// OnConnectivityStateChange() asynchronously.
- void Notify(grpc_connectivity_state new_state) override final;
+ void Notify(grpc_connectivity_state new_state,
+ const absl::Status& status) override final;
protected:
class Notifier;
@@ -76,7 +80,8 @@ class AsyncConnectivityStateWatcherInterface
: work_serializer_(std::move(work_serializer)) {}
// Invoked asynchronously when Notify() is called.
- virtual void OnConnectivityStateChange(grpc_connectivity_state new_state) = 0;
+ virtual void OnConnectivityStateChange(grpc_connectivity_state new_state,
+ const absl::Status& status) = 0;
private:
std::shared_ptr work_serializer_;
@@ -91,8 +96,9 @@ class AsyncConnectivityStateWatcherInterface
class ConnectivityStateTracker {
public:
ConnectivityStateTracker(const char* name,
- grpc_connectivity_state state = GRPC_CHANNEL_IDLE)
- : name_(name), state_(state) {}
+ grpc_connectivity_state state = GRPC_CHANNEL_IDLE,
+ const absl::Status& status = absl::Status())
+ : name_(name), state_(state), status_(status) {}
~ConnectivityStateTracker();
@@ -110,15 +116,21 @@ class ConnectivityStateTracker {
// Sets connectivity state.
// Not thread safe; access must be serialized with an external lock.
- void SetState(grpc_connectivity_state state, const char* reason);
+ void SetState(grpc_connectivity_state state, const absl::Status& status,
+ const char* reason);
// Gets the current state.
// Thread safe; no need to use an external lock.
grpc_connectivity_state state() const;
+ // Get the current status.
+ // Not thread safe; access must be serialized with an external lock.
+ absl::Status status() const { return status_; }
+
private:
const char* name_;
Atomic state_;
+ absl::Status status_;
// TODO(roth): Once we can use C++-14 heterogeneous lookups, this can
// be a set instead of a map.
std::map(status),
+ absl::string_view(reinterpret_cast(
+ GRPC_SLICE_START_PTR(message)),
+ GRPC_SLICE_LENGTH(message)));
+}
+
bool grpc_error_has_clear_grpc_status(grpc_error* error) {
intptr_t unused;
if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &unused)) {
diff --git a/src/core/lib/transport/error_utils.h b/src/core/lib/transport/error_utils.h
index 9a46267f38a..e9b1a8f1d2f 100644
--- a/src/core/lib/transport/error_utils.h
+++ b/src/core/lib/transport/error_utils.h
@@ -21,6 +21,8 @@
#include
+#include "absl/status/status.h"
+
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/transport/http2_errors.h"
@@ -37,6 +39,10 @@ void grpc_error_get_status(grpc_error* error, grpc_millis deadline,
grpc_http2_error_code* http_status,
const char** error_string);
+/// Utility Function to convert a grpc_error * \a error to an absl::Status.
+/// Does NOT consume a ref to grpc_error.
+absl::Status grpc_error_to_absl_status(grpc_error* error);
+
/// A utility function to check whether there is a clear status code that
/// doesn't need to be guessed in \a error. This means that \a error or some
/// child has GRPC_ERROR_INT_GRPC_STATUS set, or that it is GRPC_ERROR_NONE or
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 5b9dc43d30d..cb217c93534 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -476,6 +476,7 @@ CORE_SOURCE_FILES = [
'src/core/tsi/transport_security_grpc.cc',
'third_party/abseil-cpp/absl/base/dynamic_annotations.cc',
'third_party/abseil-cpp/absl/base/internal/cycleclock.cc',
+ 'third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc',
'third_party/abseil-cpp/absl/base/internal/raw_logging.cc',
'third_party/abseil-cpp/absl/base/internal/spinlock.cc',
'third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc',
@@ -484,9 +485,18 @@ CORE_SOURCE_FILES = [
'third_party/abseil-cpp/absl/base/internal/throw_delegate.cc',
'third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc',
'third_party/abseil-cpp/absl/base/log_severity.cc',
+ 'third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc',
+ 'third_party/abseil-cpp/absl/debugging/internal/demangle.cc',
+ 'third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc',
+ 'third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc',
+ 'third_party/abseil-cpp/absl/debugging/stacktrace.cc',
+ 'third_party/abseil-cpp/absl/debugging/symbolize.cc',
'third_party/abseil-cpp/absl/numeric/int128.cc',
+ 'third_party/abseil-cpp/absl/status/status.cc',
+ 'third_party/abseil-cpp/absl/status/status_payload_printer.cc',
'third_party/abseil-cpp/absl/strings/ascii.cc',
'third_party/abseil-cpp/absl/strings/charconv.cc',
+ 'third_party/abseil-cpp/absl/strings/cord.cc',
'third_party/abseil-cpp/absl/strings/escaping.cc',
'third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc',
'third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc',
diff --git a/test/core/surface/lame_client_test.cc b/test/core/surface/lame_client_test.cc
index 812b1455094..c63335445d7 100644
--- a/test/core/surface/lame_client_test.cc
+++ b/test/core/surface/lame_client_test.cc
@@ -30,7 +30,8 @@
class Watcher : public grpc_core::ConnectivityStateWatcherInterface {
public:
- void Notify(grpc_connectivity_state new_state) override {
+ void Notify(grpc_connectivity_state new_state,
+ const absl::Status& /* status */) override {
GPR_ASSERT(new_state == GRPC_CHANNEL_SHUTDOWN);
}
};
diff --git a/test/core/transport/chttp2/too_many_pings_test.cc b/test/core/transport/chttp2/too_many_pings_test.cc
index 708ddd1cfde..308b7216e12 100644
--- a/test/core/transport/chttp2/too_many_pings_test.cc
+++ b/test/core/transport/chttp2/too_many_pings_test.cc
@@ -65,7 +65,6 @@ grpc_status_code PerformCall(grpc_channel* channel, grpc_server* server,
cq_verifier* cqv = cq_verifier_create(cq);
grpc_op ops[6];
grpc_op* op;
- grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv;
grpc_metadata_array request_metadata_recv;
grpc_call_details call_details;
@@ -78,7 +77,6 @@ grpc_status_code PerformCall(grpc_channel* channel, grpc_server* server,
grpc_slice_from_static_string("/foo"), nullptr,
deadline, nullptr);
GPR_ASSERT(c);
- grpc_metadata_array_init(&initial_metadata_recv);
grpc_metadata_array_init(&trailing_metadata_recv);
grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details);
@@ -111,7 +109,6 @@ grpc_status_code PerformCall(grpc_channel* channel, grpc_server* server,
cq_verify(cqv);
// cleanup
grpc_slice_unref(details);
- grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_details_destroy(&call_details);
diff --git a/test/core/transport/connectivity_state_test.cc b/test/core/transport/connectivity_state_test.cc
index 23bd100e686..e0bd8d02198 100644
--- a/test/core/transport/connectivity_state_test.cc
+++ b/test/core/transport/connectivity_state_test.cc
@@ -42,116 +42,164 @@ TEST(ConnectivityStateName, Basic) {
class Watcher : public ConnectivityStateWatcherInterface {
public:
- Watcher(int* count, grpc_connectivity_state* output,
+ Watcher(int* count, grpc_connectivity_state* output, absl::Status* status,
bool* destroyed = nullptr)
- : count_(count), output_(output), destroyed_(destroyed) {}
+ : count_(count),
+ output_(output),
+ status_(status),
+ destroyed_(destroyed) {}
~Watcher() {
if (destroyed_ != nullptr) *destroyed_ = true;
}
- void Notify(grpc_connectivity_state new_state) override {
+ void Notify(grpc_connectivity_state new_state,
+ const absl::Status& status) override {
++*count_;
*output_ = new_state;
+ *status_ = status;
}
private:
int* count_;
grpc_connectivity_state* output_;
+ absl::Status* status_;
bool* destroyed_;
};
TEST(StateTracker, SetAndGetState) {
- ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING);
+ ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING,
+ absl::Status());
EXPECT_EQ(tracker.state(), GRPC_CHANNEL_CONNECTING);
- tracker.SetState(GRPC_CHANNEL_READY, "whee");
+ EXPECT_TRUE(tracker.status().ok());
+ tracker.SetState(GRPC_CHANNEL_READY, absl::Status(), "whee");
EXPECT_EQ(tracker.state(), GRPC_CHANNEL_READY);
+ EXPECT_TRUE(tracker.status().ok());
+ absl::Status transient_failure_status(absl::StatusCode::kUnavailable,
+ "status for testing");
+ tracker.SetState(GRPC_CHANNEL_TRANSIENT_FAILURE, transient_failure_status,
+ "reason");
+ EXPECT_EQ(tracker.state(), GRPC_CHANNEL_TRANSIENT_FAILURE);
+ EXPECT_EQ(tracker.status(), transient_failure_status);
}
TEST(StateTracker, NotificationUponAddingWatcher) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
- MakeOrphanable(&count, &state));
+ MakeOrphanable(&count, &state, &status));
EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_CONNECTING);
+ EXPECT_TRUE(status.ok());
+}
+
+TEST(StateTracker, NotificationUponAddingWatcherWithTransientFailure) {
+ int count = 0;
+ grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
+ absl::Status transient_failure_status(absl::StatusCode::kUnavailable,
+ "status for testing");
+ ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_TRANSIENT_FAILURE,
+ transient_failure_status);
+ tracker.AddWatcher(GRPC_CHANNEL_IDLE,
+ MakeOrphanable(&count, &state, &status));
+ EXPECT_EQ(count, 1);
+ EXPECT_EQ(state, GRPC_CHANNEL_TRANSIENT_FAILURE);
+ EXPECT_EQ(status, transient_failure_status);
}
TEST(StateTracker, NotificationUponStateChange) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
- MakeOrphanable(&count, &state));
+ MakeOrphanable(&count, &state, &status));
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
- tracker.SetState(GRPC_CHANNEL_CONNECTING, "whee");
+ EXPECT_TRUE(status.ok());
+ absl::Status transient_failure_status(absl::StatusCode::kUnavailable,
+ "status for testing");
+ tracker.SetState(GRPC_CHANNEL_TRANSIENT_FAILURE, transient_failure_status,
+ "whee");
EXPECT_EQ(count, 1);
- EXPECT_EQ(state, GRPC_CHANNEL_CONNECTING);
+ EXPECT_EQ(state, GRPC_CHANNEL_TRANSIENT_FAILURE);
+ EXPECT_EQ(status, transient_failure_status);
}
TEST(StateTracker, SubscribeThenUnsubscribe) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
bool destroyed = false;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
ConnectivityStateWatcherInterface* watcher =
- new Watcher(&count, &state, &destroyed);
+ new Watcher(&count, &state, &status, &destroyed);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
OrphanablePtr(watcher));
// No initial notification, since we started the watch from the
// current state.
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
+ EXPECT_TRUE(status.ok());
// Cancel watch. This should not generate another notification.
tracker.RemoveWatcher(watcher);
EXPECT_TRUE(destroyed);
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
+ EXPECT_TRUE(status.ok());
}
TEST(StateTracker, OrphanUponShutdown) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
bool destroyed = false;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
ConnectivityStateWatcherInterface* watcher =
- new Watcher(&count, &state, &destroyed);
+ new Watcher(&count, &state, &status, &destroyed);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
OrphanablePtr(watcher));
// No initial notification, since we started the watch from the
// current state.
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
+ EXPECT_TRUE(status.ok());
// Set state to SHUTDOWN.
- tracker.SetState(GRPC_CHANNEL_SHUTDOWN, "shutting down");
+ tracker.SetState(GRPC_CHANNEL_SHUTDOWN, absl::Status(), "shutting down");
EXPECT_TRUE(destroyed);
EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
+ EXPECT_TRUE(status.ok());
}
TEST(StateTracker, AddWhenAlreadyShutdown) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
bool destroyed = false;
- ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN);
+ ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN,
+ absl::Status());
ConnectivityStateWatcherInterface* watcher =
- new Watcher(&count, &state, &destroyed);
+ new Watcher(&count, &state, &status, &destroyed);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
OrphanablePtr(watcher));
EXPECT_TRUE(destroyed);
EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
+ EXPECT_TRUE(status.ok());
}
TEST(StateTracker, NotifyShutdownAtDestruction) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
+ absl::Status status;
{
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
- MakeOrphanable(&count, &state));
+ MakeOrphanable(&count, &state, &status));
// No initial notification, since we started the watch from the
// current state.
EXPECT_EQ(count, 0);
@@ -165,10 +213,11 @@ TEST(StateTracker, NotifyShutdownAtDestruction) {
TEST(StateTracker, DoNotNotifyShutdownAtDestructionIfAlreadyInShutdown) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_SHUTDOWN;
+ absl::Status status;
{
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN);
tracker.AddWatcher(GRPC_CHANNEL_SHUTDOWN,
- MakeOrphanable(&count, &state));
+ MakeOrphanable(&count, &state, &status));
// No initial notification, since we started the watch from the
// current state.
EXPECT_EQ(count, 0);
diff --git a/test/core/util/test_lb_policies.cc b/test/core/util/test_lb_policies.cc
index 56978b97949..5aa5dabafa0 100644
--- a/test/core/util/test_lb_policies.cc
+++ b/test/core/util/test_lb_policies.cc
@@ -142,10 +142,10 @@ class TestPickArgsLb : public ForwardingLoadBalancingPolicy {
return parent_->channel_control_helper()->CreateSubchannel(args);
}
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override {
parent_->channel_control_helper()->UpdateState(
- state, absl::make_unique(std::move(picker), cb_));
+ state, status, absl::make_unique(std::move(picker), cb_));
}
void RequestReresolution() override {
@@ -252,10 +252,10 @@ class InterceptRecvTrailingMetadataLoadBalancingPolicy
return parent_->channel_control_helper()->CreateSubchannel(args);
}
- void UpdateState(grpc_connectivity_state state,
+ void UpdateState(grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr picker) override {
parent_->channel_control_helper()->UpdateState(
- state, absl::make_unique(std::move(picker), cb_));
+ state, status, absl::make_unique(std::move(picker), cb_));
}
void RequestReresolution() override {