Merge branch 'master' into chttp2combiner

pull/20331/head
Yash Tibrewal 5 years ago
commit 0978a15561
  1. 2
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 2
      .github/ISSUE_TEMPLATE/cleanup_request.md
  3. 2
      .github/ISSUE_TEMPLATE/feature_request.md
  4. 2
      .github/pull_request_template.md
  5. 10
      BUILD
  6. 83
      CMakeLists.txt
  7. 4
      CONTRIBUTING.md
  8. 1
      GOVERNANCE.md
  9. 82
      MAINTAINERS.md
  10. 84
      Makefile
  11. 19
      build.yaml
  12. 8
      examples/cpp/helloworld/.gitignore
  13. 7
      include/grpc/impl/codegen/grpc_types.h
  14. 6
      include/grpcpp/impl/codegen/config_protobuf.h
  15. 4
      include/grpcpp/impl/codegen/proto_buffer_reader.h
  16. 2
      include/grpcpp/impl/codegen/proto_buffer_writer.h
  17. 13
      include/grpcpp/impl/codegen/server_interface.h
  18. 4
      package.xml
  19. 235
      src/core/ext/filters/client_channel/client_channel.cc
  20. 6
      src/core/ext/filters/client_channel/client_channel.h
  21. 5
      src/core/ext/filters/client_channel/client_channel_channelz.cc
  22. 8
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  23. 2
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
  24. 4
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
  25. 6
      src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
  26. 982
      src/core/ext/filters/client_channel/lb_policy/xds/xds.cc
  27. 78
      src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.cc
  28. 83
      src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.h
  29. 3
      src/core/ext/filters/client_channel/resolving_lb_policy.cc
  30. 97
      src/core/ext/filters/client_channel/subchannel.cc
  31. 6
      src/core/ext/filters/client_channel/subchannel.h
  32. 85
      src/core/ext/filters/max_age/max_age_filter.cc
  33. 31
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  34. 16
      src/core/ext/transport/chttp2/transport/internal.h
  35. 33
      src/core/ext/transport/inproc/inproc_transport.cc
  36. 16
      src/core/lib/channel/channel_args.cc
  37. 14
      src/core/lib/channel/channel_args.h
  38. 3
      src/core/lib/channel/channelz.cc
  39. 4
      src/core/lib/gprpp/inlined_vector.h
  40. 2
      src/core/lib/iomgr/executor.cc
  41. 35
      src/core/lib/iomgr/poller/eventmanager_interface.h
  42. 13
      src/core/lib/iomgr/socket_utils_common_posix.cc
  43. 4
      src/core/lib/iomgr/socket_utils_posix.h
  44. 15
      src/core/lib/iomgr/tcp_client_posix.cc
  45. 13
      src/core/lib/iomgr/tcp_server_utils_posix_common.cc
  46. 7
      src/core/lib/surface/channel.cc
  47. 29
      src/core/lib/surface/lame_client.cc
  48. 67
      src/core/lib/surface/server.cc
  49. 203
      src/core/lib/transport/connectivity_state.cc
  50. 140
      src/core/lib/transport/connectivity_state.h
  51. 9
      src/core/lib/transport/transport.h
  52. 25
      src/core/lib/transport/transport_op_string.cc
  53. 2
      src/core/tsi/alts/frame_protector/alts_frame_protector.cc
  54. 14
      src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc
  55. 1
      src/core/tsi/fake_transport_security.cc
  56. 5792
      src/core/tsi/grpc_shadow_boringssl.h
  57. 3
      src/core/tsi/local_transport_security.cc
  58. 7
      src/core/tsi/transport_security_grpc.cc
  59. 6
      src/core/tsi/transport_security_grpc.h
  60. 4
      src/csharp/docfx/generate_reference_docs.sh
  61. 2
      src/csharp/experimental/build_native_ext_for_ios.sh
  62. 5804
      src/objective-c/BoringSSL-GRPC.podspec
  63. 2
      src/objective-c/CronetFramework.podspec
  64. 5792
      src/objective-c/grpc_shadow_boringssl_symbol_list
  65. 119
      src/objective-c/tests/PerfTests/PerfTests.m
  66. 30
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/PerfTests.xcscheme
  67. 85
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/PerfTestsPosix.xcscheme
  68. 22
      src/objective-c/tests/run_one_test.sh
  69. 64
      src/php/ext/grpc/channel.c
  70. 18
      src/php/tests/MemoryLeakTest/MemoryLeakTest.php
  71. 10
      templates/CMakeLists.txt.template
  72. 4
      templates/package.xml.template
  73. 4
      templates/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh.template
  74. 127
      test/core/channel/channel_args_test.cc
  75. 4
      test/core/channel/channelz_test.cc
  76. 10
      test/core/client_channel/service_config_test.cc
  77. 4
      test/core/debug/stats_test.cc
  78. 5
      test/core/end2end/fuzzers/server_fuzzer.cc
  79. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/hope.bin
  80. 3
      test/core/end2end/h2_ssl_cert_test.cc
  81. 18
      test/core/gprpp/inlined_vector_test.cc
  82. 32
      test/core/surface/lame_client_test.cc
  83. 3
      test/core/transport/BUILD
  84. 6
      test/core/transport/bdp_estimator_test.cc
  85. 206
      test/core/transport/connectivity_state_test.cc
  86. 2
      test/core/transport/pid_controller_test.cc
  87. 7
      test/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector_test.cc
  88. 2
      test/core/util/fuzzer_corpus_test.cc
  89. 4
      test/core/util/ubsan_suppressions.txt
  90. 4
      test/cpp/common/time_jump_test.cc
  91. 11
      test/cpp/end2end/async_end2end_test.cc
  92. 4
      test/cpp/end2end/cfstream_test.cc
  93. 4
      test/cpp/end2end/client_callback_end2end_test.cc
  94. 10
      test/cpp/end2end/end2end_test.cc
  95. 4
      test/cpp/end2end/flaky_network_test.cc
  96. 4
      test/cpp/end2end/hybrid_end2end_test.cc
  97. 12
      test/cpp/end2end/message_allocator_end2end_test.cc
  98. 4
      test/cpp/end2end/port_sharing_end2end_test.cc
  99. 4
      test/cpp/end2end/server_builder_plugin_test.cc
  100. 4
      test/cpp/end2end/shutdown_test.cc
  101. Some files were not shown because too many files have changed in this diff Show More

@ -2,7 +2,7 @@
name: Report a bug
about: Create a report to help us improve
labels: kind/bug, priority/P2
assignees: veblush
assignees: nicolasnoble
---

@ -2,7 +2,7 @@
name: Request a cleanup
about: Suggest a cleanup in our repository
labels: kind/internal cleanup
assignees: veblush
assignees: nicolasnoble
---

@ -2,7 +2,7 @@
name: Request a feature
about: Suggest an idea for this project
labels: kind/enhancement
assignees: veblush
assignees: nicolasnoble
---

@ -8,4 +8,4 @@ If you know who should review your pull request, please remove the mentioning be
-->
@veblush
@nicolasnoble

10
BUILD

@ -1958,6 +1958,7 @@ grpc_cc_library(
deps = [
"grpc",
"grpc++_codegen_base",
"grpc++_codegen_base_src",
"grpc_health_upb",
],
)
@ -1970,6 +1971,7 @@ grpc_cc_library(
public_hdrs = GRPCXX_PUBLIC_HDRS,
deps = [
"grpc++_codegen_base",
"grpc++_codegen_base_src",
"grpc_health_upb",
"grpc_unsecure",
],
@ -2519,3 +2521,11 @@ filegroup(
],
visibility = ["//visibility:public"],
)
# Base classes of EventManagerInterface
grpc_cc_library(
name = "eventmanager_interface",
hdrs = [
"src/core/lib/iomgr/poller/eventmanager_interface.h",
],
)

@ -100,14 +100,16 @@ if (MSVC)
include(cmake/msvc_static_runtime.cmake)
add_definitions(-D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS)
# needed to compile protobuf
add_definitions(/wd4065 /wd4506)
set(_gRPC_C_CXX_FLAGS "${_gRPC_C_CXX_FLAGS} /wd4065 /wd4506")
# TODO(jtattermusch): revisit warnings that were silenced as part of upgrade to protobuf3.6.0
add_definitions(/wd4200 /wd4291 /wd4244)
set(_gRPC_C_CXX_FLAGS "${_gRPC_C_CXX_FLAGS} /wd4200 /wd4291 /wd4244")
# TODO(jtattermusch): revisit C4267 occurrences throughout the code
add_definitions(/wd4267)
set(_gRPC_C_CXX_FLAGS "${_gRPC_C_CXX_FLAGS} /wd4267")
# TODO(jtattermusch): needed to build boringssl with VS2017, revisit later
add_definitions(/wd4987 /wd4774 /wd4819 /wd4996 /wd4619)
set(_gRPC_C_CXX_FLAGS "${_gRPC_C_CXX_FLAGS} /wd4987 /wd4774 /wd4819 /wd4996 /wd4619")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_gRPC_C_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_gRPC_C_CXX_FLAGS}")
if (gRPC_USE_PROTO_LITE)
set(_gRPC_PROTOBUF_LIBRARY_NAME "libprotobuf-lite")
@ -425,7 +427,6 @@ add_dependencies(buildtests_c time_averaged_stats_test)
add_dependencies(buildtests_c timeout_encoding_test)
add_dependencies(buildtests_c timer_heap_test)
add_dependencies(buildtests_c timer_list_test)
add_dependencies(buildtests_c transport_connectivity_state_test)
add_dependencies(buildtests_c transport_metadata_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c transport_security_test)
@ -724,6 +725,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx time_change_test)
endif()
add_dependencies(buildtests_cxx timer_test)
add_dependencies(buildtests_cxx transport_connectivity_state_test)
add_dependencies(buildtests_cxx transport_pid_controller_test)
add_dependencies(buildtests_cxx transport_security_common_api_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@ -9845,37 +9847,6 @@ target_link_libraries(timer_list_test
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(transport_connectivity_state_test
test/core/transport/connectivity_state_test.cc
)
target_include_directories(transport_connectivity_state_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_UPB_GENERATED_DIR}
PRIVATE ${_gRPC_UPB_GRPC_GENERATED_DIR}
PRIVATE ${_gRPC_UPB_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
)
target_link_libraries(transport_connectivity_state_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
@ -16690,6 +16661,46 @@ target_link_libraries(timer_test
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(transport_connectivity_state_test
test/core/transport/connectivity_state_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(transport_connectivity_state_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${_gRPC_UPB_GENERATED_DIR}
PRIVATE ${_gRPC_UPB_GRPC_GENERATED_DIR}
PRIVATE ${_gRPC_UPB_INCLUDE_DIR}
PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
PRIVATE third_party/googletest/googletest/include
PRIVATE third_party/googletest/googletest
PRIVATE third_party/googletest/googlemock/include
PRIVATE third_party/googletest/googlemock
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(transport_connectivity_state_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr
${_gRPC_GFLAGS_LIBRARIES}
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)

@ -1,6 +1,8 @@
# How to contribute
We definitely welcome your patches and contributions to gRPC!
We definitely welcome your patches and contributions to gRPC! Please read the gRPC
organization's [governance rules](https://github.com/grpc/grpc-community/blob/master/governance.md)
and [contribution guidelines](https://github.com/grpc/grpc-community/blob/master/CONTRIBUTING.md) before proceeding.
If you are new to github, please start by reading [Pull Request
howto](https://help.github.com/articles/about-pull-requests/)

@ -0,0 +1 @@
This repository is governed by the gRPC organization's [governance rules](https://github.com/grpc/grpc-community/blob/master/governance.md).

@ -0,0 +1,82 @@
This page lists all active maintainers of this repository. If you were a
maintainer and would like to add your name to the Emeritus list, please send us a
PR.
See [GOVERNANCE.md](https://github.com/grpc/grpc-community/blob/master/governance.md)
for governance guidelines and how to become a maintainer.
See [CONTRIBUTING.md](https://github.com/grpc/grpc-community/blob/master/CONTRIBUTING.md)
for general contribution guidelines.
## Maintainers (in alphabetical order)
- [a11r](https://github.com/a11r), Google LLC
- [apolcyn](https://github.com/apolcyn), Google LLC
- [arjunroy](https://github.com/arjunroy), Google LLC
- [AspirinSJL](https://github.com/AspirinSJL), Google LLC
- [bogdandrutu](https://github.com/bogdandrutu), Google LLC
- [daniel-j-born](https://github.com/daniel-j-born), Google LLC
- [dapengzhang0](https://github.com/dapengzhang0), Google LLC
- [dfawley](https://github.com/dfawley), Google LLC
- [dklempner](https://github.com/dklempner), Google LLC
- [ejona86](https://github.com/ejona86), Google LLC
- [gnossen](https://github.com/gnossen), Google LLC
- [guantaol](https://github.com/guantaol), Google LLC
- [hcaseyal](https://github.com/hcaseyal), Google LLC
- [jboeuf](https://github.com/jboeuf), Google LLC
- [jiangtaoli2016](https://github.com/jiangtaoli2016), Google LLC
- [jkolhe](https://github.com/jkolhe), Google LLC
- [jtattermusch](https://github.com/jtattermusch), Google LLC
- [karthikravis](https://github.com/karthikravis), Google LLC
- [kumaralokgithub](https://github.com/kumaralokgithub), Google LLC
- [lidizheng](https://github.com/lidizheng), Google LLC
- [markdroth](https://github.com/markdroth), Google LLC
- [matthewstevenson88](https://github.com/matthewstevenson88), Google LLC
- [mehrdada](https://github.com/mehrdada), Dropbox, Inc.
- [mhaidrygoog](https://github.com/mhaidrygoog), Google LLC
- [murgatroid99](https://github.com/murgatroid99), Google LLC
- [muxi](https://github.com/muxi), Google LLC
- [nanahpang](https://github.com/nanahpang), Google LLC
- [nathanielmanistaatgoogle](https://github.com/nathanielmanistaatgoogle), Google LLC
- [nicolasnoble](https://github.com/nicolasnoble), Google LLC
- [qixuanl1](https://github.com/qixuanl1), Google LLC
- [ran-su](https://github.com/ran-su), Google LLC
- [rmstar](https://github.com/rmstar), Google LLC
- [sanjaypujare](https://github.com/sanjaypujare), Google LLC
- [sheenaqotj](https://github.com/sheenaqotj), Google LLC
- [soheilhy](https://github.com/soheilhy), Google LLC
- [sreecha](https://github.com/sreecha), LinkedIn
- [srini100](https://github.com/srini100), Google LLC
- [stanley-cheung](https://github.com/stanley-cheung), Google LLC
- [veblush](https://github.com/veblush), Google LLC
- [vishalpowar](https://github.com/vishalpowar), Google LLC
- [Vizerai](https://github.com/Vizerai), Google LLC
- [vjpai](https://github.com/vjpai), Google LLC
- [wcevans](https://github.com/wcevans), Google LLC
- [wenbozhu](https://github.com/wenbozhu), Google LLC
- [yang-g](https://github.com/yang-g), Google LLC
- [yashykt](https://github.com/yashykt), Google LLC
- [yihuazhang](https://github.com/yihuazhang), Google LLC
- [ZhouyihaiDing](https://github.com/ZhouyihaiDing), Google LLC
## Emeritus Maintainers (in alphabetical order)
- [adelez](https://github.com/adelez), Google LLC
- [billfeng327](https://github.com/billfeng327), Google LLC
- [ctiller](https://github.com/ctiller), Google LLC
- [dgquintas](https://github.com/dgquintas), Google LLC
- [ericgribkoff](https://github.com/ericgribkoff), Google LLC
- [fengli79](https://github.com/fengli79), Google LLC
- [jcanizales](https://github.com/jcanizales), Google LLC
- [jpalmerLinuxFoundation](https://github.com/jpalmerLinuxFoundation), Linux Foundation
- [justinburke](https://github.com/justinburke), Google LLC
- [kpayson64](https://github.com/kpayson64), Google LLC
- [lyuxuan](https://github.com/lyuxuan), Google LLC
- [matt-kwong](https://github.com/matt-kwong), Google LLC
- [mit-mit](https://github.com/mit-mit), Google LLC
- [mpwarres](https://github.com/mpwarres), Google LLC
- [ncteisen](https://github.com/ncteisen), Google LLC
- [pmarks-net](https://github.com/pmarks-net), Google LLC
- [slash-lib](https://github.com/slash-lib), Google LLC
- [soltanmm](https://github.com/soltanmm), Google LLC
- [summerxyt](https://github.com/summerxyt), Google LLC
- [y-zeng](https://github.com/y-zeng), Google LLC
- [zpencer](https://github.com/zpencer), Google LLC

@ -1137,7 +1137,6 @@ time_averaged_stats_test: $(BINDIR)/$(CONFIG)/time_averaged_stats_test
timeout_encoding_test: $(BINDIR)/$(CONFIG)/timeout_encoding_test
timer_heap_test: $(BINDIR)/$(CONFIG)/timer_heap_test
timer_list_test: $(BINDIR)/$(CONFIG)/timer_list_test
transport_connectivity_state_test: $(BINDIR)/$(CONFIG)/transport_connectivity_state_test
transport_metadata_test: $(BINDIR)/$(CONFIG)/transport_metadata_test
transport_security_test: $(BINDIR)/$(CONFIG)/transport_security_test
udp_server_test: $(BINDIR)/$(CONFIG)/udp_server_test
@ -1294,6 +1293,7 @@ thread_manager_test: $(BINDIR)/$(CONFIG)/thread_manager_test
thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test
time_change_test: $(BINDIR)/$(CONFIG)/time_change_test
timer_test: $(BINDIR)/$(CONFIG)/timer_test
transport_connectivity_state_test: $(BINDIR)/$(CONFIG)/transport_connectivity_state_test
transport_pid_controller_test: $(BINDIR)/$(CONFIG)/transport_pid_controller_test
transport_security_common_api_test: $(BINDIR)/$(CONFIG)/transport_security_common_api_test
writes_per_rpc_test: $(BINDIR)/$(CONFIG)/writes_per_rpc_test
@ -1563,7 +1563,6 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/timeout_encoding_test \
$(BINDIR)/$(CONFIG)/timer_heap_test \
$(BINDIR)/$(CONFIG)/timer_list_test \
$(BINDIR)/$(CONFIG)/transport_connectivity_state_test \
$(BINDIR)/$(CONFIG)/transport_metadata_test \
$(BINDIR)/$(CONFIG)/transport_security_test \
$(BINDIR)/$(CONFIG)/udp_server_test \
@ -1766,6 +1765,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/thread_stress_test \
$(BINDIR)/$(CONFIG)/time_change_test \
$(BINDIR)/$(CONFIG)/timer_test \
$(BINDIR)/$(CONFIG)/transport_connectivity_state_test \
$(BINDIR)/$(CONFIG)/transport_pid_controller_test \
$(BINDIR)/$(CONFIG)/transport_security_common_api_test \
$(BINDIR)/$(CONFIG)/writes_per_rpc_test \
@ -1936,6 +1936,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/thread_stress_test \
$(BINDIR)/$(CONFIG)/time_change_test \
$(BINDIR)/$(CONFIG)/timer_test \
$(BINDIR)/$(CONFIG)/transport_connectivity_state_test \
$(BINDIR)/$(CONFIG)/transport_pid_controller_test \
$(BINDIR)/$(CONFIG)/transport_security_common_api_test \
$(BINDIR)/$(CONFIG)/writes_per_rpc_test \
@ -2213,8 +2214,6 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/timer_heap_test || ( echo test timer_heap_test failed ; exit 1 )
$(E) "[RUN] Testing timer_list_test"
$(Q) $(BINDIR)/$(CONFIG)/timer_list_test || ( echo test timer_list_test failed ; exit 1 )
$(E) "[RUN] Testing transport_connectivity_state_test"
$(Q) $(BINDIR)/$(CONFIG)/transport_connectivity_state_test || ( echo test transport_connectivity_state_test failed ; exit 1 )
$(E) "[RUN] Testing transport_metadata_test"
$(Q) $(BINDIR)/$(CONFIG)/transport_metadata_test || ( echo test transport_metadata_test failed ; exit 1 )
$(E) "[RUN] Testing transport_security_test"
@ -2481,6 +2480,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/time_change_test || ( echo test time_change_test failed ; exit 1 )
$(E) "[RUN] Testing timer_test"
$(Q) $(BINDIR)/$(CONFIG)/timer_test || ( echo test timer_test failed ; exit 1 )
$(E) "[RUN] Testing transport_connectivity_state_test"
$(Q) $(BINDIR)/$(CONFIG)/transport_connectivity_state_test || ( echo test transport_connectivity_state_test failed ; exit 1 )
$(E) "[RUN] Testing transport_pid_controller_test"
$(Q) $(BINDIR)/$(CONFIG)/transport_pid_controller_test || ( echo test transport_pid_controller_test failed ; exit 1 )
$(E) "[RUN] Testing transport_security_common_api_test"
@ -13179,38 +13180,6 @@ endif
endif
TRANSPORT_CONNECTIVITY_STATE_TEST_SRC = \
test/core/transport/connectivity_state_test.cc \
TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_CONNECTIVITY_STATE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/transport_connectivity_state_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/transport_connectivity_state_test: $(TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/transport_connectivity_state_test
endif
$(OBJDIR)/$(CONFIG)/test/core/transport/connectivity_state_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_transport_connectivity_state_test: $(TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS:.o=.dep)
endif
endif
TRANSPORT_METADATA_TEST_SRC = \
test/core/transport/metadata_test.cc \
@ -19952,6 +19921,49 @@ endif
endif
TRANSPORT_CONNECTIVITY_STATE_TEST_SRC = \
test/core/transport/connectivity_state_test.cc \
TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_CONNECTIVITY_STATE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/transport_connectivity_state_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
$(BINDIR)/$(CONFIG)/transport_connectivity_state_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/transport_connectivity_state_test: $(PROTOBUF_DEP) $(TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/transport_connectivity_state_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/core/transport/connectivity_state_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_transport_connectivity_state_test: $(TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(TRANSPORT_CONNECTIVITY_STATE_TEST_OBJS:.o=.dep)
endif
endif
TRANSPORT_PID_CONTROLLER_TEST_SRC = \
test/core/transport/pid_controller_test.cc \

@ -3847,15 +3847,6 @@ targets:
exclude_iomgrs:
- uv
uses_polling: false
- name: transport_connectivity_state_test
build: test
language: c
src:
- test/core/transport/connectivity_state_test.cc
deps:
- grpc_test_util
- grpc
- gpr
- name: transport_metadata_test
build: test
language: c
@ -5989,6 +5980,16 @@ targets:
- grpc++
- grpc
- gpr
- name: transport_connectivity_state_test
gtest: true
build: test
language: c++
src:
- test/core/transport/connectivity_state_test.cc
deps:
- grpc_test_util
- grpc
- gpr
- name: transport_pid_controller_test
build: test
language: c++

@ -0,0 +1,8 @@
*.o
*.pb.cc
*.pb.h
greeter_client
greeter_server
greeter_async_client
greeter_async_client2
greeter_async_server

@ -339,6 +339,13 @@ typedef struct {
value is 15 minutes. */
#define GRPC_ARG_LOCALITY_RETENTION_INTERVAL_MS \
"grpc.xds_locality_retention_interval_ms"
/* Timeout in milliseconds to wait for the localities of a specific priority to
complete their initial connection attempt before xDS fails over to the next
priority. Specifically, the connection attempt of a priority is considered
completed when any locality of that priority is ready or all the localities
of that priority fail to connect. If 0, failover happens immediately. Default
value is 10 seconds. */
#define GRPC_ARG_XDS_FAILOVER_TIMEOUT_MS "grpc.xds_failover_timeout_ms"
/** If non-zero, grpc server's cronet compression workaround will be enabled */
#define GRPC_ARG_WORKAROUND_CRONET_COMPRESSION \
"grpc.workaround.cronet_compression"

@ -21,11 +21,6 @@
#define GRPC_OPEN_SOURCE_PROTO
#ifndef GRPC_CUSTOM_PROTOBUF_INT64
#include <google/protobuf/stubs/common.h>
#define GRPC_CUSTOM_PROTOBUF_INT64 ::google::protobuf::int64
#endif
#ifndef GRPC_CUSTOM_MESSAGE
#ifdef GRPC_USE_PROTO_LITE
#include <google/protobuf/message_lite.h>
@ -79,7 +74,6 @@ namespace protobuf {
typedef GRPC_CUSTOM_MESSAGE Message;
typedef GRPC_CUSTOM_MESSAGELITE MessageLite;
typedef GRPC_CUSTOM_PROTOBUF_INT64 int64;
typedef GRPC_CUSTOM_DESCRIPTOR Descriptor;
typedef GRPC_CUSTOM_DESCRIPTORPOOL DescriptorPool;

@ -121,9 +121,7 @@ class ProtoBufferReader : public ::grpc::protobuf::io::ZeroCopyInputStream {
}
/// Returns the total number of bytes read since this object was created.
grpc::protobuf::int64 ByteCount() const override {
return byte_count_ - backup_count_;
}
int64_t ByteCount() const override { return byte_count_ - backup_count_; }
// These protected members are needed to support internal optimizations.
// they expose internal bits of grpc core that are NOT stable. If you have

@ -138,7 +138,7 @@ class ProtoBufferWriter : public ::grpc::protobuf::io::ZeroCopyOutputStream {
}
/// Returns the total number of bytes written since this object was created.
grpc::protobuf::int64 ByteCount() const override { return byte_count_; }
int64_t ByteCount() const override { return byte_count_; }
// These protected members are needed to support internal optimizations.
// they expose internal bits of grpc core that are NOT stable. If you have

@ -266,12 +266,6 @@ class ServerInterface : public internal::CallHook {
server, context, stream, call_cq, notification_cq, tag,
registered_method->name(), registered_method->method_type()),
registered_method_(registered_method),
server_(server),
context_(context),
stream_(stream),
call_cq_(call_cq),
notification_cq_(notification_cq),
tag_(tag),
request_(request) {
IssueRequest(registered_method->server_tag(), payload_.bbuf_ptr(),
notification_cq);
@ -313,13 +307,6 @@ class ServerInterface : public internal::CallHook {
private:
internal::RpcServiceMethod* const registered_method_;
ServerInterface* const server_;
::grpc_impl::ServerContext* const context_;
internal::ServerAsyncStreamingInterface* const stream_;
::grpc_impl::CompletionQueue* const call_cq_;
::grpc_impl::ServerCompletionQueue* const notification_cq_;
void* const tag_;
Message* const request_;
ByteBuffer payload_;
};

@ -10,7 +10,7 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
<date>2018-01-19</date>
<date>2019-09-24</date>
<time>16:06:07</time>
<version>
<release>1.25.0dev</release>
@ -22,7 +22,7 @@
</stability>
<license>Apache 2.0</license>
<notes>
- TBD
- gRPC Core 1.25.0 update
</notes>
<contents>
<dir baseinstalldir="/" name="/">

@ -152,43 +152,41 @@ class ChannelData {
SubchannelInterface* subchannel) const;
grpc_connectivity_state CheckConnectivityState(bool try_to_connect);
void AddExternalConnectivityWatcher(grpc_polling_entity pollent,
grpc_connectivity_state* state,
grpc_closure* on_complete,
grpc_closure* watcher_timer_init) {
// Will delete itself.
New<ExternalConnectivityWatcher>(this, pollent, state, on_complete,
watcher_timer_init);
MutexLock lock(&external_watchers_mu_);
// Will be deleted when the watch is complete.
GPR_ASSERT(external_watchers_[on_complete] == nullptr);
external_watchers_[on_complete] = New<ExternalConnectivityWatcher>(
this, pollent, state, on_complete, watcher_timer_init);
}
void RemoveExternalConnectivityWatcher(grpc_closure* on_complete,
bool cancel) {
MutexLock lock(&external_watchers_mu_);
auto it = external_watchers_.find(on_complete);
if (it != external_watchers_.end()) {
if (cancel) it->second->Cancel();
external_watchers_.erase(it);
}
}
int NumExternalConnectivityWatchers() const {
return external_connectivity_watcher_list_.size();
MutexLock lock(&external_watchers_mu_);
return static_cast<int>(external_watchers_.size());
}
private:
class SubchannelWrapper;
class ClientChannelControlHelper;
class ExternalConnectivityWatcher {
// Represents a pending connectivity callback from an external caller
// via grpc_client_channel_watch_connectivity_state().
class ExternalConnectivityWatcher : public ConnectivityStateWatcherInterface {
public:
class WatcherList {
public:
WatcherList() { gpr_mu_init(&mu_); }
~WatcherList() { gpr_mu_destroy(&mu_); }
int size() const;
ExternalConnectivityWatcher* Lookup(grpc_closure* on_complete) const;
void Add(ExternalConnectivityWatcher* watcher);
void Remove(const ExternalConnectivityWatcher* watcher);
private:
// head_ is guarded by a mutex, since the size() method needs to
// iterate over the list, and it's called from the C-core API
// function grpc_channel_num_external_connectivity_watchers(), which
// is synchronous and therefore cannot run in the combiner.
mutable gpr_mu mu_;
ExternalConnectivityWatcher* head_ = nullptr;
};
ExternalConnectivityWatcher(ChannelData* chand, grpc_polling_entity pollent,
grpc_connectivity_state* state,
grpc_closure* on_complete,
@ -196,17 +194,23 @@ class ChannelData {
~ExternalConnectivityWatcher();
void Notify(grpc_connectivity_state state) override;
void Cancel();
private:
static void OnWatchCompleteLocked(void* arg, grpc_error* error);
static void WatchConnectivityStateLocked(void* arg, grpc_error* ignored);
static void AddWatcherLocked(void* arg, grpc_error* ignored);
static void RemoveWatcherLocked(void* arg, grpc_error* ignored);
ChannelData* chand_;
grpc_polling_entity pollent_;
grpc_connectivity_state initial_state_;
grpc_connectivity_state* state_;
grpc_closure* on_complete_;
grpc_closure* watcher_timer_init_;
grpc_closure my_closure_;
ExternalConnectivityWatcher* next_ = nullptr;
grpc_closure add_closure_;
grpc_closure remove_closure_;
Atomic<bool> done_{false};
};
ChannelData(grpc_channel_element_args* args, grpc_error** error);
@ -273,8 +277,7 @@ class ChannelData {
grpc_pollset_set* interested_parties_;
RefCountedPtr<SubchannelPoolInterface> subchannel_pool_;
OrphanablePtr<ResolvingLoadBalancingPolicy> resolving_lb_policy_;
grpc_connectivity_state_tracker state_tracker_;
ExternalConnectivityWatcher::WatcherList external_connectivity_watcher_list_;
ConnectivityStateTracker state_tracker_;
UniquePtr<char> health_check_service_name_;
RefCountedPtr<ServiceConfig> saved_service_config_;
bool received_first_resolver_result_ = false;
@ -305,6 +308,13 @@ class ChannelData {
gpr_mu info_mu_;
UniquePtr<char> info_lb_policy_name_;
UniquePtr<char> info_service_config_json_;
//
// Fields guarded by a mutex, since they need to be accessed
// synchronously via grpc_channel_num_external_connectivity_watchers().
//
mutable Mutex external_watchers_mu_;
Map<grpc_closure*, ExternalConnectivityWatcher*> external_watchers_;
};
//
@ -994,8 +1004,7 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
"subchannel %p (connected_subchannel=%p state=%s); "
"hopping into combiner",
parent_->chand_, parent_.get(), parent_->subchannel_,
connected_subchannel.get(),
grpc_connectivity_state_name(new_state));
connected_subchannel.get(), ConnectivityStateName(new_state));
}
// Will delete itself.
New<Updater>(Ref(), new_state, std::move(connected_subchannel));
@ -1044,7 +1053,7 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
self->parent_->parent_->chand_, self->parent_->parent_.get(),
self->parent_->parent_->subchannel_,
self->connected_subchannel_.get(),
grpc_connectivity_state_name(self->state_),
ConnectivityStateName(self->state_),
self->parent_->watcher_.get());
}
// Ignore update if the parent WatcherWrapper has been replaced
@ -1105,55 +1114,6 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface {
RefCountedPtr<ConnectedSubchannel> connected_subchannel_in_data_plane_;
};
//
// ChannelData::ExternalConnectivityWatcher::WatcherList
//
int ChannelData::ExternalConnectivityWatcher::WatcherList::size() const {
MutexLock lock(&mu_);
int count = 0;
for (ExternalConnectivityWatcher* w = head_; w != nullptr; w = w->next_) {
++count;
}
return count;
}
ChannelData::ExternalConnectivityWatcher*
ChannelData::ExternalConnectivityWatcher::WatcherList::Lookup(
grpc_closure* on_complete) const {
MutexLock lock(&mu_);
ExternalConnectivityWatcher* w = head_;
while (w != nullptr && w->on_complete_ != on_complete) {
w = w->next_;
}
return w;
}
void ChannelData::ExternalConnectivityWatcher::WatcherList::Add(
ExternalConnectivityWatcher* watcher) {
GPR_ASSERT(Lookup(watcher->on_complete_) == nullptr);
MutexLock lock(&mu_);
GPR_ASSERT(watcher->next_ == nullptr);
watcher->next_ = head_;
head_ = watcher;
}
void ChannelData::ExternalConnectivityWatcher::WatcherList::Remove(
const ExternalConnectivityWatcher* watcher) {
MutexLock lock(&mu_);
if (watcher == head_) {
head_ = watcher->next_;
return;
}
for (ExternalConnectivityWatcher* w = head_; w != nullptr; w = w->next_) {
if (w->next_ == watcher) {
w->next_ = w->next_->next_;
return;
}
}
GPR_UNREACHABLE_CODE(return );
}
//
// ChannelData::ExternalConnectivityWatcher
//
@ -1164,6 +1124,7 @@ ChannelData::ExternalConnectivityWatcher::ExternalConnectivityWatcher(
grpc_closure* watcher_timer_init)
: chand_(chand),
pollent_(pollent),
initial_state_(*state),
state_(state),
on_complete_(on_complete),
watcher_timer_init_(watcher_timer_init) {
@ -1171,7 +1132,7 @@ ChannelData::ExternalConnectivityWatcher::ExternalConnectivityWatcher(
chand_->interested_parties_);
GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "ExternalConnectivityWatcher");
GRPC_CLOSURE_SCHED(
GRPC_CLOSURE_INIT(&my_closure_, WatchConnectivityStateLocked, this,
GRPC_CLOSURE_INIT(&add_closure_, AddWatcherLocked, this,
grpc_combiner_scheduler(chand_->combiner_)),
GRPC_ERROR_NONE);
}
@ -1183,42 +1144,61 @@ ChannelData::ExternalConnectivityWatcher::~ExternalConnectivityWatcher() {
"ExternalConnectivityWatcher");
}
void ChannelData::ExternalConnectivityWatcher::OnWatchCompleteLocked(
void* arg, grpc_error* error) {
ExternalConnectivityWatcher* self =
static_cast<ExternalConnectivityWatcher*>(arg);
grpc_closure* on_complete = self->on_complete_;
self->chand_->external_connectivity_watcher_list_.Remove(self);
Delete(self);
GRPC_CLOSURE_SCHED(on_complete, GRPC_ERROR_REF(error));
void ChannelData::ExternalConnectivityWatcher::Notify(
grpc_connectivity_state state) {
bool done = false;
if (!done_.CompareExchangeStrong(&done, true, MemoryOrder::RELAXED,
MemoryOrder::RELAXED)) {
return; // Already done.
}
// Report new state to the user.
*state_ = state;
GRPC_CLOSURE_SCHED(on_complete_, GRPC_ERROR_NONE);
// Remove external watcher.
chand_->RemoveExternalConnectivityWatcher(on_complete_, /*cancel=*/false);
// Hop back into the combiner to clean up.
// Not needed in state SHUTDOWN, because the tracker will
// automatically remove all watchers in that case.
if (state != GRPC_CHANNEL_SHUTDOWN) {
GRPC_CLOSURE_SCHED(
GRPC_CLOSURE_INIT(&remove_closure_, RemoveWatcherLocked, this,
grpc_combiner_scheduler(chand_->combiner_)),
GRPC_ERROR_NONE);
}
}
void ChannelData::ExternalConnectivityWatcher::Cancel() {
bool done = false;
if (!done_.CompareExchangeStrong(&done, true, MemoryOrder::RELAXED,
MemoryOrder::RELAXED)) {
return; // Already done.
}
GRPC_CLOSURE_SCHED(on_complete_, GRPC_ERROR_CANCELLED);
// Hop back into the combiner to clean up.
GRPC_CLOSURE_SCHED(
GRPC_CLOSURE_INIT(&remove_closure_, RemoveWatcherLocked, this,
grpc_combiner_scheduler(chand_->combiner_)),
GRPC_ERROR_NONE);
}
void ChannelData::ExternalConnectivityWatcher::WatchConnectivityStateLocked(
void ChannelData::ExternalConnectivityWatcher::AddWatcherLocked(
void* arg, grpc_error* ignored) {
ExternalConnectivityWatcher* self =
static_cast<ExternalConnectivityWatcher*>(arg);
if (self->state_ == nullptr) {
// Handle cancellation.
GPR_ASSERT(self->watcher_timer_init_ == nullptr);
ExternalConnectivityWatcher* found =
self->chand_->external_connectivity_watcher_list_.Lookup(
self->on_complete_);
if (found != nullptr) {
grpc_connectivity_state_notify_on_state_change(
&found->chand_->state_tracker_, nullptr, &found->my_closure_);
}
Delete(self);
return;
}
// New watcher.
self->chand_->external_connectivity_watcher_list_.Add(self);
// This assumes that the closure is scheduled on the ExecCtx scheduler
// and that GRPC_CLOSURE_RUN would run the closure immediately.
// and that GRPC_CLOSURE_RUN() will run the closure immediately.
GRPC_CLOSURE_RUN(self->watcher_timer_init_, GRPC_ERROR_NONE);
GRPC_CLOSURE_INIT(&self->my_closure_, OnWatchCompleteLocked, self,
grpc_combiner_scheduler(self->chand_->combiner_));
grpc_connectivity_state_notify_on_state_change(
&self->chand_->state_tracker_, self->state_, &self->my_closure_);
// Add new watcher.
self->chand_->state_tracker_.AddWatcher(
self->initial_state_,
OrphanablePtr<ConnectivityStateWatcherInterface>(self));
}
void ChannelData::ExternalConnectivityWatcher::RemoveWatcherLocked(
void* arg, grpc_error* ignored) {
ExternalConnectivityWatcher* self =
static_cast<ExternalConnectivityWatcher*>(arg);
self->chand_->state_tracker_.RemoveWatcher(self);
}
//
@ -1271,7 +1251,7 @@ class ChannelData::ClientChannelControlHelper
? ""
: " (ignoring -- channel shutting down)";
gpr_log(GPR_INFO, "chand=%p: update: state=%s picker=%p%s", chand_,
grpc_connectivity_state_name(state), picker.get(), extra);
ConnectivityStateName(state), picker.get(), extra);
}
// Do update only if not shutting down.
if (disconnect_error == GRPC_ERROR_NONE) {
@ -1362,14 +1342,13 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error)
combiner_(grpc_combiner_create()),
interested_parties_(grpc_pollset_set_create()),
subchannel_pool_(GetSubchannelPool(args->channel_args)),
state_tracker_("client_channel", GRPC_CHANNEL_IDLE),
disconnect_error_(GRPC_ERROR_NONE) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) {
gpr_log(GPR_INFO, "chand=%p: creating client_channel for channel stack %p",
this, owning_stack_);
}
// Initialize data members.
grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE,
"client_channel");
gpr_mu_init(&info_mu_);
// Start backup polling.
grpc_client_channel_start_backup_polling(interested_parties_);
@ -1433,7 +1412,6 @@ ChannelData::~ChannelData() {
grpc_pollset_set_destroy(interested_parties_);
GRPC_COMBINER_UNREF(combiner_, "client_channel");
GRPC_ERROR_UNREF(disconnect_error_.Load(MemoryOrder::RELAXED));
grpc_connectivity_state_destroy(&state_tracker_);
gpr_mu_destroy(&info_mu_);
}
@ -1447,7 +1425,7 @@ void ChannelData::UpdateStateAndPickerLocked(
received_first_resolver_result_ = false;
}
// Update connectivity state.
grpc_connectivity_state_set(&state_tracker_, state, reason);
state_tracker_.SetState(state, reason);
if (channelz_node_ != nullptr) {
channelz_node_->SetConnectivityState(state);
channelz_node_->AddTraceEvent(
@ -1736,7 +1714,7 @@ bool ChannelData::ProcessResolverResultLocked(
}
grpc_error* ChannelData::DoPingLocked(grpc_transport_op* op) {
if (grpc_connectivity_state_check(&state_tracker_) != GRPC_CHANNEL_READY) {
if (state_tracker_.state() != GRPC_CHANNEL_READY) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("channel not connected");
}
LoadBalancingPolicy::PickResult result =
@ -1764,12 +1742,12 @@ void ChannelData::StartTransportOpLocked(void* arg, grpc_error* ignored) {
static_cast<grpc_channel_element*>(op->handler_private.extra_arg);
ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
// Connectivity watch.
if (op->on_connectivity_state_change != nullptr) {
grpc_connectivity_state_notify_on_state_change(
&chand->state_tracker_, op->connectivity_state,
op->on_connectivity_state_change);
op->on_connectivity_state_change = nullptr;
op->connectivity_state = nullptr;
if (op->start_connectivity_watch != nullptr) {
chand->state_tracker_.AddWatcher(op->start_connectivity_watch_state,
std::move(op->start_connectivity_watch));
}
if (op->stop_connectivity_watch != nullptr) {
chand->state_tracker_.RemoveWatcher(op->stop_connectivity_watch);
}
// Ping.
if (op->send_ping.on_initiate != nullptr || op->send_ping.on_ack != nullptr) {
@ -1900,7 +1878,7 @@ void ChannelData::TryToConnectLocked(void* arg, grpc_error* error_ignored) {
grpc_connectivity_state ChannelData::CheckConnectivityState(
bool try_to_connect) {
grpc_connectivity_state out = grpc_connectivity_state_check(&state_tracker_);
grpc_connectivity_state out = state_tracker_.state();
if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
GRPC_CHANNEL_STACK_REF(owning_stack_, "TryToConnect");
GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(TryToConnectLocked, this,
@ -3950,6 +3928,13 @@ void grpc_client_channel_watch_connectivity_state(
grpc_connectivity_state* state, grpc_closure* closure,
grpc_closure* watcher_timer_init) {
auto* chand = static_cast<ChannelData*>(elem->channel_data);
if (state == nullptr) {
// Handle cancellation.
GPR_ASSERT(watcher_timer_init == nullptr);
chand->RemoveExternalConnectivityWatcher(closure, /*cancel=*/true);
return;
}
// Handle addition.
return chand->AddExternalConnectivityWatcher(pollent, state, closure,
watcher_timer_init);
}

@ -46,6 +46,12 @@ grpc_connectivity_state grpc_client_channel_check_connectivity_state(
int grpc_client_channel_num_external_connectivity_watchers(
grpc_channel_element* elem);
// TODO(roth): This function is used both when handling external
// connectivity watchers and for LB policies like grpclb and xds that
// contain nested channels. In the latter case, we ideally want
// something closer to the normal connectivity state tracker API.
// When we have time, consider refactoring this somehow to allow each
// use-case to be handled more cleanly.
void grpc_client_channel_watch_connectivity_state(
grpc_channel_element* elem, grpc_polling_entity pollent,
grpc_connectivity_state* state, grpc_closure* on_complete,

@ -53,9 +53,8 @@ void SubchannelNode::PopulateConnectivityState(grpc_json* json) {
connectivity_state_.Load(MemoryOrder::RELAXED);
json = grpc_json_create_child(nullptr, json, "state", nullptr,
GRPC_JSON_OBJECT, false);
grpc_json_create_child(nullptr, json, "state",
grpc_connectivity_state_name(state), GRPC_JSON_STRING,
false);
grpc_json_create_child(nullptr, json, "state", ConnectivityStateName(state),
GRPC_JSON_STRING, false);
}
grpc_json* SubchannelNode::RenderJson() {

@ -660,7 +660,7 @@ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
gpr_log(GPR_INFO,
"[grpclb %p helper %p] pending child policy %p reports state=%s",
parent_.get(), this, parent_->pending_child_policy_.get(),
grpc_connectivity_state_name(state));
ConnectivityStateName(state));
}
if (state != GRPC_CHANNEL_READY) return;
grpc_pollset_set_del_pollset_set(
@ -700,8 +700,7 @@ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
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, grpc_connectivity_state_name(state),
picker.get());
parent_.get(), this, ConnectivityStateName(state), picker.get());
}
parent_->channel_control_helper()->UpdateState(state, std::move(picker));
return;
@ -709,8 +708,7 @@ void GrpcLb::Helper::UpdateState(grpc_connectivity_state state,
// 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, grpc_connectivity_state_name(state),
picker.get());
parent_.get(), this, ConnectivityStateName(state), picker.get());
}
RefCountedPtr<GrpcLbClientStats> client_stats;
if (parent_->lb_calld_ != nullptr &&

@ -294,7 +294,7 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) {
gpr_log(GPR_INFO,
"Pick First %p selected subchannel connectivity changed to %s", p,
grpc_connectivity_state_name(connectivity_state));
ConnectivityStateName(connectivity_state));
}
// If the new state is anything other than READY and there is a
// pending update, switch to the pending update.

@ -379,8 +379,8 @@ void RoundRobin::RoundRobinSubchannelData::UpdateConnectivityStateLocked(
"(index %" PRIuPTR " of %" PRIuPTR "): prev_state=%s new_state=%s",
p, subchannel(), subchannel_list(), Index(),
subchannel_list()->num_subchannels(),
grpc_connectivity_state_name(last_connectivity_state_),
grpc_connectivity_state_name(connectivity_state));
ConnectivityStateName(last_connectivity_state_),
ConnectivityStateName(connectivity_state));
}
// Decide what state to report for aggregation purposes.
// If we haven't seen a failure since the last time we were in state

@ -254,8 +254,7 @@ void SubchannelData<SubchannelListType, SubchannelDataType>::Watcher::
subchannel_list_.get(), subchannel_data_->Index(),
subchannel_list_->num_subchannels(),
subchannel_data_->subchannel_.get(),
grpc_connectivity_state_name(new_state),
subchannel_list_->shutting_down(),
ConnectivityStateName(new_state), subchannel_list_->shutting_down(),
subchannel_data_->pending_watcher_);
}
if (!subchannel_list_->shutting_down() &&
@ -318,8 +317,7 @@ void SubchannelData<SubchannelListType,
" (subchannel %p): starting watch (from %s)",
subchannel_list_->tracer()->name(), subchannel_list_->policy(),
subchannel_list_, Index(), subchannel_list_->num_subchannels(),
subchannel_.get(),
grpc_connectivity_state_name(connectivity_state_));
subchannel_.get(), ConnectivityStateName(connectivity_state_));
}
GPR_ASSERT(pending_watcher_ == nullptr);
pending_watcher_ =

File diff suppressed because it is too large Load Diff

@ -53,6 +53,42 @@ constexpr char kEndpointRequired[] = "endpointRequired";
} // namespace
bool XdsPriorityListUpdate::operator==(
const XdsPriorityListUpdate& other) const {
if (priorities_.size() != other.priorities_.size()) return false;
for (size_t i = 0; i < priorities_.size(); ++i) {
if (priorities_[i].localities != other.priorities_[i].localities) {
return false;
}
}
return true;
}
void XdsPriorityListUpdate::Add(
XdsPriorityListUpdate::LocalityMap::Locality locality) {
// Pad the missing priorities in case the localities are not ordered by
// priority.
// TODO(juanlishen): Implement InlinedVector::resize() and use that instead.
while (!Contains(locality.priority)) priorities_.emplace_back();
LocalityMap& locality_map = priorities_[locality.priority];
locality_map.localities.emplace(locality.name, std::move(locality));
}
const XdsPriorityListUpdate::LocalityMap* XdsPriorityListUpdate::Find(
uint32_t priority) const {
if (!Contains(priority)) return nullptr;
return &priorities_[priority];
}
bool XdsPriorityListUpdate::Contains(
const RefCountedPtr<XdsLocalityName>& name) {
for (size_t i = 0; i < priorities_.size(); ++i) {
const LocalityMap& locality_map = priorities_[i];
if (locality_map.Contains(name)) return true;
}
return false;
}
bool XdsDropConfig::ShouldDrop(const UniquePtr<char>** category_name) const {
for (size_t i = 0; i < drop_category_list_.size(); ++i) {
const auto& drop_category = drop_category_list_[i];
@ -66,7 +102,7 @@ bool XdsDropConfig::ShouldDrop(const UniquePtr<char>** category_name) const {
return false;
}
grpc_slice XdsEdsRequestCreateAndEncode(const char* service_name) {
grpc_slice XdsEdsRequestCreateAndEncode(const char* server_name) {
upb::Arena arena;
// Create a request.
envoy_api_v2_DiscoveryRequest* request =
@ -83,7 +119,7 @@ grpc_slice XdsEdsRequestCreateAndEncode(const char* service_name) {
google_protobuf_Struct_FieldsEntry_mutable_value(field, arena.ptr());
google_protobuf_Value_set_bool_value(value, true);
envoy_api_v2_DiscoveryRequest_add_resource_names(
request, upb_strview_makez(service_name), arena.ptr());
request, upb_strview_makez(server_name), arena.ptr());
envoy_api_v2_DiscoveryRequest_set_type_url(request,
upb_strview_makez(kEdsTypeUrl));
// Encode the request.
@ -136,7 +172,7 @@ UniquePtr<char> StringCopy(const upb_strview& strview) {
grpc_error* LocalityParse(
const envoy_api_v2_endpoint_LocalityLbEndpoints* locality_lb_endpoints,
XdsLocalityInfo* locality_info) {
XdsPriorityListUpdate::LocalityMap::Locality* output_locality) {
// Parse LB weight.
const google_protobuf_UInt32Value* lb_weight =
envoy_api_v2_endpoint_LocalityLbEndpoints_load_balancing_weight(
@ -144,13 +180,13 @@ grpc_error* LocalityParse(
// If LB weight is not specified, it means this locality is assigned no load.
// TODO(juanlishen): When we support CDS to configure the inter-locality
// policy, we should change the LB weight handling.
locality_info->lb_weight =
output_locality->lb_weight =
lb_weight != nullptr ? google_protobuf_UInt32Value_value(lb_weight) : 0;
if (locality_info->lb_weight == 0) return GRPC_ERROR_NONE;
if (output_locality->lb_weight == 0) return GRPC_ERROR_NONE;
// Parse locality name.
const envoy_api_v2_core_Locality* locality =
envoy_api_v2_endpoint_LocalityLbEndpoints_locality(locality_lb_endpoints);
locality_info->locality_name = MakeRefCounted<XdsLocalityName>(
output_locality->name = MakeRefCounted<XdsLocalityName>(
StringCopy(envoy_api_v2_core_Locality_region(locality)),
StringCopy(envoy_api_v2_core_Locality_zone(locality)),
StringCopy(envoy_api_v2_core_Locality_sub_zone(locality)));
@ -160,12 +196,12 @@ grpc_error* LocalityParse(
envoy_api_v2_endpoint_LocalityLbEndpoints_lb_endpoints(
locality_lb_endpoints, &size);
for (size_t i = 0; i < size; ++i) {
grpc_error* error = ServerAddressParseAndAppend(lb_endpoints[i],
&locality_info->serverlist);
grpc_error* error = ServerAddressParseAndAppend(
lb_endpoints[i], &output_locality->serverlist);
if (error != GRPC_ERROR_NONE) return error;
}
// Parse the priority.
locality_info->priority =
output_locality->priority =
envoy_api_v2_endpoint_LocalityLbEndpoints_priority(locality_lb_endpoints);
return GRPC_ERROR_NONE;
}
@ -253,18 +289,13 @@ grpc_error* XdsEdsResponseDecodeAndParse(const grpc_slice& encoded_response,
envoy_api_v2_ClusterLoadAssignment_endpoints(cluster_load_assignment,
&size);
for (size_t i = 0; i < size; ++i) {
XdsLocalityInfo locality_info;
grpc_error* error = LocalityParse(endpoints[i], &locality_info);
XdsPriorityListUpdate::LocalityMap::Locality locality;
grpc_error* error = LocalityParse(endpoints[i], &locality);
if (error != GRPC_ERROR_NONE) return error;
// Filter out locality with weight 0.
if (locality_info.lb_weight == 0) continue;
update->locality_list.push_back(std::move(locality_info));
if (locality.lb_weight == 0) continue;
update->priority_list_update.Add(locality);
}
// The locality list is sorted here into deterministic order so that it's
// easier to check if two locality lists contain the same set of localities.
std::sort(update->locality_list.data(),
update->locality_list.data() + update->locality_list.size(),
XdsLocalityInfo::Less());
// Get the drop config.
update->drop_config = MakeRefCounted<XdsDropConfig>();
const envoy_api_v2_ClusterLoadAssignment_Policy* policy =
@ -414,8 +445,8 @@ grpc_slice XdsLrsRequestCreateAndEncode(const char* server_name,
}
grpc_error* XdsLrsResponseDecodeAndParse(const grpc_slice& encoded_response,
grpc_millis* load_reporting_interval,
const char* expected_server_name) {
UniquePtr<char>* cluster_name,
grpc_millis* load_reporting_interval) {
upb::Arena arena;
// Decode the response.
const envoy_service_load_stats_v2_LoadStatsResponse* decoded_response =
@ -435,11 +466,8 @@ grpc_error* XdsLrsResponseDecodeAndParse(const grpc_slice& encoded_response,
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"The number of clusters (server names) is not 1.");
}
// Check the cluster name in the response
if (strncmp(expected_server_name, clusters[0].data, clusters[0].size) != 0) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Unexpected cluster (server name).");
}
// Get the cluster name for reporting loads.
*cluster_name = StringCopy(clusters[0]);
// Get the load report interval.
const google_protobuf_Duration* load_reporting_interval_duration =
envoy_service_load_stats_v2_LoadStatsResponse_load_reporting_interval(

@ -23,33 +23,66 @@
#include <grpc/slice_buffer.h>
#include <stdint.h>
#include "src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h"
#include "src/core/ext/filters/client_channel/server_address.h"
namespace grpc_core {
struct XdsLocalityInfo {
bool operator==(const XdsLocalityInfo& other) const {
return *locality_name == *other.locality_name &&
serverlist == other.serverlist && lb_weight == other.lb_weight &&
priority == other.priority;
}
// This comparator only compares the locality names.
struct Less {
bool operator()(const XdsLocalityInfo& lhs,
const XdsLocalityInfo& rhs) const {
return XdsLocalityName::Less()(lhs.locality_name, rhs.locality_name);
class XdsPriorityListUpdate {
public:
struct LocalityMap {
struct Locality {
bool operator==(const Locality& other) const {
return *name == *other.name && serverlist == other.serverlist &&
lb_weight == other.lb_weight && priority == other.priority;
}
// This comparator only compares the locality names.
struct Less {
bool operator()(const Locality& lhs, const Locality& rhs) const {
return XdsLocalityName::Less()(lhs.name, rhs.name);
}
};
RefCountedPtr<XdsLocalityName> name;
ServerAddressList serverlist;
uint32_t lb_weight;
uint32_t priority;
};
bool Contains(const RefCountedPtr<XdsLocalityName>& name) const {
return localities.find(name) != localities.end();
}
size_t size() const { return localities.size(); }
Map<RefCountedPtr<XdsLocalityName>, Locality, XdsLocalityName::Less>
localities;
};
RefCountedPtr<XdsLocalityName> locality_name;
ServerAddressList serverlist;
uint32_t lb_weight;
uint32_t priority;
};
bool operator==(const XdsPriorityListUpdate& other) const;
void Add(LocalityMap::Locality locality);
const LocalityMap* Find(uint32_t priority) const;
using XdsLocalityList = InlinedVector<XdsLocalityInfo, 1>;
bool Contains(uint32_t priority) const {
return priority < priorities_.size();
}
bool Contains(const RefCountedPtr<XdsLocalityName>& name);
bool empty() const { return priorities_.empty(); }
size_t size() const { return priorities_.size(); }
// Callers should make sure the priority list is non-empty.
uint32_t LowestPriority() const {
return static_cast<uint32_t>(priorities_.size()) - 1;
}
private:
InlinedVector<LocalityMap, 2> priorities_;
};
// There are two phases of accessing this class's content:
// 1. to initialize in the control plane combiner;
@ -93,13 +126,13 @@ class XdsDropConfig : public RefCounted<XdsDropConfig> {
};
struct XdsUpdate {
XdsLocalityList locality_list;
XdsPriorityListUpdate priority_list_update;
RefCountedPtr<XdsDropConfig> drop_config;
bool drop_all = false;
};
// Creates an EDS request querying \a service_name.
grpc_slice XdsEdsRequestCreateAndEncode(const char* service_name);
grpc_slice XdsEdsRequestCreateAndEncode(const char* server_name);
// Parses the EDS response and returns the args to update locality map. If there
// is any error, the output update is invalid.
@ -114,12 +147,12 @@ grpc_slice XdsLrsRequestCreateAndEncode(const char* server_name);
grpc_slice XdsLrsRequestCreateAndEncode(const char* server_name,
XdsClientStats* client_stats);
// Parses the LRS response and returns the client-side load reporting interval.
// If there is any error (e.g., the found server name doesn't match \a
// expected_server_name), the output config is invalid.
// Parses the LRS response and returns \a cluster_name and \a
// load_reporting_interval for client-side load reporting. If there is any
// error, the output config is invalid.
grpc_error* XdsLrsResponseDecodeAndParse(const grpc_slice& encoded_response,
grpc_millis* load_reporting_interval,
const char* expected_server_name);
UniquePtr<char>* cluster_name,
grpc_millis* load_reporting_interval);
} // namespace grpc_core

@ -123,8 +123,7 @@ class ResolvingLoadBalancingPolicy::ResolvingControlHelper
gpr_log(GPR_INFO,
"resolving_lb=%p helper=%p: pending child policy %p reports "
"state=%s",
parent_.get(), this, child_,
grpc_connectivity_state_name(state));
parent_.get(), this, child_, ConnectivityStateName(state));
}
if (state != GRPC_CHANNEL_READY) return;
grpc_pollset_set_del_pollset_set(

@ -95,15 +95,14 @@ ConnectedSubchannel::~ConnectedSubchannel() {
GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor");
}
void ConnectedSubchannel::NotifyOnStateChange(
grpc_pollset_set* interested_parties, grpc_connectivity_state* state,
grpc_closure* closure) {
void ConnectedSubchannel::StartWatch(
grpc_pollset_set* interested_parties,
OrphanablePtr<ConnectivityStateWatcherInterface> watcher) {
grpc_transport_op* op = grpc_make_transport_op(nullptr);
grpc_channel_element* elem;
op->connectivity_state = state;
op->on_connectivity_state_change = closure;
op->start_connectivity_watch = std::move(watcher);
op->start_connectivity_watch_state = GRPC_CHANNEL_READY;
op->bind_pollset_set = interested_parties;
elem = grpc_channel_stack_element(channel_stack_, 0);
grpc_channel_element* elem = grpc_channel_stack_element(channel_stack_, 0);
elem->filter->start_transport_op(elem, op);
}
@ -310,19 +309,14 @@ void SubchannelCall::IncrementRefCount(const grpc_core::DebugLocation& location,
// Subchannel::ConnectedSubchannelStateWatcher
//
class Subchannel::ConnectedSubchannelStateWatcher {
class Subchannel::ConnectedSubchannelStateWatcher
: public AsyncConnectivityStateWatcherInterface {
public:
// Must be instantiated while holding c->mu.
explicit ConnectedSubchannelStateWatcher(Subchannel* c) : subchannel_(c) {
// Steal subchannel ref for connecting.
GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "state_watcher");
GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "connecting");
// Start watching for connectivity state changes.
GRPC_CLOSURE_INIT(&on_connectivity_changed_, OnConnectivityChanged, this,
grpc_schedule_on_exec_ctx);
c->connected_subchannel_->NotifyOnStateChange(c->pollset_set_,
&pending_connectivity_state_,
&on_connectivity_changed_);
}
~ConnectedSubchannelStateWatcher() {
@ -330,54 +324,41 @@ class Subchannel::ConnectedSubchannelStateWatcher {
}
private:
static void OnConnectivityChanged(void* arg, grpc_error* error) {
auto* self = static_cast<ConnectedSubchannelStateWatcher*>(arg);
Subchannel* c = self->subchannel_;
{
MutexLock lock(&c->mu_);
switch (self->pending_connectivity_state_) {
case GRPC_CHANNEL_TRANSIENT_FAILURE:
case GRPC_CHANNEL_SHUTDOWN: {
if (!c->disconnected_ && c->connected_subchannel_ != nullptr) {
if (grpc_trace_subchannel.enabled()) {
gpr_log(GPR_INFO,
"Connected subchannel %p of subchannel %p has gone into "
"%s. Attempting to reconnect.",
c->connected_subchannel_.get(), c,
grpc_connectivity_state_name(
self->pending_connectivity_state_));
}
c->connected_subchannel_.reset();
if (c->channelz_node() != nullptr) {
c->channelz_node()->SetChildSocket(nullptr);
}
c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE);
c->backoff_begun_ = false;
c->backoff_.Reset();
void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
Subchannel* c = subchannel_;
MutexLock lock(&c->mu_);
switch (new_state) {
case GRPC_CHANNEL_TRANSIENT_FAILURE:
case GRPC_CHANNEL_SHUTDOWN: {
if (!c->disconnected_ && c->connected_subchannel_ != nullptr) {
if (grpc_trace_subchannel.enabled()) {
gpr_log(GPR_INFO,
"Connected subchannel %p of subchannel %p has gone into "
"%s. Attempting to reconnect.",
c->connected_subchannel_.get(), c,
ConnectivityStateName(new_state));
}
break;
}
default: {
// In principle, this should never happen. We should not get
// 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(self->pending_connectivity_state_);
c->connected_subchannel_->NotifyOnStateChange(
nullptr, &self->pending_connectivity_state_,
&self->on_connectivity_changed_);
return; // So we don't delete ourself below.
c->connected_subchannel_.reset();
if (c->channelz_node() != nullptr) {
c->channelz_node()->SetChildSocket(nullptr);
}
c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE);
c->backoff_begun_ = false;
c->backoff_.Reset();
}
break;
}
default: {
// In principle, this should never happen. We should not get
// 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);
}
}
// Don't delete until we've released the lock, because this might
// cause the subchannel (which contains the lock) to be destroyed.
Delete(self);
}
Subchannel* subchannel_;
grpc_closure on_connectivity_changed_;
grpc_connectivity_state pending_connectivity_state_ = GRPC_CHANNEL_READY;
};
//
@ -1088,8 +1069,10 @@ bool Subchannel::PublishTransportLocked() {
if (channelz_node_ != nullptr) {
channelz_node_->SetChildSocket(std::move(socket));
}
// Instantiate state watcher. Will clean itself up.
New<ConnectedSubchannelStateWatcher>(this);
// Start watching connected subchannel.
connected_subchannel_->StartWatch(
pollset_set_, OrphanablePtr<grpc_core::ConnectivityStateWatcherInterface>(
New<ConnectedSubchannelStateWatcher>(this)));
// Report initial state.
SetConnectivityStateLocked(GRPC_CHANNEL_READY);
return true;

@ -77,9 +77,9 @@ class ConnectedSubchannel : public RefCounted<ConnectedSubchannel> {
RefCountedPtr<channelz::SubchannelNode> channelz_subchannel);
~ConnectedSubchannel();
void NotifyOnStateChange(grpc_pollset_set* interested_parties,
grpc_connectivity_state* state,
grpc_closure* closure);
void StartWatch(grpc_pollset_set* interested_parties,
OrphanablePtr<ConnectivityStateWatcherInterface> watcher);
void Ping(grpc_closure* on_initiate, grpc_closure* on_ack);
grpc_channel_stack* channel_stack() const { return channel_stack_; }

@ -29,6 +29,9 @@
#include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/transport/http2_errors.h"
/* If these settings change, make sure that we are not sending a GOAWAY for
* inproc transport, since a GOAWAY to inproc ends up destroying the transport.
*/
#define DEFAULT_MAX_CONNECTION_AGE_MS INT_MAX
#define DEFAULT_MAX_CONNECTION_AGE_GRACE_MS INT_MAX
#define DEFAULT_MAX_CONNECTION_IDLE_MS INT_MAX
@ -87,10 +90,6 @@ struct channel_data {
grpc_closure start_max_age_timer_after_init;
/* Closure to run when the goaway op is finished and the max_age_timer */
grpc_closure start_max_age_grace_timer_after_goaway_op;
/* Closure to run when the channel connectivity state changes */
grpc_closure channel_connectivity_changed;
/* Records the current connectivity state */
grpc_connectivity_state connectivity_state;
/* Number of active calls */
gpr_atm call_count;
/* TODO(zyc): C++lize this state machine */
@ -217,6 +216,47 @@ static void start_max_idle_timer_after_init(void* arg, grpc_error* error) {
"max_age start_max_idle_timer_after_init");
}
namespace grpc_core {
class ConnectivityWatcher : public AsyncConnectivityStateWatcherInterface {
public:
explicit ConnectivityWatcher(channel_data* chand) : chand_(chand) {
GRPC_CHANNEL_STACK_REF(chand_->channel_stack, "max_age conn_watch");
}
~ConnectivityWatcher() {
GRPC_CHANNEL_STACK_UNREF(chand_->channel_stack, "max_age conn_watch");
}
private:
void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
if (new_state != GRPC_CHANNEL_SHUTDOWN) return;
{
MutexLock lock(&chand_->max_age_timer_mu);
if (chand_->max_age_timer_pending) {
grpc_timer_cancel(&chand_->max_age_timer);
chand_->max_age_timer_pending = false;
}
if (chand_->max_age_grace_timer_pending) {
grpc_timer_cancel(&chand_->max_age_grace_timer);
chand_->max_age_grace_timer_pending = false;
}
}
/* If there are no active calls, this increasement will cancel
max_idle_timer, and prevent max_idle_timer from being started in the
future. */
increase_call_count(chand_);
if (gpr_atm_acq_load(&chand_->idle_state) ==
MAX_IDLE_STATE_SEEN_EXIT_IDLE) {
grpc_timer_cancel(&chand_->max_idle_timer);
}
}
channel_data* chand_;
};
} // namespace grpc_core
static void start_max_age_timer_after_init(void* arg, grpc_error* error) {
channel_data* chand = static_cast<channel_data*>(arg);
gpr_mu_lock(&chand->max_age_timer_mu);
@ -227,8 +267,9 @@ static void start_max_age_timer_after_init(void* arg, grpc_error* error) {
&chand->close_max_age_channel);
gpr_mu_unlock(&chand->max_age_timer_mu);
grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->on_connectivity_state_change = &chand->channel_connectivity_changed;
op->connectivity_state = &chand->connectivity_state;
op->start_connectivity_watch.reset(
grpc_core::New<grpc_core::ConnectivityWatcher>(chand));
op->start_connectivity_watch_state = GRPC_CHANNEL_IDLE;
grpc_channel_next_op(grpc_channel_stack_element(chand->channel_stack, 0), op);
GRPC_CHANNEL_STACK_UNREF(chand->channel_stack,
"max_age start_max_age_timer_after_init");
@ -347,35 +388,6 @@ static void force_close_max_age_channel(void* arg, grpc_error* error) {
GRPC_CHANNEL_STACK_UNREF(chand->channel_stack, "max_age max_age_grace_timer");
}
static void channel_connectivity_changed(void* arg, grpc_error* error) {
channel_data* chand = static_cast<channel_data*>(arg);
if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->on_connectivity_state_change = &chand->channel_connectivity_changed;
op->connectivity_state = &chand->connectivity_state;
grpc_channel_next_op(grpc_channel_stack_element(chand->channel_stack, 0),
op);
} else {
gpr_mu_lock(&chand->max_age_timer_mu);
if (chand->max_age_timer_pending) {
grpc_timer_cancel(&chand->max_age_timer);
chand->max_age_timer_pending = false;
}
if (chand->max_age_grace_timer_pending) {
grpc_timer_cancel(&chand->max_age_grace_timer);
chand->max_age_grace_timer_pending = false;
}
gpr_mu_unlock(&chand->max_age_timer_mu);
/* If there are no active calls, this increasement will cancel
max_idle_timer, and prevent max_idle_timer from being started in the
future. */
increase_call_count(chand);
if (gpr_atm_acq_load(&chand->idle_state) == MAX_IDLE_STATE_SEEN_EXIT_IDLE) {
grpc_timer_cancel(&chand->max_idle_timer);
}
}
}
/* A random jitter of +/-10% will be added to MAX_CONNECTION_AGE to spread out
connection storms. Note that the MAX_CONNECTION_AGE option without jitter
would not create connection storms by itself, but if there happened to be a
@ -469,9 +481,6 @@ static grpc_error* max_age_init_channel_elem(grpc_channel_element* elem,
GRPC_CLOSURE_INIT(&chand->start_max_age_grace_timer_after_goaway_op,
start_max_age_grace_timer_after_goaway_op, chand,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&chand->channel_connectivity_changed,
channel_connectivity_changed, chand,
grpc_schedule_on_exec_ctx);
if (chand->max_connection_age != GRPC_MILLIS_INF_FUTURE) {
/* When the channel reaches its max age, we send down an op with

@ -196,7 +196,6 @@ grpc_chttp2_transport::~grpc_chttp2_transport() {
GPR_ASSERT(grpc_chttp2_stream_map_size(&stream_map) == 0);
grpc_chttp2_stream_map_destroy(&stream_map);
grpc_connectivity_state_destroy(&channel_callback.state_tracker);
cancel_pings(this,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport destroyed"));
@ -466,6 +465,8 @@ grpc_chttp2_transport::grpc_chttp2_transport(
ep(ep),
peer_string(grpc_endpoint_get_peer(ep)),
resource_user(resource_user),
state_tracker(is_client ? "client_transport" : "server_transport",
GRPC_CHANNEL_READY),
is_client(is_client),
next_stream_id(is_client ? 1 : 2),
deframe_state(is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0) {
@ -480,9 +481,6 @@ grpc_chttp2_transport::grpc_chttp2_transport(
grpc_chttp2_stream_map_init(&stream_map, 8);
grpc_slice_buffer_init(&read_buffer);
grpc_connectivity_state_init(
&channel_callback.state_tracker, GRPC_CHANNEL_READY,
is_client ? "client_transport" : "server_transport");
grpc_slice_buffer_init(&outbuf);
if (is_client) {
grpc_slice_buffer_add(&outbuf, grpc_slice_from_copied_string(
@ -770,7 +768,7 @@ static void destroy_stream(grpc_transport* gt, grpc_stream* gs,
grpc_chttp2_stream* grpc_chttp2_parsing_accept_stream(grpc_chttp2_transport* t,
uint32_t id) {
if (t->channel_callback.accept_stream == nullptr) {
if (t->accept_stream_cb == nullptr) {
return nullptr;
}
// Don't accept the stream if memory quota doesn't allow. Note that we should
@ -788,9 +786,8 @@ grpc_chttp2_stream* grpc_chttp2_parsing_accept_stream(grpc_chttp2_transport* t,
grpc_chttp2_stream* accepting = nullptr;
GPR_ASSERT(t->accepting_stream == nullptr);
t->accepting_stream = &accepting;
t->channel_callback.accept_stream(t->channel_callback.accept_stream_user_data,
&t->base,
(void*)static_cast<uintptr_t>(id));
t->accept_stream_cb(t->accept_stream_cb_user_data, &t->base,
(void*)static_cast<uintptr_t>(id));
t->accepting_stream = nullptr;
return accepting;
}
@ -1843,9 +1840,8 @@ static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) {
}
if (op->set_accept_stream) {
t->channel_callback.accept_stream = op->set_accept_stream_fn;
t->channel_callback.accept_stream_user_data =
op->set_accept_stream_user_data;
t->accept_stream_cb = op->set_accept_stream_fn;
t->accept_stream_cb_user_data = op->set_accept_stream_user_data;
}
if (op->bind_pollset) {
@ -1861,10 +1857,12 @@ static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) {
grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_APPLICATION_PING);
}
if (op->on_connectivity_state_change != nullptr) {
grpc_connectivity_state_notify_on_state_change(
&t->channel_callback.state_tracker, op->connectivity_state,
op->on_connectivity_state_change);
if (op->start_connectivity_watch != nullptr) {
t->state_tracker.AddWatcher(op->start_connectivity_watch_state,
std::move(op->start_connectivity_watch));
}
if (op->stop_connectivity_watch != nullptr) {
t->state_tracker.RemoveWatcher(op->stop_connectivity_watch);
}
if (op->disconnect_with_error != GRPC_ERROR_NONE) {
@ -2850,8 +2848,7 @@ static void connectivity_state_set(grpc_chttp2_transport* t,
const char* reason) {
GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_INFO, "transport %p set connectivity_state=%d", t, state));
grpc_connectivity_state_set(&t->channel_callback.state_tracker, state,
reason);
t->state_tracker.SetState(state, reason);
}
/*******************************************************************************

@ -339,15 +339,13 @@ struct grpc_chttp2_transport {
publish the accepted server stream */
grpc_chttp2_stream** accepting_stream = nullptr;
struct {
/* accept stream callback */
void (*accept_stream)(void* user_data, grpc_transport* transport,
const void* server_data);
void* accept_stream_user_data;
/** connectivity tracking */
grpc_connectivity_state_tracker state_tracker;
} channel_callback;
/* accept stream callback */
void (*accept_stream_cb)(void* user_data, grpc_transport* transport,
const void* server_data);
void* accept_stream_cb_user_data;
/** connectivity tracking */
grpc_core::ConnectivityStateTracker state_tracker;
/** data to write now */
grpc_slice_buffer outbuf;

@ -75,17 +75,17 @@ struct shared_mu {
struct inproc_transport {
inproc_transport(const grpc_transport_vtable* vtable, shared_mu* mu,
bool is_client)
: mu(mu), is_client(is_client) {
: mu(mu),
is_client(is_client),
state_tracker(is_client ? "inproc_client" : "inproc_server",
GRPC_CHANNEL_READY) {
base.vtable = vtable;
// Start each side of transport with 2 refs since they each have a ref
// to the other
gpr_ref_init(&refs, 2);
grpc_connectivity_state_init(&connectivity, GRPC_CHANNEL_READY,
is_client ? "inproc_client" : "inproc_server");
}
~inproc_transport() {
grpc_connectivity_state_destroy(&connectivity);
if (gpr_unref(&mu->refs)) {
mu->~shared_mu();
gpr_free(mu);
@ -111,7 +111,7 @@ struct inproc_transport {
shared_mu* mu;
gpr_refcount refs;
bool is_client;
grpc_connectivity_state_tracker connectivity;
grpc_core::ConnectivityStateTracker state_tracker;
void (*accept_stream_cb)(void* user_data, grpc_transport* transport,
const void* server_data);
void* accept_stream_data;
@ -1090,8 +1090,7 @@ 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);
grpc_connectivity_state_set(&t->connectivity, GRPC_CHANNEL_SHUTDOWN,
"close transport");
t->state_tracker.SetState(GRPC_CHANNEL_SHUTDOWN, "close transport");
if (!t->is_closed) {
t->is_closed = true;
/* Also end all streams on this transport */
@ -1110,10 +1109,12 @@ void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) {
inproc_transport* t = reinterpret_cast<inproc_transport*>(gt);
INPROC_LOG(GPR_INFO, "perform_transport_op %p %p", t, op);
gpr_mu_lock(&t->mu->mu);
if (op->on_connectivity_state_change) {
grpc_connectivity_state_notify_on_state_change(
&t->connectivity, op->connectivity_state,
op->on_connectivity_state_change);
if (op->start_connectivity_watch != nullptr) {
t->state_tracker.AddWatcher(op->start_connectivity_watch_state,
std::move(op->start_connectivity_watch));
}
if (op->stop_connectivity_watch != nullptr) {
t->state_tracker.RemoveWatcher(op->stop_connectivity_watch);
}
if (op->set_accept_stream) {
t->accept_stream_cb = op->set_accept_stream_fn;
@ -1226,10 +1227,15 @@ grpc_channel* grpc_inproc_channel_create(grpc_server* server,
grpc_core::ExecCtx exec_ctx;
const grpc_channel_args* server_args = grpc_server_get_channel_args(server);
// Remove max_connection_idle and max_connection_age channel arguments since
// those do not apply to inproc transports.
const char* args_to_remove[] = {GRPC_ARG_MAX_CONNECTION_IDLE_MS,
GRPC_ARG_MAX_CONNECTION_AGE_MS};
const grpc_channel_args* server_args = grpc_channel_args_copy_and_remove(
grpc_server_get_channel_args(server), args_to_remove,
GPR_ARRAY_SIZE(args_to_remove));
// Add a default authority channel argument for the client
grpc_arg default_authority_arg;
default_authority_arg.type = GRPC_ARG_STRING;
default_authority_arg.key = (char*)GRPC_ARG_DEFAULT_AUTHORITY;
@ -1249,6 +1255,7 @@ grpc_channel* grpc_inproc_channel_create(grpc_server* server,
"inproc", client_args, GRPC_CLIENT_DIRECT_CHANNEL, client_transport);
// Free up created channel args
grpc_channel_args_destroy(server_args);
grpc_channel_args_destroy(client_args);
// Now finish scheduled operations

@ -22,6 +22,8 @@
#include <string.h>
#include <grpc/grpc.h>
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/impl/codegen/log.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
@ -361,3 +363,17 @@ char* grpc_channel_args_string(const grpc_channel_args* args) {
gpr_strvec_destroy(&v);
return result;
}
namespace {
grpc_channel_args_client_channel_creation_mutator g_mutator = nullptr;
} // namespace
void grpc_channel_args_set_client_channel_creation_mutator(
grpc_channel_args_client_channel_creation_mutator cb) {
GPR_DEBUG_ASSERT(g_mutator == nullptr);
g_mutator = cb;
}
grpc_channel_args_client_channel_creation_mutator
grpc_channel_args_get_client_channel_creation_mutator() {
return g_mutator;
}

@ -23,6 +23,8 @@
#include <grpc/grpc.h>
#include "src/core/lib/surface/channel_stack_type.h"
// Channel args are intentionally immutable, to avoid the need for locking.
/** Copy the arguments in \a src into a new instance */
@ -108,4 +110,16 @@ grpc_arg grpc_channel_arg_pointer_create(char* name, void* value,
// Callers takes ownership of result.
char* grpc_channel_args_string(const grpc_channel_args* args);
// Takes ownership of the old_args
typedef grpc_channel_args* (*grpc_channel_args_client_channel_creation_mutator)(
const char* target, grpc_channel_args* old_args,
grpc_channel_stack_type type);
// Should be called only once globaly before grpc is init'ed.
void grpc_channel_args_set_client_channel_creation_mutator(
grpc_channel_args_client_channel_creation_mutator cb);
// This will be called at the creation of each channel.
grpc_channel_args_client_channel_creation_mutator
grpc_channel_args_get_client_channel_creation_mutator();
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_ARGS_H */

@ -234,8 +234,7 @@ grpc_json* ChannelNode::RenderJson() {
static_cast<grpc_connectivity_state>(state_field >> 1);
json = grpc_json_create_child(nullptr, json, "state", nullptr,
GRPC_JSON_OBJECT, false);
grpc_json_create_child(nullptr, json, "state",
grpc_connectivity_state_name(state),
grpc_json_create_child(nullptr, json, "state", ConnectivityStateName(state),
GRPC_JSON_STRING, false);
json = data;
}

@ -107,6 +107,10 @@ class InlinedVector {
return true;
}
bool operator!=(const InlinedVector& other) const {
return !(*this == other);
}
void reserve(size_t capacity) {
if (capacity > capacity_) {
T* new_dynamic =

@ -264,8 +264,6 @@ void Executor::ThreadMain(void* arg) {
grpc_core::ExecCtx::Get()->InvalidateNow();
subtract_depth = RunClosures(ts->name, closures);
}
// Clear the thread local after use.
gpr_tls_set(&g_this_thread_state, reinterpret_cast<intptr_t>(nullptr));
}
void Executor::Enqueue(grpc_closure* closure, grpc_error* error,

@ -0,0 +1,35 @@
/*
*
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPC_CORE_LIB_IOMGR_POLLER_EVENTMANAGER_INTERFACE_H
#define GRPC_CORE_LIB_IOMGR_POLLER_EVENTMANAGER_INTERFACE_H
namespace grpc {
namespace experimental {
class BaseEventManagerInterface {
public:
virtual ~BaseEventManagerInterface() {}
};
class EpollEventManagerInterface : public BaseEventManagerInterface {};
} // namespace experimental
} // namespace grpc
#endif /* GRPC_CORE_LIB_IOMGR_POLLER_EVENTMANAGER_INTERFACE_H */

@ -330,6 +330,19 @@ grpc_error* grpc_set_socket_with_mutator(int fd, grpc_socket_mutator* mutator) {
return GRPC_ERROR_NONE;
}
grpc_error* grpc_apply_socket_mutator_in_args(int fd,
const grpc_channel_args* args) {
const grpc_arg* socket_mutator_arg =
grpc_channel_args_find(args, GRPC_ARG_SOCKET_MUTATOR);
if (socket_mutator_arg == nullptr) {
return GRPC_ERROR_NONE;
}
GPR_DEBUG_ASSERT(socket_mutator_arg->type == GRPC_ARG_POINTER);
grpc_socket_mutator* mutator =
static_cast<grpc_socket_mutator*>(socket_mutator_arg->value.pointer.p);
return grpc_set_socket_with_mutator(fd, mutator);
}
static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT;
static int g_ipv6_loopback_available;

@ -91,6 +91,10 @@ grpc_error* grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes);
/* Tries to set the socket using a grpc_socket_mutator */
grpc_error* grpc_set_socket_with_mutator(int fd, grpc_socket_mutator* mutator);
/* Extracts the first socket mutator from args if any and applies on the fd. */
grpc_error* grpc_apply_socket_mutator_in_args(int fd,
const grpc_channel_args* args);
/* An enum to keep track of IPv4/IPv6 socket modes.
Currently, this information is only used when a socket is first created, but

@ -84,17 +84,10 @@ static grpc_error* prepare_socket(const grpc_resolved_address* addr, int fd,
}
err = grpc_set_socket_no_sigpipe_if_possible(fd);
if (err != GRPC_ERROR_NONE) goto error;
if (channel_args) {
for (size_t i = 0; i < channel_args->num_args; i++) {
if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_SOCKET_MUTATOR)) {
GPR_ASSERT(channel_args->args[i].type == GRPC_ARG_POINTER);
grpc_socket_mutator* mutator = static_cast<grpc_socket_mutator*>(
channel_args->args[i].value.pointer.p);
err = grpc_set_socket_with_mutator(fd, mutator);
if (err != GRPC_ERROR_NONE) goto error;
}
}
}
err = grpc_apply_socket_mutator_in_args(fd, channel_args);
if (err != GRPC_ERROR_NONE) goto error;
goto done;
error:

@ -173,17 +173,8 @@ grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server* s, int fd,
err = grpc_set_socket_no_sigpipe_if_possible(fd);
if (err != GRPC_ERROR_NONE) goto error;
if (s->channel_args) {
for (size_t i = 0; i < s->channel_args->num_args; i++) {
if (0 == strcmp(s->channel_args->args[i].key, GRPC_ARG_SOCKET_MUTATOR)) {
GPR_ASSERT(s->channel_args->args[i].type == GRPC_ARG_POINTER);
grpc_socket_mutator* mutator = static_cast<grpc_socket_mutator*>(
s->channel_args->args[i].value.pointer.p);
err = grpc_set_socket_with_mutator(fd, mutator);
if (err != GRPC_ERROR_NONE) goto error;
}
}
}
err = grpc_apply_socket_mutator_in_args(fd, s->channel_args);
if (err != GRPC_ERROR_NONE) goto error;
if (bind(fd, reinterpret_cast<grpc_sockaddr*>(const_cast<char*>(addr->addr)),
addr->len) < 0) {

@ -257,6 +257,13 @@ grpc_channel* grpc_channel_create(const char* target,
get_default_authority(input_args);
grpc_channel_args* args =
build_channel_args(input_args, default_authority.get());
if (grpc_channel_stack_type_is_client(channel_stack_type)) {
auto channel_args_mutator =
grpc_channel_args_get_client_channel_creation_mutator();
if (channel_args_mutator != nullptr) {
args = channel_args_mutator(target, args, channel_stack_type);
}
}
grpc_channel_stack_builder_set_channel_arguments(builder, args);
grpc_channel_args_destroy(args);
grpc_channel_stack_builder_set_target(builder, target);

@ -32,6 +32,7 @@
#include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/surface/lame_client.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/static_metadata.h"
namespace grpc_core {
@ -39,15 +40,19 @@ namespace grpc_core {
namespace {
struct CallData {
grpc_core::CallCombiner* call_combiner;
CallCombiner* call_combiner;
grpc_linked_mdelem status;
grpc_linked_mdelem details;
grpc_core::Atomic<bool> filled_metadata;
Atomic<bool> filled_metadata;
};
struct ChannelData {
ChannelData() : state_tracker("lame_channel", GRPC_CHANNEL_SHUTDOWN) {}
grpc_status_code error_code;
const char* error_message;
Mutex mu;
ConnectivityStateTracker state_tracker;
};
static void fill_metadata(grpc_call_element* elem, grpc_metadata_batch* mdb) {
@ -94,10 +99,16 @@ static void lame_get_channel_info(grpc_channel_element* elem,
static void lame_start_transport_op(grpc_channel_element* elem,
grpc_transport_op* op) {
if (op->on_connectivity_state_change) {
GPR_ASSERT(*op->connectivity_state != GRPC_CHANNEL_SHUTDOWN);
*op->connectivity_state = GRPC_CHANNEL_SHUTDOWN;
GRPC_CLOSURE_SCHED(op->on_connectivity_state_change, GRPC_ERROR_NONE);
ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
{
MutexLock lock(&chand->mu);
if (op->start_connectivity_watch != nullptr) {
chand->state_tracker.AddWatcher(op->start_connectivity_watch_state,
std::move(op->start_connectivity_watch));
}
if (op->stop_connectivity_watch != nullptr) {
chand->state_tracker.RemoveWatcher(op->stop_connectivity_watch);
}
}
if (op->send_ping.on_initiate != nullptr) {
GRPC_CLOSURE_SCHED(
@ -132,10 +143,14 @@ static grpc_error* lame_init_channel_elem(grpc_channel_element* elem,
grpc_channel_element_args* args) {
GPR_ASSERT(args->is_first);
GPR_ASSERT(args->is_last);
new (elem->channel_data) ChannelData;
return GRPC_ERROR_NONE;
}
static void lame_destroy_channel_elem(grpc_channel_element* elem) {}
static void lame_destroy_channel_elem(grpc_channel_element* elem) {
ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
chand->~ChannelData();
}
} // namespace

@ -105,7 +105,6 @@ struct channel_registered_method {
struct channel_data {
grpc_server* server;
grpc_connectivity_state connectivity_state;
grpc_channel* channel;
size_t cq_idx;
/* linked list of all channels on a server */
@ -115,7 +114,6 @@ struct channel_data {
uint32_t registered_method_slots;
uint32_t registered_method_max_probes;
grpc_closure finish_destroy_channel_closure;
grpc_closure channel_connectivity_changed;
intptr_t channelz_socket_uuid;
};
@ -458,7 +456,7 @@ static void finish_destroy_channel(void* cd, grpc_error* error) {
server_unref(server);
}
static void destroy_channel(channel_data* chand, grpc_error* error) {
static void destroy_channel(channel_data* chand) {
if (is_channel_orphaned(chand)) return;
GPR_ASSERT(chand->server != nullptr);
orphan_channel(chand);
@ -467,12 +465,9 @@ static void destroy_channel(channel_data* chand, grpc_error* error) {
GRPC_CLOSURE_INIT(&chand->finish_destroy_channel_closure,
finish_destroy_channel, chand, grpc_schedule_on_exec_ctx);
if (GRPC_TRACE_FLAG_ENABLED(grpc_server_channel_trace) &&
error != GRPC_ERROR_NONE) {
const char* msg = grpc_error_string(error);
gpr_log(GPR_INFO, "Disconnected client: %s", msg);
if (GRPC_TRACE_FLAG_ENABLED(grpc_server_channel_trace)) {
gpr_log(GPR_INFO, "Disconnected client");
}
GRPC_ERROR_UNREF(error);
grpc_transport_op* op =
grpc_make_transport_op(&chand->finish_destroy_channel_closure);
@ -633,7 +628,7 @@ static void start_new_rpc(grpc_call_element* elem) {
for (i = 0; i <= chand->registered_method_max_probes; i++) {
rm = &chand->registered_methods[(hash + i) %
chand->registered_method_slots];
if (!rm) break;
if (rm->server_registered_method == nullptr) break;
if (!rm->has_host) continue;
if (!grpc_slice_eq(rm->host, calld->host)) continue;
if (!grpc_slice_eq(rm->method, calld->path)) continue;
@ -651,7 +646,7 @@ static void start_new_rpc(grpc_call_element* elem) {
for (i = 0; i <= chand->registered_method_max_probes; i++) {
rm = &chand->registered_methods[(hash + i) %
chand->registered_method_slots];
if (!rm) break;
if (rm->server_registered_method == nullptr) break;
if (rm->has_host) continue;
if (!grpc_slice_eq(rm->method, calld->path)) continue;
if ((rm->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) &&
@ -891,24 +886,6 @@ static void accept_stream(void* cd, grpc_transport* transport,
grpc_call_start_batch_and_execute(call, &op, 1, &calld->got_initial_metadata);
}
static void channel_connectivity_changed(void* cd, grpc_error* error) {
channel_data* chand = static_cast<channel_data*>(cd);
grpc_server* server = chand->server;
if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->on_connectivity_state_change = &chand->channel_connectivity_changed;
op->connectivity_state = &chand->connectivity_state;
grpc_channel_next_op(grpc_channel_stack_element(
grpc_channel_get_channel_stack(chand->channel), 0),
op);
} else {
gpr_mu_lock(&server->mu_global);
destroy_channel(chand, GRPC_ERROR_REF(error));
gpr_mu_unlock(&server->mu_global);
GRPC_CHANNEL_INTERNAL_UNREF(chand->channel, "connectivity");
}
}
static grpc_error* server_init_call_elem(grpc_call_element* elem,
const grpc_call_element_args* args) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
@ -935,10 +912,6 @@ static grpc_error* server_init_channel_elem(grpc_channel_element* elem,
chand->channel = nullptr;
chand->next = chand->prev = chand;
chand->registered_methods = nullptr;
chand->connectivity_state = GRPC_CHANNEL_IDLE;
GRPC_CLOSURE_INIT(&chand->channel_connectivity_changed,
channel_connectivity_changed, chand,
grpc_schedule_on_exec_ctx);
return GRPC_ERROR_NONE;
}
@ -1149,6 +1122,31 @@ void grpc_server_get_pollsets(grpc_server* server, grpc_pollset*** pollsets,
*pollsets = server->pollsets;
}
class ConnectivityWatcher
: public grpc_core::AsyncConnectivityStateWatcherInterface {
public:
explicit ConnectivityWatcher(channel_data* chand) : chand_(chand) {
GRPC_CHANNEL_INTERNAL_REF(chand_->channel, "connectivity");
}
~ConnectivityWatcher() {
GRPC_CHANNEL_INTERNAL_UNREF(chand_->channel, "connectivity");
}
private:
void OnConnectivityStateChange(grpc_connectivity_state new_state) override {
// Don't do anything until we are being shut down.
if (new_state != GRPC_CHANNEL_SHUTDOWN) return;
// Shut down channel.
grpc_server* server = chand_->server;
gpr_mu_lock(&server->mu_global);
destroy_channel(chand_);
gpr_mu_unlock(&server->mu_global);
}
channel_data* chand_;
};
void grpc_server_setup_transport(
grpc_server* s, grpc_transport* transport, grpc_pollset* accepting_pollset,
const grpc_channel_args* args,
@ -1241,13 +1239,12 @@ void grpc_server_setup_transport(
chand->next->prev = chand->prev->next = chand;
gpr_mu_unlock(&s->mu_global);
GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity");
op = grpc_make_transport_op(nullptr);
op->set_accept_stream = true;
op->set_accept_stream_fn = accept_stream;
op->set_accept_stream_user_data = chand;
op->on_connectivity_state_change = &chand->channel_connectivity_changed;
op->connectivity_state = &chand->connectivity_state;
op->start_connectivity_watch.reset(
grpc_core::New<ConnectivityWatcher>(chand));
if (gpr_atm_acq_load(&s->shutdown_flag) != 0) {
op->disconnect_with_error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server shutdown");

@ -26,9 +26,13 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
grpc_core::TraceFlag grpc_connectivity_state_trace(false, "connectivity_state");
#include "src/core/lib/iomgr/exec_ctx.h"
const char* grpc_connectivity_state_name(grpc_connectivity_state state) {
namespace grpc_core {
TraceFlag grpc_connectivity_state_trace(false, "connectivity_state");
const char* ConnectivityStateName(grpc_connectivity_state state) {
switch (state) {
case GRPC_CHANNEL_IDLE:
return "IDLE";
@ -44,122 +48,121 @@ const char* grpc_connectivity_state_name(grpc_connectivity_state state) {
GPR_UNREACHABLE_CODE(return "UNKNOWN");
}
void grpc_connectivity_state_init(grpc_connectivity_state_tracker* tracker,
grpc_connectivity_state init_state,
const char* name) {
gpr_atm_no_barrier_store(&tracker->current_state_atm, init_state);
tracker->watchers = nullptr;
tracker->name = gpr_strdup(name);
}
//
// AsyncConnectivityStateWatcherInterface
//
void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker* tracker) {
grpc_error* error;
grpc_connectivity_state_watcher* w;
while ((w = tracker->watchers)) {
tracker->watchers = w->next;
if (GRPC_CHANNEL_SHUTDOWN != *w->current) {
*w->current = GRPC_CHANNEL_SHUTDOWN;
error = GRPC_ERROR_NONE;
} else {
error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Shutdown connectivity owner");
}
GRPC_CLOSURE_SCHED(w->notify, error);
gpr_free(w);
// A fire-and-forget class to asynchronously deliver a connectivity
// state notification to a watcher.
class AsyncConnectivityStateWatcherInterface::Notifier {
public:
Notifier(RefCountedPtr<AsyncConnectivityStateWatcherInterface> watcher,
grpc_connectivity_state state)
: watcher_(std::move(watcher)), state_(state) {
GRPC_CLOSURE_INIT(&closure_, SendNotification, this,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE);
}
gpr_free(tracker->name);
}
grpc_connectivity_state grpc_connectivity_state_check(
grpc_connectivity_state_tracker* tracker) {
grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
gpr_atm_no_barrier_load(&tracker->current_state_atm));
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
gpr_log(GPR_INFO, "CONWATCH: %p %s: get %s", tracker, tracker->name,
grpc_connectivity_state_name(cur));
private:
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_));
}
self->watcher_->OnConnectivityStateChange(self->state_);
Delete(self);
}
return cur;
RefCountedPtr<AsyncConnectivityStateWatcherInterface> watcher_;
const grpc_connectivity_state state_;
grpc_closure closure_;
};
void AsyncConnectivityStateWatcherInterface::Notify(
grpc_connectivity_state state) {
New<Notifier>(Ref(), state); // Deletes itself when done.
}
bool grpc_connectivity_state_has_watchers(
grpc_connectivity_state_tracker* connectivity_state) {
return connectivity_state->watchers != nullptr;
//
// ConnectivityStateTracker
//
ConnectivityStateTracker::~ConnectivityStateTracker() {
grpc_connectivity_state current_state = state_.Load(MemoryOrder::RELAXED);
if (current_state == GRPC_CHANNEL_SHUTDOWN) return;
for (const auto& p : watchers_) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
gpr_log(GPR_INFO,
"ConnectivityStateTracker %s[%p]: notifying watcher %p: %s -> %s",
name_, this, p.first, ConnectivityStateName(current_state),
ConnectivityStateName(GRPC_CHANNEL_SHUTDOWN));
}
p.second->Notify(GRPC_CHANNEL_SHUTDOWN);
}
}
bool grpc_connectivity_state_notify_on_state_change(
grpc_connectivity_state_tracker* tracker, grpc_connectivity_state* current,
grpc_closure* notify) {
grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
gpr_atm_no_barrier_load(&tracker->current_state_atm));
void ConnectivityStateTracker::AddWatcher(
grpc_connectivity_state initial_state,
OrphanablePtr<ConnectivityStateWatcherInterface> watcher) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
if (current == nullptr) {
gpr_log(GPR_INFO, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
tracker->name, notify);
} else {
gpr_log(GPR_INFO, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker,
tracker->name, grpc_connectivity_state_name(*current),
grpc_connectivity_state_name(cur), notify);
}
gpr_log(GPR_INFO, "ConnectivityStateTracker %s[%p]: add watcher %p", name_,
this, watcher.get());
}
if (current == nullptr) {
grpc_connectivity_state_watcher* w = tracker->watchers;
if (w != nullptr && w->notify == notify) {
GRPC_CLOSURE_SCHED(notify, GRPC_ERROR_CANCELLED);
tracker->watchers = w->next;
gpr_free(w);
return false;
}
while (w != nullptr) {
grpc_connectivity_state_watcher* rm_candidate = w->next;
if (rm_candidate != nullptr && rm_candidate->notify == notify) {
GRPC_CLOSURE_SCHED(notify, GRPC_ERROR_CANCELLED);
w->next = w->next->next;
gpr_free(rm_candidate);
return false;
}
w = w->next;
}
return false;
} else {
if (cur != *current) {
*current = cur;
GRPC_CLOSURE_SCHED(notify, GRPC_ERROR_NONE);
} else {
grpc_connectivity_state_watcher* w =
static_cast<grpc_connectivity_state_watcher*>(gpr_malloc(sizeof(*w)));
w->current = current;
w->notify = notify;
w->next = tracker->watchers;
tracker->watchers = w;
grpc_connectivity_state current_state = state_.Load(MemoryOrder::RELAXED);
if (initial_state != current_state) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
gpr_log(GPR_INFO,
"ConnectivityStateTracker %s[%p]: notifying watcher %p: %s -> %s",
name_, this, watcher.get(), ConnectivityStateName(initial_state),
ConnectivityStateName(current_state));
}
return cur == GRPC_CHANNEL_IDLE;
watcher->Notify(current_state);
}
watchers_.insert(MakePair(watcher.get(), std::move(watcher)));
}
void grpc_connectivity_state_set(grpc_connectivity_state_tracker* tracker,
grpc_connectivity_state state,
const char* reason) {
grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
gpr_atm_no_barrier_load(&tracker->current_state_atm));
grpc_connectivity_state_watcher* w;
void ConnectivityStateTracker::RemoveWatcher(
ConnectivityStateWatcherInterface* watcher) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
gpr_log(GPR_INFO, "SET: %p %s: %s --> %s [%s]", tracker, tracker->name,
grpc_connectivity_state_name(cur),
grpc_connectivity_state_name(state), reason);
gpr_log(GPR_INFO, "ConnectivityStateTracker %s[%p]: remove watcher %p",
name_, this, watcher);
}
if (cur == state) {
return;
watchers_.erase(watcher);
}
void ConnectivityStateTracker::SetState(grpc_connectivity_state state,
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_ASSERT(cur != GRPC_CHANNEL_SHUTDOWN);
gpr_atm_no_barrier_store(&tracker->current_state_atm, state);
while ((w = tracker->watchers) != nullptr) {
*w->current = state;
tracker->watchers = w->next;
state_.Store(state, MemoryOrder::RELAXED);
for (const auto& p : watchers_) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
gpr_log(GPR_INFO, "NOTIFY: %p %s: %p", tracker, tracker->name, w->notify);
gpr_log(GPR_INFO,
"ConnectivityStateTracker %s[%p]: notifying watcher %p: %s -> %s",
name_, this, p.first, ConnectivityStateName(current_state),
ConnectivityStateName(state));
}
GRPC_CLOSURE_SCHED(w->notify, GRPC_ERROR_NONE);
gpr_free(w);
p.second->Notify(state);
}
// If the new state is SHUTDOWN, orphan all of the watchers. This
// avoids the need for the callers to explicitly cancel them.
if (state == GRPC_CHANNEL_SHUTDOWN) watchers_.clear();
}
grpc_connectivity_state ConnectivityStateTracker::state() const {
grpc_connectivity_state state = state_.Load(MemoryOrder::RELAXED);
if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
gpr_log(GPR_INFO, "ConnectivityStateTracker %s[%p]: get current state: %s",
name_, this, ConnectivityStateName(state));
}
return state;
}
} // namespace grpc_core

@ -22,58 +22,98 @@
#include <grpc/support/port_platform.h>
#include <grpc/grpc.h>
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/atomic.h"
#include "src/core/lib/gprpp/map.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/iomgr/closure.h"
typedef struct grpc_connectivity_state_watcher {
/** we keep watchers in a linked list */
struct grpc_connectivity_state_watcher* next;
/** closure to notify on change */
grpc_closure* notify;
/** the current state as believed by the watcher */
grpc_connectivity_state* current;
} grpc_connectivity_state_watcher;
typedef struct {
/** current grpc_connectivity_state */
gpr_atm current_state_atm;
/** all our watchers */
grpc_connectivity_state_watcher* watchers;
/** a name to help debugging */
char* name;
} grpc_connectivity_state_tracker;
extern grpc_core::TraceFlag grpc_connectivity_state_trace;
/** enum --> string conversion */
const char* grpc_connectivity_state_name(grpc_connectivity_state state);
void grpc_connectivity_state_init(grpc_connectivity_state_tracker* tracker,
grpc_connectivity_state init_state,
const char* name);
void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker* tracker);
/** Set connectivity state; not thread safe; access must be serialized with an
* external lock */
void grpc_connectivity_state_set(grpc_connectivity_state_tracker* tracker,
grpc_connectivity_state state,
const char* reason);
/** Return true if this connectivity state has watchers.
Access must be serialized with an external lock. */
bool grpc_connectivity_state_has_watchers(
grpc_connectivity_state_tracker* tracker);
/** Return the last seen connectivity state. No need to synchronize access. */
grpc_connectivity_state grpc_connectivity_state_check(
grpc_connectivity_state_tracker* tracker);
/** Return 1 if the channel should start connecting, 0 otherwise.
If current==NULL cancel notify if it is already queued (success==0 in that
case).
Access must be serialized with an external lock. */
bool grpc_connectivity_state_notify_on_state_change(
grpc_connectivity_state_tracker* tracker, grpc_connectivity_state* current,
grpc_closure* notify);
namespace grpc_core {
extern TraceFlag grpc_connectivity_state_trace;
// Enum to string conversion.
const char* ConnectivityStateName(grpc_connectivity_state state);
// Interface for watching connectivity state.
// Subclasses must implement the Notify() method.
//
// Note: Most callers will want to use
// AsyncConnectivityStateWatcherInterface instead.
class ConnectivityStateWatcherInterface
: public InternallyRefCounted<ConnectivityStateWatcherInterface> {
public:
virtual ~ConnectivityStateWatcherInterface() = default;
// Notifies the watcher that the state has changed to new_state.
virtual void Notify(grpc_connectivity_state new_state) GRPC_ABSTRACT;
void Orphan() override { Unref(); }
GRPC_ABSTRACT_BASE_CLASS
};
// An alternative watcher interface that performs notifications via an
// asynchronous callback scheduled on the ExecCtx.
// Subclasses must implement the OnConnectivityStateChange() method.
class AsyncConnectivityStateWatcherInterface
: public ConnectivityStateWatcherInterface {
public:
virtual ~AsyncConnectivityStateWatcherInterface() = default;
// Schedules a closure on the ExecCtx to invoke
// OnConnectivityStateChange() asynchronously.
void Notify(grpc_connectivity_state new_state) override final;
protected:
class Notifier;
// Invoked asynchronously when Notify() is called.
virtual void OnConnectivityStateChange(grpc_connectivity_state new_state)
GRPC_ABSTRACT;
};
// Tracks connectivity state. Maintains a list of watchers that are
// notified whenever the state changes.
class ConnectivityStateTracker {
public:
ConnectivityStateTracker(const char* name,
grpc_connectivity_state state = GRPC_CHANNEL_IDLE)
: name_(name), state_(state) {}
~ConnectivityStateTracker();
// Adds a watcher.
// If the current state is different than initial_state, the watcher
// will be notified immediately. Otherwise, it will be notified
// whenever the state changes.
// Not thread safe; access must be serialized with an external lock.
void AddWatcher(grpc_connectivity_state initial_state,
OrphanablePtr<ConnectivityStateWatcherInterface> watcher);
// Removes a watcher. The watcher will be orphaned.
// Not thread safe; access must be serialized with an external lock.
void RemoveWatcher(ConnectivityStateWatcherInterface* watcher);
// Sets connectivity state.
// Not thread safe; access must be serialized with an external lock.
void SetState(grpc_connectivity_state state, const char* reason);
// Gets the current state.
// Thread safe; no need to use an external lock.
grpc_connectivity_state state() const;
private:
const char* name_;
Atomic<grpc_connectivity_state> state_;
// TODO(roth): This could be a set instead of a map if we had a set
// implementation.
Map<ConnectivityStateWatcherInterface*,
OrphanablePtr<ConnectivityStateWatcherInterface>>
watchers_;
};
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H */

@ -25,6 +25,7 @@
#include "src/core/lib/channel/context.h"
#include "src/core/lib/gprpp/arena.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/iomgr/call_combiner.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/polling_entity.h"
@ -32,6 +33,7 @@
#include "src/core/lib/iomgr/pollset_set.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/byte_stream.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/metadata_batch.h"
/* Minimum and maximum protocol accepted versions. */
@ -320,8 +322,11 @@ typedef struct grpc_transport_op {
/** Called when processing of this op is done. */
grpc_closure* on_consumed = nullptr;
/** connectivity monitoring - set connectivity_state to NULL to unsubscribe */
grpc_closure* on_connectivity_state_change = nullptr;
grpc_connectivity_state* connectivity_state = nullptr;
grpc_core::OrphanablePtr<grpc_core::ConnectivityStateWatcherInterface>
start_connectivity_watch;
grpc_connectivity_state start_connectivity_watch_state = GRPC_CHANNEL_IDLE;
grpc_core::ConnectivityStateWatcherInterface* stop_connectivity_watch =
nullptr;
/** should the transport be disconnected
* Error contract: the transport that gets this op must cause
* disconnect_with_error to be unref'ed after processing it */

@ -134,19 +134,22 @@ char* grpc_transport_op_string(grpc_transport_op* op) {
gpr_strvec b;
gpr_strvec_init(&b);
if (op->on_connectivity_state_change != nullptr) {
if (op->start_connectivity_watch != nullptr) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
first = false;
if (op->connectivity_state != nullptr) {
gpr_asprintf(&tmp, "ON_CONNECTIVITY_STATE_CHANGE:p=%p:from=%s",
op->on_connectivity_state_change,
grpc_connectivity_state_name(*op->connectivity_state));
gpr_strvec_add(&b, tmp);
} else {
gpr_asprintf(&tmp, "ON_CONNECTIVITY_STATE_CHANGE:p=%p:unsubscribe",
op->on_connectivity_state_change);
gpr_strvec_add(&b, tmp);
}
gpr_asprintf(
&tmp, "START_CONNECTIVITY_WATCH:watcher=%p:from=%s",
op->start_connectivity_watch.get(),
grpc_core::ConnectivityStateName(op->start_connectivity_watch_state));
gpr_strvec_add(&b, tmp);
}
if (op->stop_connectivity_watch != nullptr) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
first = false;
gpr_asprintf(&tmp, "STOP_CONNECTIVITY_WATCH:watcher=%p",
op->stop_connectivity_watch);
gpr_strvec_add(&b, tmp);
}
if (op->disconnect_with_error != GRPC_ERROR_NONE) {

@ -34,7 +34,7 @@
constexpr size_t kMinFrameLength = 1024;
constexpr size_t kDefaultFrameLength = 16 * 1024;
constexpr size_t kMaxFrameLength = 16 * 1024 * 1024;
constexpr size_t kMaxFrameLength = 1024 * 1024;
// Limit k on number of frames such that at most 2^(8 * k) frames can be sent.
constexpr size_t kAltsRecordProtocolRekeyFrameLimit = 8;

@ -37,7 +37,7 @@
constexpr size_t kMinFrameLength = 1024;
constexpr size_t kDefaultFrameLength = 16 * 1024;
constexpr size_t kMaxFrameLength = 1024 * 1024;
constexpr size_t kMaxFrameLength = 16 * 1024 * 1024;
/**
* Main struct for alts_zero_copy_grpc_protector.
@ -233,11 +233,21 @@ static void alts_zero_copy_grpc_protector_destroy(
gpr_free(protector);
}
static tsi_result alts_zero_copy_grpc_protector_max_frame_size(
tsi_zero_copy_grpc_protector* self, size_t& max_frame_size) {
if (self == nullptr) return TSI_INVALID_ARGUMENT;
alts_zero_copy_grpc_protector* protector =
reinterpret_cast<alts_zero_copy_grpc_protector*>(self);
max_frame_size = protector->max_protected_frame_size;
return TSI_OK;
}
static const tsi_zero_copy_grpc_protector_vtable
alts_zero_copy_grpc_protector_vtable = {
alts_zero_copy_grpc_protector_protect,
alts_zero_copy_grpc_protector_unprotect,
alts_zero_copy_grpc_protector_destroy};
alts_zero_copy_grpc_protector_destroy,
alts_zero_copy_grpc_protector_max_frame_size};
tsi_result alts_zero_copy_grpc_protector_create(
const uint8_t* key, size_t key_size, bool is_rekey, bool is_client,

@ -483,6 +483,7 @@ static const tsi_zero_copy_grpc_protector_vtable
fake_zero_copy_grpc_protector_protect,
fake_zero_copy_grpc_protector_unprotect,
fake_zero_copy_grpc_protector_destroy,
nullptr /* fake_zero_copy_grpc_protector_max_frame_size */
};
/* --- tsi_handshaker_result methods implementation. ---*/

File diff suppressed because it is too large Load Diff

@ -84,7 +84,8 @@ static const tsi_zero_copy_grpc_protector_vtable
local_zero_copy_grpc_protector_vtable = {
local_zero_copy_grpc_protector_protect,
local_zero_copy_grpc_protector_unprotect,
local_zero_copy_grpc_protector_destroy};
local_zero_copy_grpc_protector_destroy,
nullptr /* local_zero_copy_grpc_protector_max_frame_size */};
tsi_result local_zero_copy_grpc_protector_create(
tsi_zero_copy_grpc_protector** protector) {

@ -64,3 +64,10 @@ void tsi_zero_copy_grpc_protector_destroy(tsi_zero_copy_grpc_protector* self) {
if (self == nullptr) return;
self->vtable->destroy(self);
}
tsi_result tsi_zero_copy_grpc_protector_max_frame_size(
tsi_zero_copy_grpc_protector* self, size_t& max_frame_size) {
if (self == nullptr) return TSI_INVALID_ARGUMENT;
if (self->vtable->max_frame_size == nullptr) return TSI_UNIMPLEMENTED;
return self->vtable->max_frame_size(self, max_frame_size);
}

@ -56,6 +56,10 @@ tsi_result tsi_zero_copy_grpc_protector_unprotect(
/* Destroys the tsi_zero_copy_grpc_protector object. */
void tsi_zero_copy_grpc_protector_destroy(tsi_zero_copy_grpc_protector* self);
/* Returns value of max protected frame size. Useful for testing. */
tsi_result tsi_zero_copy_grpc_protector_max_frame_size(
tsi_zero_copy_grpc_protector* self, size_t& max_frame_size);
/* Base for tsi_zero_copy_grpc_protector implementations. */
typedef struct {
tsi_result (*protect)(tsi_zero_copy_grpc_protector* self,
@ -65,6 +69,8 @@ typedef struct {
grpc_slice_buffer* protected_slices,
grpc_slice_buffer* unprotected_slices);
void (*destroy)(tsi_zero_copy_grpc_protector* self);
tsi_result (*max_frame_size)(tsi_zero_copy_grpc_protector* self,
size_t& max_frame_size);
} tsi_zero_copy_grpc_protector_vtable;
struct tsi_zero_copy_grpc_protector {

@ -20,9 +20,9 @@ cd $(dirname $0)
# cleanup temporary files
rm -rf html obj grpc-gh-pages
# generate into src/csharp/doc/html directory
# generate into src/csharp/docfx/html directory
cd ..
docker run --rm -v "$(pwd)":/work -w /work/doc --user "$(id -u):$(id -g)" -it tsgkadot/docker-docfx:latest docfx
docker run --rm -v "$(pwd)":/work -w /work/docfx --user "$(id -u):$(id -g)" -it tsgkadot/docker-docfx:latest docfx
cd docfx
# prepare a clone of "gh-pages" branch where the generated docs are stored

@ -28,7 +28,7 @@ function build {
PATH_CC="$(xcrun --sdk $SDK --find clang)"
PATH_CXX="$(xcrun --sdk $SDK --find clang++)"
CPPFLAGS="-O2 -Wframe-larger-than=16384 -arch $ARCH -isysroot $(xcrun --sdk $SDK --show-sdk-path) -fembed-bitcode -mios-version-min=6.0 -DPB_NO_PACKED_STRUCTS=1"
CPPFLAGS="-O2 -Wframe-larger-than=16384 -arch $ARCH -isysroot $(xcrun --sdk $SDK --show-sdk-path) -mios-version-min=6.0 -DPB_NO_PACKED_STRUCTS=1"
LDFLAGS="-arch $ARCH -isysroot $(xcrun --sdk $SDK --show-sdk-path) -Wl,ios_version_min=6.0"
# TODO(jtattermusch): revisit the build arguments

File diff suppressed because it is too large Load Diff

@ -30,7 +30,7 @@
Pod::Spec.new do |s|
s.name = "CronetFramework"
v = '0.0.4'
v = '0.0.5'
s.version = v
s.summary = "Cronet, precompiled and used as a framework."
s.homepage = "http://chromium.org"

File diff suppressed because it is too large Load Diff

@ -76,11 +76,6 @@ extern const char *kCFStreamVarName;
@end
BOOL isUsingCFStream() {
NSString *enabled = @(getenv(kCFStreamVarName));
return [enabled isEqualToString:@"1"];
}
#pragma mark Tests
@implementation PerfTests {
@ -118,12 +113,6 @@ BOOL isUsingCFStream() {
return nil;
}
+ (void)setUp {
setenv("GRPC_TRACE", "tcp", 1);
setenv("GRPC_VERBOSITY", "DEBUG", 1);
NSLog(@"In setUp");
}
- (void)setUp {
self.continueAfterFailure = NO;
@ -137,6 +126,10 @@ BOOL isUsingCFStream() {
_service = [[self class] host] ? [RMTTestService serviceWithHost:[[self class] host]] : nil;
}
- (BOOL)isUsingCFStream {
return [NSStringFromClass([self class]) isEqualToString:@"PerfTestsCFStreamSSL"];
}
- (void)pingPongV2APIWithRequest:(RMTStreamingOutputCallRequest *)request
numMessages:(int)numMessages
options:(GRPCMutableCallOptions *)options {
@ -265,37 +258,41 @@ BOOL isUsingCFStream() {
}];
}
- (void)unaryRPCWithRequest:(RMTSimpleRequest *)request
numMessages:(int)numMessages
callOptions:(GRPCMutableCallOptions *)options {
const int kOutstandingRPCs = 10;
NSAssert(numMessages > kOutstandingRPCs, @"Number of RPCs must be > %d", kOutstandingRPCs);
- (void)unaryRPCsWithServices:(NSArray<RMTTestService *> *)services
request:(RMTSimpleRequest *)request
callsPerService:(int)callsPerService
maxOutstandingCalls:(int)maxOutstandingCalls
callOptions:(GRPCMutableCallOptions *)options {
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"unaryRPC"];
dispatch_semaphore_t sema = dispatch_semaphore_create(kOutstandingRPCs);
dispatch_semaphore_t sema = dispatch_semaphore_create(maxOutstandingCalls);
__block int index = 0;
for (int i = 0; i < numMessages; ++i) {
GRPCUnaryProtoCall *call = [_service
unaryCallWithMessage:request
responseHandler:[[PerfTestsBlockCallbacks alloc]
initWithInitialMetadataCallback:nil
messageCallback:nil
closeCallback:^(NSDictionary *trailingMetadata,
NSError *error) {
dispatch_semaphore_signal(sema);
@synchronized(self) {
++index;
if (index == numMessages) {
[expectation fulfill];
for (RMTTestService *service in services) {
for (int i = 0; i < callsPerService; ++i) {
GRPCUnaryProtoCall *call = [service
unaryCallWithMessage:request
responseHandler:[[PerfTestsBlockCallbacks alloc]
initWithInitialMetadataCallback:nil
messageCallback:nil
closeCallback:^(NSDictionary *trailingMetadata,
NSError *error) {
dispatch_semaphore_signal(sema);
@synchronized(self) {
++index;
if (index ==
callsPerService * [services count]) {
[expectation fulfill];
}
}
}
}]
callOptions:options];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
[call start];
}]
callOptions:options];
dispatch_time_t timeout =
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(TEST_TIMEOUT * NSEC_PER_SEC));
dispatch_semaphore_wait(sema, timeout);
[call start];
}
}
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
@ -303,7 +300,7 @@ BOOL isUsingCFStream() {
- (void)testUnaryRPC {
// Workaround Apple CFStream bug
if (isUsingCFStream()) {
if ([self isUsingCFStream]) {
return;
}
@ -317,10 +314,54 @@ BOOL isUsingCFStream() {
options.hostNameOverride = [[self class] hostNameOverride];
// warm up
[self unaryRPCWithRequest:request numMessages:50 callOptions:options];
[self unaryRPCsWithServices:@[ self->_service ]
request:request
callsPerService:50
maxOutstandingCalls:10
callOptions:options];
[self measureBlock:^{
[self unaryRPCsWithServices:@[ self->_service ]
request:request
callsPerService:50
maxOutstandingCalls:10
callOptions:options];
}];
}
- (void)testMultipleChannels {
NSString *port = [[[self class] host] componentsSeparatedByString:@":"][1];
int kNumAddrs = 10;
NSMutableArray<NSString *> *addrs = [NSMutableArray arrayWithCapacity:kNumAddrs];
NSMutableArray<RMTTestService *> *services = [NSMutableArray arrayWithCapacity:kNumAddrs];
for (int i = 0; i < kNumAddrs; ++i) {
addrs[i] = [NSString stringWithFormat:@"127.0.0.%d", (i + 1)];
NSString *hostWithPort = [NSString stringWithFormat:@"%@:%@", addrs[i], port];
services[i] = [RMTTestService serviceWithHost:hostWithPort];
}
RMTSimpleRequest *request = [RMTSimpleRequest message];
request.responseSize = 0;
request.payload.body = [NSMutableData dataWithLength:0];
GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
options.transport = [[self class] transport];
options.PEMRootCertificates = [[self class] PEMRootCertificates];
options.hostNameOverride = [[self class] hostNameOverride];
// warm up
[self unaryRPCsWithServices:services
request:request
callsPerService:100
maxOutstandingCalls:100
callOptions:options];
[self measureBlock:^{
[self unaryRPCWithRequest:request numMessages:50 callOptions:options];
[self unaryRPCsWithServices:services
request:request
callsPerService:100
maxOutstandingCalls:100
callOptions:options];
}];
}

@ -41,6 +41,36 @@
<Test
Identifier = "PerfTests">
</Test>
<Test
Identifier = "PerfTestsCFStreamCleartext">
</Test>
<Test
Identifier = "PerfTestsCronet/testPingPongRPCWithFlowControl">
</Test>
<Test
Identifier = "PerfTestsCronet/testPingPongRPCWithInterceptor">
</Test>
<Test
Identifier = "PerfTestsCronet/testPingPongRPCWithV1API">
</Test>
<Test
Identifier = "PerfTestsNoCFStreamCleartext">
</Test>
<Test
Identifier = "PerfTestsNoCFStreamSSL">
</Test>
<Test
Identifier = "PerfTestsNoCFStreamSSL/testPingPongRPCWithFlowControl">
</Test>
<Test
Identifier = "PerfTestsNoCFStreamSSL/testPingPongRPCWithInterceptor">
</Test>
<Test
Identifier = "PerfTestsNoCFStreamSSL/testPingPongRPCWithV1API">
</Test>
<Test
Identifier = "TestBase">
</Test>
</SkippedTests>
</TestableReference>
</Testables>

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1010"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
</BuildAction>
<TestAction
buildConfiguration = "Test"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B0F2D0B9232991BA008C2575"
BuildableName = "PerfTests.xctest"
BlueprintName = "PerfTests"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
<SkippedTests>
<Test
Identifier = "PerfTests">
</Test>
<Test
Identifier = "PerfTestsCFStreamCleartext">
</Test>
<Test
Identifier = "PerfTestsCFStreamSSL">
</Test>
<Test
Identifier = "PerfTestsCronet">
</Test>
<Test
Identifier = "PerfTestsNoCFStreamCleartext">
</Test>
<Test
Identifier = "PerfTestsNoCFStreamSSL/testPingPongRPCWithFlowControl">
</Test>
<Test
Identifier = "PerfTestsNoCFStreamSSL/testPingPongRPCWithInterceptor">
</Test>
<Test
Identifier = "PerfTestsNoCFStreamSSL/testPingPongRPCWithV1API">
</Test>
<Test
Identifier = "TestBase">
</Test>
</SkippedTests>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

@ -43,7 +43,25 @@ TLS_PORT=$(curl localhost:32766/get)
$INTEROP --port=$PLAIN_PORT --max_send_message_size=8388608 &
$INTEROP --port=$TLS_PORT --max_send_message_size=8388608 --use_tls &
trap 'kill -9 `jobs -p` ; echo "EXIT TIME: $(date)"' EXIT
# Create loopback aliases for iOS performance tests
if [ $SCHEME == PerfTests ] || [ $SCHEME == PerfTestsPosix ]; then
for ((i=2;i<11;i++))
do
sudo ifconfig lo0 alias 127.0.0.$i up
done
fi
function finish {
if [ $SCHEME == PerfTests ] || [ $SCHEME == PerfTestsPosix ]; then
for ((i=2;i<11;i++))
do
sudo ifconfig lo0 -alias 127.0.0.$i
done
fi
kill -9 `jobs -p`
echo "EXIT TIME: $(date)"
}
trap finish EXIT
set -o pipefail
@ -59,6 +77,7 @@ elif [ $PLATFORM == tvos ]; then
DESTINATION='platform=tvOS Simulator,name=Apple TV'
fi
xcodebuild \
-workspace Tests.xcworkspace \
-scheme $SCHEME \
@ -70,3 +89,4 @@ xcodebuild \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -

@ -98,6 +98,21 @@ php_grpc_zend_object create_wrapped_grpc_channel(zend_class_entry *class_type
PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_channel, channel_ce_handlers);
}
static bool php_grpc_not_channel_arg_key(const char* key) {
static const char* ignoredKeys[] = {
"credentials",
"force_new",
"grpc_target_persist_bound",
};
for (int i = 0; i < sizeof(ignoredKeys) / sizeof(ignoredKeys[0]); i++) {
if (strcmp(key, ignoredKeys[i]) == 0) {
return true;
}
}
return false;
}
int php_grpc_read_args_array(zval *args_array,
grpc_channel_args *args TSRMLS_DC) {
HashTable *array_hash;
@ -108,8 +123,8 @@ int php_grpc_read_args_array(zval *args_array,
"array_hash is NULL", 1 TSRMLS_CC);
return FAILURE;
}
args->num_args = zend_hash_num_elements(array_hash);
args->args = ecalloc(args->num_args, sizeof(grpc_arg));
args->args = ecalloc(zend_hash_num_elements(array_hash), sizeof(grpc_arg));
args_index = 0;
char *key = NULL;
@ -122,6 +137,11 @@ int php_grpc_read_args_array(zval *args_array,
"args keys must be strings", 1 TSRMLS_CC);
return FAILURE;
}
if (php_grpc_not_channel_arg_key(key)) {
continue;
}
args->args[args_index].key = key;
switch (Z_TYPE_P(data)) {
case IS_LONG:
@ -139,6 +159,7 @@ int php_grpc_read_args_array(zval *args_array,
}
args_index++;
PHP_GRPC_HASH_FOREACH_END()
args->num_args = args_index;
return SUCCESS;
}
@ -322,7 +343,6 @@ PHP_METHOD(Channel, __construct) {
(void **)&creds_obj) == SUCCESS) {
if (Z_TYPE_P(creds_obj) == IS_NULL) {
creds = NULL;
php_grpc_zend_hash_del(array_hash, "credentials", sizeof("credentials"));
} else if (PHP_GRPC_GET_CLASS_ENTRY(creds_obj) !=
grpc_ce_channel_credentials) {
zend_throw_exception(spl_ce_InvalidArgumentException,
@ -333,7 +353,6 @@ PHP_METHOD(Channel, __construct) {
Z_ADDREF(*creds_obj);
creds = PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel_credentials,
creds_obj);
php_grpc_zend_hash_del(array_hash, "credentials", sizeof("credentials"));
}
}
if (php_grpc_zend_hash_find(array_hash, "force_new", sizeof("force_new"),
@ -341,7 +360,6 @@ PHP_METHOD(Channel, __construct) {
if (PHP_GRPC_BVAL_IS_TRUE(force_new_obj)) {
force_new = true;
}
php_grpc_zend_hash_del(array_hash, "force_new", sizeof("force_new"));
}
if (php_grpc_zend_hash_find(array_hash, "grpc_target_persist_bound",
@ -353,8 +371,6 @@ PHP_METHOD(Channel, __construct) {
1 TSRMLS_CC);
}
target_upper_bound = (int)Z_LVAL_P(force_new_obj);
php_grpc_zend_hash_del(array_hash, "grpc_target_persist_bound",
sizeof("grpc_target_persist_bound"));
}
// parse the rest of the channel args array
@ -366,18 +382,31 @@ PHP_METHOD(Channel, __construct) {
// Construct a hashkey for the persistent channel
// Currently, the hashkey contains 3 parts:
// 1. hostname
// 2. hash value of the channel args array (excluding "credentials"
// and "force_new")
// 2. hash value of the channel args (args_array excluding "credentials",
// "force_new" and "grpc_target_persist_bound")
// 3. (optional) hash value of the ChannelCredentials object
php_serialize_data_t var_hash;
smart_str buf = {0};
PHP_VAR_SERIALIZE_INIT(var_hash);
PHP_GRPC_VAR_SERIALIZE(&buf, args_array, &var_hash);
PHP_VAR_SERIALIZE_DESTROY(var_hash);
char sha1str[41];
generate_sha1_str(sha1str, PHP_GRPC_SERIALIZED_BUF_STR(buf),
PHP_GRPC_SERIALIZED_BUF_LEN(buf));
char sha1str[41] = { 0 };
unsigned char digest[20] = { 0 };
PHP_SHA1_CTX context;
PHP_SHA1Init(&context);
for (int i = 0; i < args.num_args; i++) {
PHP_GRPC_SHA1Update(&context, args.args[i].key, strlen(args.args[i].key) + 1);
switch (args.args[i].type) {
case GRPC_ARG_INTEGER:
PHP_GRPC_SHA1Update(&context, &args.args[i].value.integer, 4);
break;
case GRPC_ARG_STRING:
PHP_GRPC_SHA1Update(&context, args.args[i].value.string, strlen(args.args[i].value.string) + 1);
break;
default:
zend_throw_exception(spl_ce_InvalidArgumentException,
"args values must be int or string", 1 TSRMLS_CC);
return;
}
};
PHP_SHA1Final(digest, &context);
make_sha1_digest(sha1str, digest);
php_grpc_int key_len = target_length + strlen(sha1str);
if (creds != NULL && creds->hashstr != NULL) {
@ -405,7 +434,6 @@ PHP_METHOD(Channel, __construct) {
}
gpr_mu_init(&channel->wrapper->mu);
smart_str_free(&buf);
if (force_new || (creds != NULL && creds->has_call_creds)) {
// If the ChannelCredentials object was composed with a CallCredentials
// object, there is no way we can tell them apart. Do NOT persist

@ -47,7 +47,7 @@ function waitUntilNotIdle($channel) {
}
// Set up
$channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$channel = new Grpc\Channel('localhost:50101', ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
// Test InsecureCredentials
assert('Grpc\Channel' == get_class($channel));
@ -56,28 +56,16 @@ assert('Grpc\Channel' == get_class($channel));
$state = $channel->getConnectivityState();
assert(0 == $state);
// Test GetConnectivityStateWithInt
$state = $channel->getConnectivityState(123);
assert(0 == $state);
// Test GetConnectivityStateWithString
$state = $channel->getConnectivityState('hello');
assert(0 == $state);
// Test GetConnectivityStateWithBool
$state = $channel->getConnectivityState(true);
assert(0 == $state);
$channel->close();
// Test GetTarget
$channel = new Grpc\Channel('localhost:8888', ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$channel = new Grpc\Channel('localhost:50102', ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$target = $channel->getTarget();
assert(is_string($target) == true);
$channel->close();
// Test WatchConnectivityState
$channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$channel = new Grpc\Channel('localhost:50103', ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
$now = Grpc\Timeval::now();
$deadline = $now->add(new Grpc\Timeval(100*1000));

@ -149,14 +149,16 @@
include(cmake/msvc_static_runtime.cmake)
add_definitions(-D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS)
# needed to compile protobuf
add_definitions(/wd4065 /wd4506)
set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /wd4065 /wd4506")
# TODO(jtattermusch): revisit warnings that were silenced as part of upgrade to protobuf3.6.0
add_definitions(/wd4200 /wd4291 /wd4244)
set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /wd4200 /wd4291 /wd4244")
# TODO(jtattermusch): revisit C4267 occurrences throughout the code
add_definitions(/wd4267)
set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /wd4267")
# TODO(jtattermusch): needed to build boringssl with VS2017, revisit later
add_definitions(/wd4987 /wd4774 /wd4819 /wd4996 /wd4619)
set(_gRPC_C_CXX_FLAGS "<%text>${_gRPC_C_CXX_FLAGS}</%text> /wd4987 /wd4774 /wd4819 /wd4996 /wd4619")
endif()
set(CMAKE_C_FLAGS "<%text>${CMAKE_C_FLAGS} ${_gRPC_C_CXX_FLAGS}</%text>")
set(CMAKE_CXX_FLAGS "<%text>${CMAKE_CXX_FLAGS} ${_gRPC_C_CXX_FLAGS}</%text>")
if (gRPC_USE_PROTO_LITE)
set(_gRPC_PROTOBUF_LIBRARY_NAME "libprotobuf-lite")

@ -12,7 +12,7 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
<date>2018-01-19</date>
<date>2019-09-24</date>
<time>16:06:07</time>
<version>
<release>${settings.php_version.php()}</release>
@ -24,7 +24,7 @@
</stability>
<license>Apache 2.0</license>
<notes>
- TBD
- gRPC Core ${settings.php_version.php_composer()} update
</notes>
<contents>
<dir baseinstalldir="/" name="/">

@ -39,4 +39,6 @@
ln -s $(pwd)/.dotnet/dotnet /usr/local/bin/dotnet
fi
dotnet build --configuration Debug Grpc.DotNet.sln
# Cloning from a local path sets RepositoryUrl to a path and breaks Source Link.
# Override RepositoryUrl to a URL to fix Source Link. The value doesn't matter.
dotnet build --configuration Debug Grpc.DotNet.sln -p:RepositoryUrl=https://github.com/grpc/grpc-dotnet.git

@ -16,43 +16,38 @@
*
*/
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/impl/codegen/log.h>
#include <string.h>
#include <grpc/support/log.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/surface/channel.h"
#include "test/core/util/test_config.h"
static void test_create(void) {
grpc_core::ExecCtx exec_ctx;
grpc_arg arg_int;
grpc_arg arg_string;
grpc_arg to_add[2];
grpc_channel_args* ch_args;
arg_int.key = const_cast<char*>("int_arg");
arg_int.type = GRPC_ARG_INTEGER;
arg_int.value.integer = 123;
arg_string.key = const_cast<char*>("str key");
arg_string.type = GRPC_ARG_STRING;
arg_string.value.string = const_cast<char*>("str value");
to_add[0] = arg_int;
to_add[1] = arg_string;
to_add[0] =
grpc_channel_arg_integer_create(const_cast<char*>("int_arg"), 123);
to_add[1] = grpc_channel_arg_string_create(const_cast<char*>("str key"),
const_cast<char*>("str value"));
ch_args = grpc_channel_args_copy_and_add(nullptr, to_add, 2);
GPR_ASSERT(ch_args->num_args == 2);
GPR_ASSERT(strcmp(ch_args->args[0].key, arg_int.key) == 0);
GPR_ASSERT(ch_args->args[0].type == arg_int.type);
GPR_ASSERT(ch_args->args[0].value.integer == arg_int.value.integer);
GPR_ASSERT(strcmp(ch_args->args[0].key, to_add[0].key) == 0);
GPR_ASSERT(ch_args->args[0].type == to_add[0].type);
GPR_ASSERT(ch_args->args[0].value.integer == to_add[0].value.integer);
GPR_ASSERT(strcmp(ch_args->args[1].key, arg_string.key) == 0);
GPR_ASSERT(ch_args->args[1].type == arg_string.type);
GPR_ASSERT(strcmp(ch_args->args[1].value.string, arg_string.value.string) ==
GPR_ASSERT(strcmp(ch_args->args[1].key, to_add[1].key) == 0);
GPR_ASSERT(ch_args->args[1].type == to_add[1].type);
GPR_ASSERT(strcmp(ch_args->args[1].value.string, to_add[1].value.string) ==
0);
grpc_channel_args_destroy(ch_args);
@ -84,23 +79,15 @@ static const grpc_arg_pointer_vtable fake_pointer_arg_vtable = {
static void test_channel_create_with_args(void) {
grpc_arg client_a[3];
// adds integer arg
client_a[0].type = GRPC_ARG_INTEGER;
client_a[0].key = const_cast<char*>("arg_int");
client_a[0].value.integer = 0;
// adds const str arg
client_a[1].type = GRPC_ARG_STRING;
client_a[1].key = const_cast<char*>("arg_str");
client_a[1].value.string = const_cast<char*>("arg_str_val");
client_a[0] =
grpc_channel_arg_integer_create(const_cast<char*>("arg_int"), 0);
client_a[1] = grpc_channel_arg_string_create(
const_cast<char*>("arg_str"), const_cast<char*>("arg_str_val"));
// allocated and adds custom pointer arg
fake_class* fc = static_cast<fake_class*>(gpr_malloc(sizeof(fake_class)));
fc->foo = 42;
client_a[2].type = GRPC_ARG_POINTER;
client_a[2].key = const_cast<char*>("arg_pointer");
client_a[2].value.pointer.vtable = &fake_pointer_arg_vtable;
client_a[2].value.pointer.p = fc;
client_a[2] = grpc_channel_arg_pointer_create(
const_cast<char*>("arg_pointer"), fc, &fake_pointer_arg_vtable);
// creates channel
grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
@ -111,6 +98,78 @@ static void test_channel_create_with_args(void) {
grpc_channel_destroy(c);
}
grpc_channel_args* mutate_channel_args(const char* target,
grpc_channel_args* old_args,
grpc_channel_stack_type type) {
GPR_ASSERT(old_args != nullptr);
GPR_ASSERT(grpc_channel_args_find(old_args, "arg_int")->value.integer == 0);
GPR_ASSERT(strcmp(grpc_channel_args_find(old_args, "arg_str")->value.string,
"arg_str_val") == 0);
GPR_ASSERT(
grpc_channel_args_find(old_args, "arg_pointer")->value.pointer.vtable ==
&fake_pointer_arg_vtable);
if (strcmp(target, "no_op_mutator") == 0) {
return old_args;
}
GPR_ASSERT(strcmp(target, "minimal_stack_mutator") == 0);
const char* args_to_remove[] = {"arg_int", "arg_str", "arg_pointer"};
grpc_arg no_deadline_filter_arg = grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_MINIMAL_STACK), 1);
grpc_channel_args* new_args = nullptr;
new_args = grpc_channel_args_copy_and_add_and_remove(
old_args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove),
&no_deadline_filter_arg, 1);
grpc_channel_args_destroy(old_args);
return new_args;
}
// Minimal stack should not have client_idle filter
static bool channel_has_client_idle_filter(grpc_channel* c) {
grpc_channel_stack* stack = grpc_channel_get_channel_stack(c);
for (size_t i = 0; i < stack->count; i++) {
if (strcmp(grpc_channel_stack_element(stack, i)->filter->name,
"client_idle") == 0) {
return true;
}
}
return false;
}
static void test_channel_create_with_global_mutator(void) {
grpc_channel_args_set_client_channel_creation_mutator(mutate_channel_args);
// We also add some custom args to make sure the ownership is correct.
grpc_arg client_a[3];
client_a[0] =
grpc_channel_arg_integer_create(const_cast<char*>("arg_int"), 0);
client_a[1] = grpc_channel_arg_string_create(
const_cast<char*>("arg_str"), const_cast<char*>("arg_str_val"));
// allocated and adds custom pointer arg
fake_class* fc = static_cast<fake_class*>(gpr_malloc(sizeof(fake_class)));
fc->foo = 42;
client_a[2] = grpc_channel_arg_pointer_create(
const_cast<char*>("arg_pointer"), fc, &fake_pointer_arg_vtable);
// creates channels
grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a};
grpc_channel* c =
grpc_insecure_channel_create("no_op_mutator", &client_args, nullptr);
GPR_ASSERT(channel_has_client_idle_filter(c));
grpc_channel_destroy(c);
c = grpc_insecure_channel_create("minimal_stack_mutator", &client_args,
nullptr);
GPR_ASSERT(channel_has_client_idle_filter(c) == false);
grpc_channel_destroy(c);
gpr_free(fc);
auto mutator = grpc_channel_args_get_client_channel_creation_mutator();
GPR_ASSERT(mutator == &mutate_channel_args);
}
static void test_server_create_with_args(void) {
grpc_arg server_a[3];
@ -146,6 +205,8 @@ int main(int argc, char** argv) {
test_create();
test_channel_create_with_args();
test_server_create_with_args();
// This has to be the last test.
test_channel_create_with_global_mutator();
grpc_shutdown();
return 0;
}

@ -533,8 +533,8 @@ TEST_F(ChannelzRegistryBasedTest, ManyServersTest) {
ValidateGetServers(10);
}
INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest,
::testing::Values(0, 8, 64, 1024, 1024 * 1024));
INSTANTIATE_TEST_SUITE_P(ChannelzChannelTestSweep, ChannelzChannelTest,
::testing::Values(0, 8, 64, 1024, 1024 * 1024));
} // namespace testing
} // namespace channelz

@ -921,10 +921,7 @@ TEST_F(ClientChannelParserTest, InvalidHealthCheckMultipleEntries) {
"error)(.*)(referenced_errors)(.*)(Global "
"Params)(.*)(referenced_errors)(.*)(field:healthCheckConfig "
"error:Duplicate entry)"));
std::smatch match;
std::string s(grpc_error_string(error));
EXPECT_TRUE(std::regex_search(s, match, e));
GRPC_ERROR_UNREF(error);
VerifyRegexMatch(error, e);
}
class MessageSizeParserTest : public ::testing::Test {
@ -1014,6 +1011,11 @@ TEST_F(MessageSizeParserTest, InvalidMaxResponseMessageBytes) {
} // namespace grpc_core
int main(int argc, char** argv) {
// Regexes don't work in gcc4.8 and below, so just skip testing in those cases
#if defined(__GNUC__) && \
((__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__) <= 8))
return 0;
#endif
grpc::testing::TestEnvironment env(argc, argv);
grpc_init();
::testing::InitGoogleTest(&argc, argv);

@ -135,8 +135,8 @@ TEST_P(HistogramTest, IncHistogram) {
}
}
INSTANTIATE_TEST_CASE_P(HistogramTestCases, HistogramTest,
::testing::Range<int>(0, GRPC_STATS_HISTOGRAM_COUNT));
INSTANTIATE_TEST_SUITE_P(HistogramTestCases, HistogramTest,
::testing::Range<int>(0, GRPC_STATS_HISTOGRAM_COUNT));
} // namespace testing
} // namespace grpc

@ -57,9 +57,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
grpc_server* server = grpc_server_create(nullptr, nullptr);
grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
grpc_server_register_completion_queue(server, cq, nullptr);
// TODO(ctiller): add registered methods (one for POST, one for PUT)
// void *registered_method =
// grpc_server_register_method(server, "/reg", NULL, 0);
// TODO(ctiller): add more registered methods (one for POST, one for PUT)
grpc_server_register_method(server, "/reg", nullptr, {}, 0);
grpc_server_start(server);
grpc_transport* transport =
grpc_create_chttp2_transport(nullptr, mock_endpoint, false);

@ -346,7 +346,8 @@ TEST_P(H2SslCertTest, SimpleRequestBody) {
simple_request_body(fixture_, GetParam().result);
}
INSTANTIATE_TEST_CASE_P(H2SslCert, H2SslCertTest, ::testing::ValuesIn(configs));
INSTANTIATE_TEST_SUITE_P(H2SslCert, H2SslCertTest,
::testing::ValuesIn(configs));
} // namespace testing
} // namespace grpc

@ -127,6 +127,24 @@ TEST(InlinedVectorTest, EqualOperator) {
EXPECT_FALSE(v1 == v2);
}
TEST(InlinedVectorTest, NotEqualOperator) {
constexpr int kNumElements = 10;
// Both v1 and v2 are empty.
InlinedVector<int, 5> v1;
InlinedVector<int, 5> v2;
EXPECT_FALSE(v1 != v2);
// Both v1 and v2 contains the same data.
FillVector(&v1, kNumElements);
FillVector(&v2, kNumElements);
EXPECT_FALSE(v1 != v2);
// The sizes of v1 and v2 are different.
v1.push_back(0);
EXPECT_TRUE(v1 != v2);
// The contents of v1 and v2 are different although their sizes are the same.
v2.push_back(1);
EXPECT_TRUE(v1 != v2);
}
// the following constants and typedefs are used for copy/move
// construction/assignment
const size_t kInlinedLength = 8;

@ -28,31 +28,27 @@
#include "test/core/end2end/cq_verifier.h"
#include "test/core/util/test_config.h"
grpc_closure transport_op_cb;
class Watcher : public grpc_core::ConnectivityStateWatcherInterface {
public:
void Notify(grpc_connectivity_state new_state) override {
GPR_ASSERT(new_state == GRPC_CHANNEL_SHUTDOWN);
}
};
static void* tag(intptr_t x) { return (void*)x; }
void verify_connectivity(void* arg, grpc_error* error) {
grpc_connectivity_state* state = static_cast<grpc_connectivity_state*>(arg);
GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN == *state);
GPR_ASSERT(error == GRPC_ERROR_NONE);
}
static grpc_closure transport_op_cb;
void do_nothing(void* arg, grpc_error* error) {}
static void do_nothing(void* arg, grpc_error* error) {}
void test_transport_op(grpc_channel* channel) {
grpc_transport_op* op;
grpc_channel_element* elem;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
grpc_core::ExecCtx exec_ctx;
GRPC_CLOSURE_INIT(&transport_op_cb, verify_connectivity, &state,
grpc_schedule_on_exec_ctx);
op = grpc_make_transport_op(nullptr);
op->on_connectivity_state_change = &transport_op_cb;
op->connectivity_state = &state;
elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->start_connectivity_watch =
grpc_core::OrphanablePtr<grpc_core::ConnectivityStateWatcherInterface>(
grpc_core::New<Watcher>());
grpc_channel_element* elem =
grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0);
elem->filter->start_transport_op(elem, op);
GRPC_CLOSURE_INIT(&transport_op_cb, do_nothing, nullptr,

@ -49,6 +49,9 @@ grpc_cc_test(
grpc_cc_test(
name = "connectivity_state_test",
srcs = ["connectivity_state_test.cc"],
external_deps = [
"gtest",
],
language = "C++",
deps = [
"//:gpr",

@ -131,9 +131,9 @@ TEST_P(BdpEstimatorRandomTest, GetEstimateRandomValues) {
}
}
INSTANTIATE_TEST_CASE_P(TooManyNames, BdpEstimatorRandomTest,
::testing::Values(3, 4, 6, 9, 13, 19, 28, 42, 63, 94,
141, 211, 316, 474, 711));
INSTANTIATE_TEST_SUITE_P(TooManyNames, BdpEstimatorRandomTest,
::testing::Values(3, 4, 6, 9, 13, 19, 28, 42, 63, 94,
141, 211, 316, 474, 711));
} // namespace testing
} // namespace grpc_core

@ -20,124 +20,146 @@
#include <string.h>
#include <gtest/gtest.h>
#include <grpc/support/log.h>
#include "src/core/lib/iomgr/exec_ctx.h"
#include "test/core/util/test_config.h"
#include "test/core/util/tracer_util.h"
#define THE_ARG ((void*)(size_t)0xcafebabe)
int g_counter;
namespace grpc_core {
namespace {
static void must_succeed(void* arg, grpc_error* error) {
GPR_ASSERT(error == GRPC_ERROR_NONE);
GPR_ASSERT(arg == THE_ARG);
g_counter++;
TEST(ConnectivityStateName, Basic) {
EXPECT_STREQ("IDLE", ConnectivityStateName(GRPC_CHANNEL_IDLE));
EXPECT_STREQ("CONNECTING", ConnectivityStateName(GRPC_CHANNEL_CONNECTING));
EXPECT_STREQ("READY", ConnectivityStateName(GRPC_CHANNEL_READY));
EXPECT_STREQ("TRANSIENT_FAILURE",
ConnectivityStateName(GRPC_CHANNEL_TRANSIENT_FAILURE));
EXPECT_STREQ("SHUTDOWN", ConnectivityStateName(GRPC_CHANNEL_SHUTDOWN));
}
static void must_fail(void* arg, grpc_error* error) {
GPR_ASSERT(error != GRPC_ERROR_NONE);
GPR_ASSERT(arg == THE_ARG);
g_counter++;
class Watcher : public ConnectivityStateWatcherInterface {
public:
Watcher(int* count, grpc_connectivity_state* output,
bool* destroyed = nullptr)
: count_(count), output_(output), destroyed_(destroyed) {}
~Watcher() {
if (destroyed_ != nullptr) *destroyed_ = true;
}
void Notify(grpc_connectivity_state new_state) override {
++*count_;
*output_ = new_state;
}
private:
int* count_;
grpc_connectivity_state* output_;
bool* destroyed_;
};
TEST(StateTracker, SetAndGetState) {
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING);
EXPECT_EQ(tracker.state(), GRPC_CHANNEL_CONNECTING);
tracker.SetState(GRPC_CHANNEL_READY, "whee");
EXPECT_EQ(tracker.state(), GRPC_CHANNEL_READY);
}
static void test_connectivity_state_name(void) {
gpr_log(GPR_DEBUG, "test_connectivity_state_name");
GPR_ASSERT(0 ==
strcmp(grpc_connectivity_state_name(GRPC_CHANNEL_IDLE), "IDLE"));
GPR_ASSERT(0 == strcmp(grpc_connectivity_state_name(GRPC_CHANNEL_CONNECTING),
"CONNECTING"));
GPR_ASSERT(0 ==
strcmp(grpc_connectivity_state_name(GRPC_CHANNEL_READY), "READY"));
GPR_ASSERT(
0 == strcmp(grpc_connectivity_state_name(GRPC_CHANNEL_TRANSIENT_FAILURE),
"TRANSIENT_FAILURE"));
GPR_ASSERT(0 == strcmp(grpc_connectivity_state_name(GRPC_CHANNEL_SHUTDOWN),
"SHUTDOWN"));
TEST(StateTracker, NotificationUponAddingWatcher) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_CONNECTING);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
OrphanablePtr<ConnectivityStateWatcherInterface>(
New<Watcher>(&count, &state)));
EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_CONNECTING);
}
static void test_check(void) {
grpc_connectivity_state_tracker tracker;
grpc_core::ExecCtx exec_ctx;
gpr_log(GPR_DEBUG, "test_check");
grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_IDLE, "xxx");
GPR_ASSERT(grpc_connectivity_state_check(&tracker) == GRPC_CHANNEL_IDLE);
grpc_connectivity_state_destroy(&tracker);
TEST(StateTracker, NotificationUponStateChange) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
OrphanablePtr<ConnectivityStateWatcherInterface>(
New<Watcher>(&count, &state)));
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
tracker.SetState(GRPC_CHANNEL_CONNECTING, "whee");
EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_CONNECTING);
}
static void test_subscribe_then_unsubscribe(void) {
grpc_connectivity_state_tracker tracker;
grpc_closure* closure =
GRPC_CLOSURE_CREATE(must_fail, THE_ARG, grpc_schedule_on_exec_ctx);
TEST(StateTracker, SubscribeThenUnsubscribe) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
grpc_core::ExecCtx exec_ctx;
gpr_log(GPR_DEBUG, "test_subscribe_then_unsubscribe");
g_counter = 0;
grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_IDLE, "xxx");
GPR_ASSERT(grpc_connectivity_state_notify_on_state_change(&tracker, &state,
closure));
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(state == GRPC_CHANNEL_IDLE);
GPR_ASSERT(g_counter == 0);
grpc_connectivity_state_notify_on_state_change(&tracker, nullptr, closure);
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(state == GRPC_CHANNEL_IDLE);
GPR_ASSERT(g_counter == 1);
grpc_connectivity_state_destroy(&tracker);
bool destroyed = false;
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
ConnectivityStateWatcherInterface* watcher =
New<Watcher>(&count, &state, &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);
// Cancel watch. This should not generate another notification.
tracker.RemoveWatcher(watcher);
EXPECT_TRUE(destroyed);
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
}
static void test_subscribe_then_destroy(void) {
grpc_connectivity_state_tracker tracker;
grpc_closure* closure =
GRPC_CLOSURE_CREATE(must_succeed, THE_ARG, grpc_schedule_on_exec_ctx);
TEST(StateTracker, NotifyShutdownAtDestruction) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
grpc_core::ExecCtx exec_ctx;
gpr_log(GPR_DEBUG, "test_subscribe_then_destroy");
g_counter = 0;
grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_IDLE, "xxx");
GPR_ASSERT(grpc_connectivity_state_notify_on_state_change(&tracker, &state,
closure));
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(state == GRPC_CHANNEL_IDLE);
GPR_ASSERT(g_counter == 0);
grpc_connectivity_state_destroy(&tracker);
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(state == GRPC_CHANNEL_SHUTDOWN);
GPR_ASSERT(g_counter == 1);
{
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_IDLE);
tracker.AddWatcher(GRPC_CHANNEL_IDLE,
OrphanablePtr<ConnectivityStateWatcherInterface>(
New<Watcher>(&count, &state)));
// No initial notification, since we started the watch from the
// current state.
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_IDLE);
}
// Upon tracker destruction, we get a notification for SHUTDOWN.
EXPECT_EQ(count, 1);
EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
}
static void test_subscribe_with_failure_then_destroy(void) {
grpc_connectivity_state_tracker tracker;
grpc_closure* closure =
GRPC_CLOSURE_CREATE(must_fail, THE_ARG, grpc_schedule_on_exec_ctx);
TEST(StateTracker, DoNotNotifyShutdownAtDestructionIfAlreadyInShutdown) {
int count = 0;
grpc_connectivity_state state = GRPC_CHANNEL_SHUTDOWN;
grpc_core::ExecCtx exec_ctx;
gpr_log(GPR_DEBUG, "test_subscribe_with_failure_then_destroy");
g_counter = 0;
grpc_connectivity_state_init(&tracker, GRPC_CHANNEL_SHUTDOWN, "xxx");
GPR_ASSERT(0 == grpc_connectivity_state_notify_on_state_change(
&tracker, &state, closure));
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(state == GRPC_CHANNEL_SHUTDOWN);
GPR_ASSERT(g_counter == 0);
grpc_connectivity_state_destroy(&tracker);
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(state == GRPC_CHANNEL_SHUTDOWN);
GPR_ASSERT(g_counter == 1);
{
ConnectivityStateTracker tracker("xxx", GRPC_CHANNEL_SHUTDOWN);
tracker.AddWatcher(GRPC_CHANNEL_SHUTDOWN,
OrphanablePtr<ConnectivityStateWatcherInterface>(
New<Watcher>(&count, &state)));
// No initial notification, since we started the watch from the
// current state.
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
}
// No additional notification upon tracker destruction, since we were
// already in state SHUTDOWN.
EXPECT_EQ(count, 0);
EXPECT_EQ(state, GRPC_CHANNEL_SHUTDOWN);
}
} // namespace
} // namespace grpc_core
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
grpc_init();
grpc_core::testing::grpc_tracer_enable_flag(&grpc_connectivity_state_trace);
test_connectivity_state_name();
test_check();
test_subscribe_then_unsubscribe();
test_subscribe_then_destroy();
test_subscribe_with_failure_then_destroy();
grpc_core::testing::grpc_tracer_enable_flag(
&grpc_core::grpc_connectivity_state_trace);
::testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
grpc_shutdown();
return 0;
return ret;
}

@ -75,7 +75,7 @@ TEST_P(SimpleConvergenceTest, Converges) {
}
}
INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_SUITE_P(
X, SimpleConvergenceTest,
::testing::Values(SimpleConvergenceTestArgs{0.2, 0, 0, 1, 100, 0},
SimpleConvergenceTestArgs{0.2, 0.1, 0, 1, 100, 0},

@ -109,15 +109,22 @@ alts_zero_copy_grpc_protector_test_fixture_create(bool rekey,
size_t key_length = rekey ? kAes128GcmRekeyKeyLength : kAes128GcmKeyLength;
uint8_t* key;
size_t max_protected_frame_size = 1024;
size_t actual_max_protected_frame_size;
gsec_test_random_array(&key, key_length);
GPR_ASSERT(alts_zero_copy_grpc_protector_create(
key, key_length, rekey, /*is_client=*/true, integrity_only,
enable_extra_copy, &max_protected_frame_size,
&fixture->client) == TSI_OK);
GPR_ASSERT(tsi_zero_copy_grpc_protector_max_frame_size(
fixture->client, actual_max_protected_frame_size) == TSI_OK);
GPR_ASSERT(actual_max_protected_frame_size == max_protected_frame_size);
GPR_ASSERT(alts_zero_copy_grpc_protector_create(
key, key_length, rekey, /*is_client=*/false, integrity_only,
enable_extra_copy, &max_protected_frame_size,
&fixture->server) == TSI_OK);
GPR_ASSERT(tsi_zero_copy_grpc_protector_max_frame_size(
fixture->server, actual_max_protected_frame_size) == TSI_OK);
GPR_ASSERT(actual_max_protected_frame_size == max_protected_frame_size);
gpr_free(key);
grpc_core::ExecCtx::Get()->Flush();
return fixture;

@ -140,7 +140,7 @@ ExampleGenerator::End() const {
return new ExampleIterator(*this, examples_.end());
}
INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_SUITE_P(
CorpusExamples, FuzzerCorpusTest,
::testing::internal::ParamGenerator<std::string>(new ExampleGenerator));

@ -22,3 +22,7 @@ signed-integer-overflow:chrono
enum:grpc_http2_error_to_grpc_status
enum:grpc_chttp2_cancel_stream
enum:api_fuzzer
# TODO(juanlishen): Remove this supression after
# https://github.com/GoogleCloudPlatform/layer-definitions/issues/531 is
# addressed.
alignment:grpc_core::XdsPriorityListUpdate::*

@ -75,8 +75,8 @@ class TimeJumpTest : public ::testing::TestWithParam<std::string> {
std::vector<std::string> CreateTestScenarios() {
return {"-1M", "+1M", "-1H", "+1H", "-1d", "+1d", "-1y", "+1y"};
}
INSTANTIATE_TEST_CASE_P(TimeJump, TimeJumpTest,
::testing::ValuesIn(CreateTestScenarios()));
INSTANTIATE_TEST_SUITE_P(TimeJump, TimeJumpTest,
::testing::ValuesIn(CreateTestScenarios()));
TEST_P(TimeJumpTest, TimerRunning) {
grpc_core::ExecCtx exec_ctx;

@ -1875,11 +1875,12 @@ std::vector<TestScenario> CreateTestScenarios(bool test_secure,
return scenarios;
}
INSTANTIATE_TEST_CASE_P(AsyncEnd2end, AsyncEnd2endTest,
::testing::ValuesIn(CreateTestScenarios(true, true)));
INSTANTIATE_TEST_CASE_P(AsyncEnd2endServerTryCancel,
AsyncEnd2endServerTryCancelTest,
::testing::ValuesIn(CreateTestScenarios(false, false)));
INSTANTIATE_TEST_SUITE_P(AsyncEnd2end, AsyncEnd2endTest,
::testing::ValuesIn(CreateTestScenarios(true, true)));
INSTANTIATE_TEST_SUITE_P(AsyncEnd2endServerTryCancel,
AsyncEnd2endServerTryCancelTest,
::testing::ValuesIn(CreateTestScenarios(false,
false)));
} // namespace
} // namespace testing

@ -324,8 +324,8 @@ std::vector<TestScenario> CreateTestScenarios() {
return scenarios;
}
INSTANTIATE_TEST_CASE_P(CFStreamTest, CFStreamTest,
::testing::ValuesIn(CreateTestScenarios()));
INSTANTIATE_TEST_SUITE_P(CFStreamTest, CFStreamTest,
::testing::ValuesIn(CreateTestScenarios()));
// gRPC should automatically detech network flaps (without enabling keepalives)
// when CFStream is enabled

@ -1375,8 +1375,8 @@ std::vector<TestScenario> CreateTestScenarios(bool test_insecure) {
return scenarios;
}
INSTANTIATE_TEST_CASE_P(ClientCallbackEnd2endTest, ClientCallbackEnd2endTest,
::testing::ValuesIn(CreateTestScenarios(true)));
INSTANTIATE_TEST_SUITE_P(ClientCallbackEnd2endTest, ClientCallbackEnd2endTest,
::testing::ValuesIn(CreateTestScenarios(true)));
} // namespace
} // namespace testing

@ -2251,23 +2251,23 @@ std::vector<TestScenario> CreateTestScenarios(bool use_proxy,
return scenarios;
}
INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_SUITE_P(
End2end, End2endTest,
::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true)));
INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_SUITE_P(
End2endServerTryCancel, End2endServerTryCancelTest,
::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true)));
INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_SUITE_P(
ProxyEnd2end, ProxyEnd2endTest,
::testing::ValuesIn(CreateTestScenarios(true, true, true, true, true)));
INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_SUITE_P(
SecureEnd2end, SecureEnd2endTest,
::testing::ValuesIn(CreateTestScenarios(false, false, true, false, true)));
INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_SUITE_P(
ResourceQuotaEnd2end, ResourceQuotaEnd2endTest,
::testing::ValuesIn(CreateTestScenarios(false, true, true, true, true)));

@ -344,8 +344,8 @@ std::vector<TestScenario> CreateTestScenarios() {
return scenarios;
}
INSTANTIATE_TEST_CASE_P(FlakyNetworkTest, FlakyNetworkTest,
::testing::ValuesIn(CreateTestScenarios()));
INSTANTIATE_TEST_SUITE_P(FlakyNetworkTest, FlakyNetworkTest,
::testing::ValuesIn(CreateTestScenarios()));
// Network interface connected to server flaps
TEST_P(FlakyNetworkTest, NetworkTransition) {

@ -962,8 +962,8 @@ TEST_F(HybridEnd2endTest, GenericMethodWithoutGenericService) {
EXPECT_EQ(nullptr, server_.get());
}
INSTANTIATE_TEST_CASE_P(HybridEnd2endTest, HybridEnd2endTest,
::testing::Bool());
INSTANTIATE_TEST_SUITE_P(HybridEnd2endTest, HybridEnd2endTest,
::testing::Bool());
} // namespace
} // namespace testing

@ -400,12 +400,12 @@ std::vector<TestScenario> CreateTestScenarios(bool test_insecure) {
return scenarios;
}
INSTANTIATE_TEST_CASE_P(NullAllocatorTest, NullAllocatorTest,
::testing::ValuesIn(CreateTestScenarios(true)));
INSTANTIATE_TEST_CASE_P(SimpleAllocatorTest, SimpleAllocatorTest,
::testing::ValuesIn(CreateTestScenarios(true)));
INSTANTIATE_TEST_CASE_P(ArenaAllocatorTest, ArenaAllocatorTest,
::testing::ValuesIn(CreateTestScenarios(true)));
INSTANTIATE_TEST_SUITE_P(NullAllocatorTest, NullAllocatorTest,
::testing::ValuesIn(CreateTestScenarios(true)));
INSTANTIATE_TEST_SUITE_P(SimpleAllocatorTest, SimpleAllocatorTest,
::testing::ValuesIn(CreateTestScenarios(true)));
INSTANTIATE_TEST_SUITE_P(ArenaAllocatorTest, ArenaAllocatorTest,
::testing::ValuesIn(CreateTestScenarios(true)));
} // namespace
} // namespace testing

@ -359,8 +359,8 @@ TEST_P(PortSharingEnd2endTest, TwoHandoffPorts) {
}
}
INSTANTIATE_TEST_CASE_P(PortSharingEnd2end, PortSharingEnd2endTest,
::testing::ValuesIn(CreateTestScenarios()));
INSTANTIATE_TEST_SUITE_P(PortSharingEnd2end, PortSharingEnd2endTest,
::testing::ValuesIn(CreateTestScenarios()));
} // namespace
} // namespace testing

@ -257,8 +257,8 @@ TEST_P(ServerBuilderPluginTest, PluginWithServiceTest) {
EXPECT_TRUE(s.ok());
}
INSTANTIATE_TEST_CASE_P(ServerBuilderPluginTest, ServerBuilderPluginTest,
::testing::Values(false, true));
INSTANTIATE_TEST_SUITE_P(ServerBuilderPluginTest, ServerBuilderPluginTest,
::testing::Values(false, true));
} // namespace testing
} // namespace grpc

@ -136,8 +136,8 @@ std::vector<string> GetAllCredentialsTypeList() {
return credentials_types;
}
INSTANTIATE_TEST_CASE_P(End2EndShutdown, ShutdownTest,
::testing::ValuesIn(GetAllCredentialsTypeList()));
INSTANTIATE_TEST_SUITE_P(End2EndShutdown, ShutdownTest,
::testing::ValuesIn(GetAllCredentialsTypeList()));
// TODO(ctiller): leaked objects in this test
TEST_P(ShutdownTest, ShutdownTest) {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save