Plumb absl::Status through connectivity state notifiers

pull/23480/head
Yash Tibrewal 4 years ago
parent 089d90933a
commit 2c5291ff71
  1. 1
      BUILD
  2. 1
      BUILD.gn
  3. 19
      CMakeLists.txt
  4. 10
      Makefile
  5. 2
      build_autogenerated.yaml
  6. 13
      config.m4
  7. 13
      config.w32
  8. 1
      gRPC-C++.podspec
  9. 1
      gRPC-Core.podspec
  10. 37
      grpc.gemspec
  11. 2
      grpc.gyp
  12. 37
      package.xml
  13. 29
      src/core/ext/filters/client_channel/client_channel.cc
  14. 6
      src/core/ext/filters/client_channel/health/health_check_client.cc
  15. 2
      src/core/ext/filters/client_channel/lb_policy.h
  16. 10
      src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc
  17. 28
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  18. 32
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
  19. 39
      src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
  20. 9
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
  21. 29
      src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
  22. 28
      src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
  23. 30
      src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
  24. 23
      src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc
  25. 20
      src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
  26. 9
      src/core/ext/filters/client_channel/resolving_lb_policy.cc
  27. 66
      src/core/ext/filters/client_channel/subchannel.cc
  28. 11
      src/core/ext/filters/client_channel/subchannel.h
  29. 8
      src/core/ext/filters/client_channel/xds/xds_client.cc
  30. 3
      src/core/ext/filters/max_age/max_age_filter.cc
  31. 16
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  32. 3
      src/core/ext/transport/inproc/inproc_transport.cc
  33. 3
      src/core/lib/surface/server.cc
  34. 31
      src/core/lib/transport/connectivity_state.cc
  35. 24
      src/core/lib/transport/connectivity_state.h
  36. 13
      src/core/lib/transport/error_utils.cc
  37. 6
      src/core/lib/transport/error_utils.h
  38. 10
      src/python/grpcio/grpc_core_dependencies.py
  39. 3
      test/core/surface/lame_client_test.cc
  40. 3
      test/core/transport/chttp2/too_many_pings_test.cc
  41. 81
      test/core/transport/connectivity_state_test.cc
  42. 8
      test/core/util/test_lb_policies.cc

@ -956,6 +956,7 @@ grpc_cc_library(
external_deps = [
"madler_zlib",
"absl/container:inlined_vector",
"absl/status",
"absl/types:optional",
],
language = "c++",

@ -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",

@ -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")

@ -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 \

@ -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

@ -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)

@ -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");

@ -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

@ -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

@ -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 )

@ -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': [

@ -971,12 +971,15 @@
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/bits.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/cycleclock.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/cycleclock.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/direct_mmap.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/endian.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/errno_saver.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/hide_ptr.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/identity.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/inline_variable.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/invoke.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/low_level_alloc.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/per_thread_tls.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/internal/raw_logging.cc" role="src" />
@ -1009,19 +1012,52 @@
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/policy_checks.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/port.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/thread_annotations.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/fixed_array.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/inlined_vector.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/internal/compressed_tuple.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/internal/inlined_vector.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/address_is_readable.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/demangle.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/demangle.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/symbolize.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/internal/vdso_support.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/stacktrace.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/stacktrace.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/symbolize.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/symbolize.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/symbolize_elf.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/symbolize_unimplemented.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/debugging/symbolize_win32.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/functional/function_ref.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/functional/internal/function_ref.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/memory/memory.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/meta/type_traits.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/numeric/int128.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/numeric/int128.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/status/status.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/status/status.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/status/status_payload_printer.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/status/status_payload_printer.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/ascii.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/ascii.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/charconv.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/charconv.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/cord.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/cord.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/escaping.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/escaping.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/char_map.h" role="src" />
@ -1029,6 +1065,7 @@
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/charconv_parse.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/cord_internal.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/escaping.cc" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/escaping.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/strings/internal/memutil.cc" role="src" />

@ -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<LoadBalancingPolicy::SubchannelPicker> 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<LoadBalancingPolicy::SubchannelPicker> 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<LoadBalancingPolicy::SubchannelPicker> 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<grpc_connectivity_state>(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<LoadBalancingPolicy::TransientFailurePicker>(
GRPC_ERROR_REF(op->disconnect_with_error)));
}

@ -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() {

@ -24,6 +24,7 @@
#include <functional>
#include <iterator>
#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<LoadBalancingPolicy> {
/// 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<SubchannelPicker>) = 0;
/// Requests that the resolver re-resolve.

@ -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<SubchannelPicker> 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 {

@ -304,7 +304,7 @@ class GrpcLb : public LoadBalancingPolicy {
RefCountedPtr<SubchannelInterface> 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<SubchannelPicker> 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<SubchannelInterface> GrpcLb::Helper::CreateSubchannel(
}
void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> 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<GrpcLbClientStats> 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<Picker>(parent_.get(), parent_->serverlist_,
std::move(picker), std::move(client_stats)));
}

@ -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<TransientFailurePicker>(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<TransientFailurePicker>(error));
} else {
p->channel_control_helper()->UpdateState(
GRPC_CHANNEL_CONNECTING, absl::make_unique<QueuePicker>(p->Ref(
DEBUG_LOCATION, "QueuePicker")));
GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique<QueuePicker>(
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<QueuePicker>(
p->Ref(DEBUG_LOCATION, "QueuePicker")));
GRPC_CHANNEL_IDLE, absl::Status(),
absl::make_unique<QueuePicker>(
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<Picker>(subchannel()->Ref()));
} else { // CONNECTING
p->channel_control_helper()->UpdateState(
connectivity_state, absl::make_unique<QueuePicker>(
p->Ref(DEBUG_LOCATION, "QueuePicker")));
connectivity_state, absl::Status(),
absl::make_unique<QueuePicker>(
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<TransientFailurePicker>(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<QueuePicker>(p->Ref(
DEBUG_LOCATION, "QueuePicker")));
GRPC_CHANNEL_CONNECTING, absl::Status(),
absl::make_unique<QueuePicker>(
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<Picker>(subchannel()->Ref()));
GRPC_CHANNEL_READY, absl::Status(),
absl::make_unique<Picker>(subchannel()->Ref()));
for (size_t i = 0; i < subchannel_list()->num_subchannels(); ++i) {
if (i != Index()) {
subchannel_list()->subchannel(i)->ShutdownLocked();

@ -20,6 +20,7 @@
#include <limits.h>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include <grpc/grpc.h>
@ -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<SubchannelInterface> CreateSubchannel(
const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> 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<SubchannelPicker> picker);
void StartFailoverTimerLocked();
@ -180,6 +188,7 @@ class PriorityLb : public LoadBalancingPolicy {
OrphanablePtr<LoadBalancingPolicy> child_policy_;
grpc_connectivity_state connectivity_state_ = GRPC_CHANNEL_CONNECTING;
absl::Status connectivity_status_;
RefCountedPtr<RefCountedPicker> 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<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker")));
}
child = MakeOrphanable<ChildPriority>(
@ -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<QueuePicker>(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<TransientFailurePicker>(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<SubchannelPicker> picker) {
grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> 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<RefCountedPicker>(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<SubchannelPicker> picker) {
grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> 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(

@ -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<Picker>(p, this));
GRPC_CHANNEL_READY, absl::Status(), absl::make_unique<Picker>(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<QueuePicker>(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<TransientFailurePicker>(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<TransientFailurePicker>(error));
subchannel_list_ = std::move(latest_pending_subchannel_list_);
} else if (subchannel_list_ == nullptr) {

@ -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<SubchannelInterface> CreateSubchannel(
const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> 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<SubchannelPicker> picker);
static void OnDelayedRemovalTimer(void* arg, grpc_error* error);
@ -375,6 +377,7 @@ void WeightedTargetLb::UpdateStateLocked() {
this, ConnectivityStateName(connectivity_state));
}
std::unique_ptr<SubchannelPicker> picker;
absl::Status status;
switch (connectivity_state) {
case GRPC_CHANNEL_READY:
picker = absl::make_unique<WeightedPicker>(std::move(picker_list));
@ -385,11 +388,15 @@ void WeightedTargetLb::UpdateStateLocked() {
absl::make_unique<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker"));
break;
default:
picker = absl::make_unique<TransientFailurePicker>(
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<TransientFailurePicker>(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<SubchannelPicker> picker) {
grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) {
// Cache the picker in the WeightedChild.
picker_wrapper_ = MakeRefCounted<ChildPickerWrapper>(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<SubchannelPicker> picker) {
grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> 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() {

@ -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<CdsLb> parent) : parent_(std::move(parent)) {}
RefCountedPtr<SubchannelInterface> 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<SubchannelPicker> 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<TransientFailurePicker>(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<TransientFailurePicker>(
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<TransientFailurePicker>(error));
parent_->MaybeDestroyChildPolicyLocked();
}
@ -242,13 +245,16 @@ RefCountedPtr<SubchannelInterface> CdsLb::Helper::CreateSubchannel(
}
void CdsLb::Helper::UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> 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() {

@ -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<SubchannelInterface> 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<SubchannelPicker> 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<ChildPickerWrapper> child_picker_;
};
@ -265,16 +267,21 @@ RefCountedPtr<SubchannelInterface> EdsLb::Helper::CreateSubchannel(
}
void EdsLb::Helper::UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> 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<ChildPickerWrapper>(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<TransientFailurePicker>(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<TransientFailurePicker>(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"EDS resource does not exist")));
GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error),
absl::make_unique<TransientFailurePicker>(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<TransientFailurePicker>(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<DropPicker>(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<DropPicker>(this));
}
}

@ -120,7 +120,7 @@ class LrsLb : public LoadBalancingPolicy {
RefCountedPtr<SubchannelInterface> 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<SubchannelPicker> 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<RefCountedPicker> picker_;
};
@ -266,10 +267,14 @@ void LrsLb::MaybeUpdatePickerLocked() {
auto lrs_picker =
absl::make_unique<LoadReportingPicker>(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<SubchannelInterface> LrsLb::Helper::CreateSubchannel(
}
void LrsLb::Helper::UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> 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<RefCountedPicker>(std::move(picker));
// Wrap the picker and return it to the channel.
lrs_policy_->MaybeUpdatePickerLocked();

@ -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<SubchannelInterface> CreateSubchannel(
const grpc_channel_args& args) override;
void UpdateState(grpc_connectivity_state state,
const absl::Status& status,
std::unique_ptr<SubchannelPicker> picker) override;
void RequestReresolution() override;
void AddTraceEvent(TraceSeverity severity,
@ -464,6 +466,7 @@ void XdsRoutingLb::UpdateStateLocked() {
ConnectivityStateName(connectivity_state));
}
std::unique_ptr<SubchannelPicker> 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<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker"));
break;
default:
picker = absl::make_unique<TransientFailurePicker>(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<TransientFailurePicker>(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<SubchannelPicker> picker) {
grpc_connectivity_state state, const absl::Status& status,
std::unique_ptr<SubchannelPicker> 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.

@ -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<SubchannelPicker> 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<QueuePicker>(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<TransientFailurePicker>(state_error));
}
GRPC_ERROR_UNREF(error);

@ -26,6 +26,8 @@
#include <algorithm>
#include <cstring>
#include "absl/strings/str_format.h"
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
@ -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<Subchannel::ConnectivityStateWatcherInterface> watcher,
Subchannel* subchannel, grpc_connectivity_state state)
Subchannel* subchannel, grpc_connectivity_state state,
const absl::Status& status)
: watcher_(std::move(watcher)) {
RefCountedPtr<ConnectedSubchannel> 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<Subchannel::ConnectivityStateWatcherInterface> 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<char> health_check_service_name_;
OrphanablePtr<HealthCheckClient> 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<ConnectedSubchannelStateWatcher>(this));
// Report initial state.
SetConnectivityStateLocked(GRPC_CHANNEL_READY);
SetConnectivityStateLocked(GRPC_CHANNEL_READY, absl::Status());
return true;
}

@ -182,6 +182,7 @@ class Subchannel {
public:
struct ConnectivityStateChange {
grpc_connectivity_state state;
absl::Status status;
RefCountedPtr<ConnectedSubchannel> 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.

@ -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"));
}

@ -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);

@ -20,6 +20,8 @@
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "absl/strings/str_format.h"
#include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@ -31,7 +33,6 @@
#include <stdio.h>
#include <string.h>
#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<grpc_millis>(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);
}
/*******************************************************************************

@ -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 */

@ -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.

@ -58,9 +58,9 @@ const char* ConnectivityStateName(grpc_connectivity_state state) {
class AsyncConnectivityStateWatcherInterface::Notifier {
public:
Notifier(RefCountedPtr<AsyncConnectivityStateWatcherInterface> watcher,
grpc_connectivity_state state,
grpc_connectivity_state state, const absl::Status& status,
const std::shared_ptr<WorkSerializer>& 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<Notifier*>(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<AsyncConnectivityStateWatcherInterface> 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.

@ -21,6 +21,8 @@
#include <grpc/support/port_platform.h>
#include "absl/status/status.h"
#include <grpc/grpc.h>
#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<WorkSerializer> 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<grpc_connectivity_state> 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<ConnectivityStateWatcherInterface*,

@ -123,6 +123,19 @@ void grpc_error_get_status(grpc_error* error, grpc_millis deadline,
}
}
absl::Status grpc_error_to_absl_status(grpc_error* error) {
grpc_status_code status;
// TODO(yashykt): This should be updated once we decide on how to use the
// absl::Status payload to capture all the contents of grpc_error.
grpc_slice message;
grpc_error_get_status(error, GRPC_MILLIS_INF_FUTURE, &status, &message,
nullptr /* http_error */, nullptr /* error_string */);
return absl::Status(static_cast<absl::StatusCode>(status),
absl::string_view(reinterpret_cast<const char*>(
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)) {

@ -21,6 +21,8 @@
#include <grpc/support/port_platform.h>
#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

@ -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',

@ -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);
}
};

@ -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);

@ -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<Watcher>(&count, &state));
MakeOrphanable<Watcher>(&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<Watcher>(&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<Watcher>(&count, &state));
MakeOrphanable<Watcher>(&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<ConnectivityStateWatcherInterface>(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<ConnectivityStateWatcherInterface>(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<ConnectivityStateWatcherInterface>(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<Watcher>(&count, &state));
MakeOrphanable<Watcher>(&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<Watcher>(&count, &state));
MakeOrphanable<Watcher>(&count, &state, &status));
// No initial notification, since we started the watch from the
// current state.
EXPECT_EQ(count, 0);

@ -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<SubchannelPicker> picker) override {
parent_->channel_control_helper()->UpdateState(
state, absl::make_unique<Picker>(std::move(picker), cb_));
state, status, absl::make_unique<Picker>(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<SubchannelPicker> picker) override {
parent_->channel_control_helper()->UpdateState(
state, absl::make_unique<Picker>(std::move(picker), cb_));
state, status, absl::make_unique<Picker>(std::move(picker), cb_));
}
void RequestReresolution() override {

Loading…
Cancel
Save