Merge remote-tracking branch 'upstream/master' into cares_rebase

pull/7771/head
Yuchen Zeng 8 years ago
commit 937302b0df
  1. 6
      BUILD
  2. 92
      CMakeLists.txt
  3. 97
      Makefile
  4. 4
      binding.gyp
  5. 40
      build.yaml
  6. 4
      config.m4
  7. 158
      doc/combiner-explainer.md
  8. 160
      doc/core/grpc-error.md
  9. 9
      examples/node/static_codegen/README.md
  10. 8
      gRPC-Core.podspec
  11. 6
      grpc.gemspec
  12. 4
      include/grpc++/support/channel_arguments.h
  13. 5
      include/grpc/impl/codegen/atm.h
  14. 6
      package.xml
  15. 3
      setup.py
  16. 123
      src/core/ext/client_channel/client_channel.c
  17. 3
      src/core/ext/client_channel/client_channel_plugin.c
  18. 2
      src/core/ext/client_channel/connector.h
  19. 50
      src/core/ext/client_channel/initial_connect_string.h
  20. 210
      src/core/ext/client_channel/retry_throttle.c
  21. 43
      src/core/ext/client_channel/retry_throttle.h
  22. 7
      src/core/ext/client_channel/subchannel.c
  23. 6
      src/core/ext/lb_policy/pick_first/pick_first.c
  24. 6
      src/core/ext/lb_policy/round_robin/round_robin.c
  25. 37
      src/core/ext/transport/chttp2/client/chttp2_connector.c
  26. 24
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  27. 17
      src/core/ext/transport/chttp2/transport/hpack_parser.c
  28. 65
      src/core/ext/transport/cronet/transport/cronet_transport.c
  29. 4
      src/core/lib/iomgr/closure.c
  30. 2
      src/core/lib/iomgr/combiner.c
  31. 25
      src/core/lib/iomgr/error.h
  32. 2
      src/core/lib/iomgr/ev_poll_posix.c
  33. 4
      src/core/lib/iomgr/executor.c
  34. 16
      src/core/lib/iomgr/tcp_server_posix.c
  35. 2
      src/core/lib/profiling/basic_timers.c
  36. 19
      src/core/lib/support/atm.c
  37. 12
      src/core/lib/transport/service_config.c
  38. 6
      src/core/lib/transport/service_config.h
  39. 3
      src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m
  40. 4
      src/python/grpcio/grpc_core_dependencies.py
  41. 8
      src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py
  42. 8
      src/python/grpcio_tests/tests/interop/_secure_intraop_test.py
  43. 4
      src/python/grpcio_tests/tests/interop/methods.py
  44. 5
      src/python/grpcio_tests/tests/interop/server.py
  45. 4
      src/python/grpcio_tests/tests/qps/qps_worker.py
  46. 8
      src/python/grpcio_tests/tests/qps/worker_server.py
  47. 7
      src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py
  48. 4
      src/python/grpcio_tests/tests/stress/client.py
  49. 7
      test/core/client_channel/BUILD
  50. 268
      test/core/client_channel/set_initial_connect_string_test.c
  51. BIN
      test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6723650944237568
  52. BIN
      test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112
  53. 587
      test/cpp/microbenchmarks/bm_chttp2_transport.cc
  54. 4
      test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
  55. 2
      tools/buildgen/plugins/make_fuzzer_tests.py
  56. 1
      tools/doxygen/Doxyfile.c++
  57. 1
      tools/doxygen/Doxyfile.c++.internal
  58. 2
      tools/doxygen/Doxyfile.core
  59. 8
      tools/doxygen/Doxyfile.core.internal
  60. 12
      tools/profiling/microbenchmarks/bm_json.py
  61. 47
      tools/run_tests/generated/sources_and_headers.json
  62. 5026
      tools/run_tests/generated/tests.json
  63. 2
      tools/run_tests/run_microbenchmark.py
  64. 28
      vsprojects/buildtests_c.sln
  65. 2
      vsprojects/vcxproj/gpr/gpr.vcxproj
  66. 3
      vsprojects/vcxproj/gpr/gpr.vcxproj.filters
  67. 8
      vsprojects/vcxproj/grpc/grpc.vcxproj
  68. 15
      vsprojects/vcxproj/grpc/grpc.vcxproj.filters
  69. 8
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
  70. 15
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
  71. 202
      vsprojects/vcxproj/test/set_initial_connect_string_test/set_initial_connect_string_test.vcxproj
  72. 21
      vsprojects/vcxproj/test/set_initial_connect_string_test/set_initial_connect_string_test.vcxproj.filters

@ -311,6 +311,7 @@ grpc_cc_library(
"src/core/lib/profiling/stap_timers.c",
"src/core/lib/support/arena.c",
"src/core/lib/support/alloc.c",
"src/core/lib/support/atm.c",
"src/core/lib/support/avl.c",
"src/core/lib/support/backoff.c",
"src/core/lib/support/cmdline.c",
@ -686,10 +687,8 @@ grpc_cc_library(
"src/core/ext/client_channel/client_channel_factory.c",
"src/core/ext/client_channel/client_channel_plugin.c",
"src/core/ext/client_channel/connector.c",
"src/core/ext/client_channel/default_initial_connect_string.c",
"src/core/ext/client_channel/http_connect_handshaker.c",
"src/core/ext/client_channel/http_proxy.c",
"src/core/ext/client_channel/initial_connect_string.c",
"src/core/ext/client_channel/lb_policy.c",
"src/core/ext/client_channel/lb_policy_factory.c",
"src/core/ext/client_channel/lb_policy_registry.c",
@ -699,6 +698,7 @@ grpc_cc_library(
"src/core/ext/client_channel/resolver.c",
"src/core/ext/client_channel/resolver_factory.c",
"src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/retry_throttle.c",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c",
@ -709,7 +709,6 @@ grpc_cc_library(
"src/core/ext/client_channel/connector.h",
"src/core/ext/client_channel/http_connect_handshaker.h",
"src/core/ext/client_channel/http_proxy.h",
"src/core/ext/client_channel/initial_connect_string.h",
"src/core/ext/client_channel/lb_policy.h",
"src/core/ext/client_channel/lb_policy_factory.h",
"src/core/ext/client_channel/lb_policy_registry.h",
@ -719,6 +718,7 @@ grpc_cc_library(
"src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/retry_throttle.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h",

@ -491,7 +491,6 @@ add_dependencies(buildtests_c secure_endpoint_test)
add_dependencies(buildtests_c sequential_connectivity_test)
add_dependencies(buildtests_c server_chttp2_test)
add_dependencies(buildtests_c server_test)
add_dependencies(buildtests_c set_initial_connect_string_test)
add_dependencies(buildtests_c slice_buffer_test)
add_dependencies(buildtests_c slice_string_helpers_test)
add_dependencies(buildtests_c slice_test)
@ -618,6 +617,9 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_chttp2_hpack)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_chttp2_transport)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_closure)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@ -732,6 +734,7 @@ add_library(gpr
src/core/lib/profiling/stap_timers.c
src/core/lib/support/alloc.c
src/core/lib/support/arena.c
src/core/lib/support/atm.c
src/core/lib/support/avl.c
src/core/lib/support/backoff.c
src/core/lib/support/cmdline.c
@ -1083,10 +1086,8 @@ add_library(grpc
src/core/ext/client_channel/client_channel_factory.c
src/core/ext/client_channel/client_channel_plugin.c
src/core/ext/client_channel/connector.c
src/core/ext/client_channel/default_initial_connect_string.c
src/core/ext/client_channel/http_connect_handshaker.c
src/core/ext/client_channel/http_proxy.c
src/core/ext/client_channel/initial_connect_string.c
src/core/ext/client_channel/lb_policy.c
src/core/ext/client_channel/lb_policy_factory.c
src/core/ext/client_channel/lb_policy_registry.c
@ -1096,6 +1097,7 @@ add_library(grpc
src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c
src/core/ext/client_channel/retry_throttle.c
src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c
@ -1376,10 +1378,8 @@ add_library(grpc_cronet
src/core/ext/client_channel/client_channel_factory.c
src/core/ext/client_channel/client_channel_plugin.c
src/core/ext/client_channel/connector.c
src/core/ext/client_channel/default_initial_connect_string.c
src/core/ext/client_channel/http_connect_handshaker.c
src/core/ext/client_channel/http_proxy.c
src/core/ext/client_channel/initial_connect_string.c
src/core/ext/client_channel/lb_policy.c
src/core/ext/client_channel/lb_policy_factory.c
src/core/ext/client_channel/lb_policy_registry.c
@ -1389,6 +1389,7 @@ add_library(grpc_cronet
src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c
src/core/ext/client_channel/retry_throttle.c
src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c
@ -1942,10 +1943,8 @@ add_library(grpc_unsecure
src/core/ext/client_channel/client_channel_factory.c
src/core/ext/client_channel/client_channel_plugin.c
src/core/ext/client_channel/connector.c
src/core/ext/client_channel/default_initial_connect_string.c
src/core/ext/client_channel/http_connect_handshaker.c
src/core/ext/client_channel/http_proxy.c
src/core/ext/client_channel/initial_connect_string.c
src/core/ext/client_channel/lb_policy.c
src/core/ext/client_channel/lb_policy_factory.c
src/core/ext/client_channel/lb_policy_registry.c
@ -1955,6 +1954,7 @@ add_library(grpc_unsecure
src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c
src/core/ext/client_channel/retry_throttle.c
src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c
@ -2545,10 +2545,8 @@ add_library(grpc++_cronet
src/core/ext/client_channel/client_channel_factory.c
src/core/ext/client_channel/client_channel_plugin.c
src/core/ext/client_channel/connector.c
src/core/ext/client_channel/default_initial_connect_string.c
src/core/ext/client_channel/http_connect_handshaker.c
src/core/ext/client_channel/http_proxy.c
src/core/ext/client_channel/initial_connect_string.c
src/core/ext/client_channel/lb_policy.c
src/core/ext/client_channel/lb_policy_factory.c
src/core/ext/client_channel/lb_policy_registry.c
@ -2558,6 +2556,7 @@ add_library(grpc++_cronet
src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c
src/core/ext/client_channel/retry_throttle.c
src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c
@ -7551,38 +7550,6 @@ target_link_libraries(server_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(set_initial_connect_string_test
test/core/client_channel/set_initial_connect_string_test.c
)
target_include_directories(set_initial_connect_string_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_BUILD_INCLUDE_DIR}
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(set_initial_connect_string_test
${_gRPC_ALLTARGETS_LIBRARIES}
test_tcp_server
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(slice_buffer_test
test/core/slice/slice_buffer_test.c
)
@ -8588,6 +8555,49 @@ endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(bm_chttp2_transport
test/cpp/microbenchmarks/bm_chttp2_transport.cc
third_party/googletest/src/gtest-all.cc
)
target_include_directories(bm_chttp2_transport
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_BUILD_INCLUDE_DIR}
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
PRIVATE third_party/googletest/include
PRIVATE third_party/googletest
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(bm_chttp2_transport
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_benchmark
benchmark
grpc++_test_util
grpc_test_util
grpc++
grpc
gpr_test_util
gpr
${_gRPC_GFLAGS_LIBRARIES}
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(bm_closure
test/cpp/microbenchmarks/bm_closure.cc
third_party/googletest/src/gtest-all.cc

@ -1062,7 +1062,6 @@ sequential_connectivity_test: $(BINDIR)/$(CONFIG)/sequential_connectivity_test
server_chttp2_test: $(BINDIR)/$(CONFIG)/server_chttp2_test
server_fuzzer: $(BINDIR)/$(CONFIG)/server_fuzzer
server_test: $(BINDIR)/$(CONFIG)/server_test
set_initial_connect_string_test: $(BINDIR)/$(CONFIG)/set_initial_connect_string_test
slice_buffer_test: $(BINDIR)/$(CONFIG)/slice_buffer_test
slice_string_helpers_test: $(BINDIR)/$(CONFIG)/slice_string_helpers_test
slice_test: $(BINDIR)/$(CONFIG)/slice_test
@ -1095,6 +1094,7 @@ auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test
bm_arena: $(BINDIR)/$(CONFIG)/bm_arena
bm_call_create: $(BINDIR)/$(CONFIG)/bm_call_create
bm_chttp2_hpack: $(BINDIR)/$(CONFIG)/bm_chttp2_hpack
bm_chttp2_transport: $(BINDIR)/$(CONFIG)/bm_chttp2_transport
bm_closure: $(BINDIR)/$(CONFIG)/bm_closure
bm_cq: $(BINDIR)/$(CONFIG)/bm_cq
bm_error: $(BINDIR)/$(CONFIG)/bm_error
@ -1428,7 +1428,6 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/sequential_connectivity_test \
$(BINDIR)/$(CONFIG)/server_chttp2_test \
$(BINDIR)/$(CONFIG)/server_test \
$(BINDIR)/$(CONFIG)/set_initial_connect_string_test \
$(BINDIR)/$(CONFIG)/slice_buffer_test \
$(BINDIR)/$(CONFIG)/slice_string_helpers_test \
$(BINDIR)/$(CONFIG)/slice_test \
@ -1520,6 +1519,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/bm_arena \
$(BINDIR)/$(CONFIG)/bm_call_create \
$(BINDIR)/$(CONFIG)/bm_chttp2_hpack \
$(BINDIR)/$(CONFIG)/bm_chttp2_transport \
$(BINDIR)/$(CONFIG)/bm_closure \
$(BINDIR)/$(CONFIG)/bm_cq \
$(BINDIR)/$(CONFIG)/bm_error \
@ -1637,6 +1637,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/bm_arena \
$(BINDIR)/$(CONFIG)/bm_call_create \
$(BINDIR)/$(CONFIG)/bm_chttp2_hpack \
$(BINDIR)/$(CONFIG)/bm_chttp2_transport \
$(BINDIR)/$(CONFIG)/bm_closure \
$(BINDIR)/$(CONFIG)/bm_cq \
$(BINDIR)/$(CONFIG)/bm_error \
@ -1890,8 +1891,6 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/server_chttp2_test || ( echo test server_chttp2_test failed ; exit 1 )
$(E) "[RUN] Testing server_test"
$(Q) $(BINDIR)/$(CONFIG)/server_test || ( echo test server_test failed ; exit 1 )
$(E) "[RUN] Testing set_initial_connect_string_test"
$(Q) $(BINDIR)/$(CONFIG)/set_initial_connect_string_test || ( echo test set_initial_connect_string_test failed ; exit 1 )
$(E) "[RUN] Testing slice_buffer_test"
$(Q) $(BINDIR)/$(CONFIG)/slice_buffer_test || ( echo test slice_buffer_test failed ; exit 1 )
$(E) "[RUN] Testing slice_string_helpers_test"
@ -1984,6 +1983,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/bm_call_create || ( echo test bm_call_create failed ; exit 1 )
$(E) "[RUN] Testing bm_chttp2_hpack"
$(Q) $(BINDIR)/$(CONFIG)/bm_chttp2_hpack || ( echo test bm_chttp2_hpack failed ; exit 1 )
$(E) "[RUN] Testing bm_chttp2_transport"
$(Q) $(BINDIR)/$(CONFIG)/bm_chttp2_transport || ( echo test bm_chttp2_transport failed ; exit 1 )
$(E) "[RUN] Testing bm_closure"
$(Q) $(BINDIR)/$(CONFIG)/bm_closure || ( echo test bm_closure failed ; exit 1 )
$(E) "[RUN] Testing bm_cq"
@ -2654,6 +2655,7 @@ LIBGPR_SRC = \
src/core/lib/profiling/stap_timers.c \
src/core/lib/support/alloc.c \
src/core/lib/support/arena.c \
src/core/lib/support/atm.c \
src/core/lib/support/avl.c \
src/core/lib/support/backoff.c \
src/core/lib/support/cmdline.c \
@ -2978,10 +2980,8 @@ LIBGRPC_SRC = \
src/core/ext/client_channel/client_channel_factory.c \
src/core/ext/client_channel/client_channel_plugin.c \
src/core/ext/client_channel/connector.c \
src/core/ext/client_channel/default_initial_connect_string.c \
src/core/ext/client_channel/http_connect_handshaker.c \
src/core/ext/client_channel/http_proxy.c \
src/core/ext/client_channel/initial_connect_string.c \
src/core/ext/client_channel/lb_policy.c \
src/core/ext/client_channel/lb_policy_factory.c \
src/core/ext/client_channel/lb_policy_registry.c \
@ -2991,6 +2991,7 @@ LIBGRPC_SRC = \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/retry_throttle.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \
@ -3269,10 +3270,8 @@ LIBGRPC_CRONET_SRC = \
src/core/ext/client_channel/client_channel_factory.c \
src/core/ext/client_channel/client_channel_plugin.c \
src/core/ext/client_channel/connector.c \
src/core/ext/client_channel/default_initial_connect_string.c \
src/core/ext/client_channel/http_connect_handshaker.c \
src/core/ext/client_channel/http_proxy.c \
src/core/ext/client_channel/initial_connect_string.c \
src/core/ext/client_channel/lb_policy.c \
src/core/ext/client_channel/lb_policy_factory.c \
src/core/ext/client_channel/lb_policy_registry.c \
@ -3282,6 +3281,7 @@ LIBGRPC_CRONET_SRC = \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/retry_throttle.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \
@ -3806,10 +3806,8 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/client_channel/client_channel_factory.c \
src/core/ext/client_channel/client_channel_plugin.c \
src/core/ext/client_channel/connector.c \
src/core/ext/client_channel/default_initial_connect_string.c \
src/core/ext/client_channel/http_connect_handshaker.c \
src/core/ext/client_channel/http_proxy.c \
src/core/ext/client_channel/initial_connect_string.c \
src/core/ext/client_channel/lb_policy.c \
src/core/ext/client_channel/lb_policy_factory.c \
src/core/ext/client_channel/lb_policy_registry.c \
@ -3819,6 +3817,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/retry_throttle.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \
@ -4395,10 +4394,8 @@ LIBGRPC++_CRONET_SRC = \
src/core/ext/client_channel/client_channel_factory.c \
src/core/ext/client_channel/client_channel_plugin.c \
src/core/ext/client_channel/connector.c \
src/core/ext/client_channel/default_initial_connect_string.c \
src/core/ext/client_channel/http_connect_handshaker.c \
src/core/ext/client_channel/http_proxy.c \
src/core/ext/client_channel/initial_connect_string.c \
src/core/ext/client_channel/lb_policy.c \
src/core/ext/client_channel/lb_policy_factory.c \
src/core/ext/client_channel/lb_policy_registry.c \
@ -4408,6 +4405,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/retry_throttle.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \
@ -11834,38 +11832,6 @@ endif
endif
SET_INITIAL_CONNECT_STRING_TEST_SRC = \
test/core/client_channel/set_initial_connect_string_test.c \
SET_INITIAL_CONNECT_STRING_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SET_INITIAL_CONNECT_STRING_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/set_initial_connect_string_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/set_initial_connect_string_test: $(SET_INITIAL_CONNECT_STRING_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(SET_INITIAL_CONNECT_STRING_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/set_initial_connect_string_test
endif
$(OBJDIR)/$(CONFIG)/test/core/client_channel/set_initial_connect_string_test.o: $(LIBDIR)/$(CONFIG)/libtest_tcp_server.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_set_initial_connect_string_test: $(SET_INITIAL_CONNECT_STRING_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(SET_INITIAL_CONNECT_STRING_TEST_OBJS:.o=.dep)
endif
endif
SLICE_BUFFER_TEST_SRC = \
test/core/slice/slice_buffer_test.c \
@ -12956,6 +12922,49 @@ endif
endif
BM_CHTTP2_TRANSPORT_SRC = \
test/cpp/microbenchmarks/bm_chttp2_transport.cc \
BM_CHTTP2_TRANSPORT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CHTTP2_TRANSPORT_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/bm_chttp2_transport: 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.0.0+.
$(BINDIR)/$(CONFIG)/bm_chttp2_transport: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/bm_chttp2_transport: $(PROTOBUF_DEP) $(BM_CHTTP2_TRANSPORT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(BM_CHTTP2_TRANSPORT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_chttp2_transport
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_chttp2_transport.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_bm_chttp2_transport: $(BM_CHTTP2_TRANSPORT_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(BM_CHTTP2_TRANSPORT_OBJS:.o=.dep)
endif
endif
BM_CLOSURE_SRC = \
test/cpp/microbenchmarks/bm_closure.cc \

@ -551,6 +551,7 @@
'src/core/lib/profiling/stap_timers.c',
'src/core/lib/support/alloc.c',
'src/core/lib/support/arena.c',
'src/core/lib/support/atm.c',
'src/core/lib/support/avl.c',
'src/core/lib/support/backoff.c',
'src/core/lib/support/cmdline.c',
@ -794,10 +795,8 @@
'src/core/ext/client_channel/client_channel_factory.c',
'src/core/ext/client_channel/client_channel_plugin.c',
'src/core/ext/client_channel/connector.c',
'src/core/ext/client_channel/default_initial_connect_string.c',
'src/core/ext/client_channel/http_connect_handshaker.c',
'src/core/ext/client_channel/http_proxy.c',
'src/core/ext/client_channel/initial_connect_string.c',
'src/core/ext/client_channel/lb_policy.c',
'src/core/ext/client_channel/lb_policy_factory.c',
'src/core/ext/client_channel/lb_policy_registry.c',
@ -807,6 +806,7 @@
'src/core/ext/client_channel/resolver.c',
'src/core/ext/client_channel/resolver_factory.c',
'src/core/ext/client_channel/resolver_registry.c',
'src/core/ext/client_channel/retry_throttle.c',
'src/core/ext/client_channel/subchannel.c',
'src/core/ext/client_channel/subchannel_index.c',
'src/core/ext/client_channel/uri_parser.c',

@ -103,6 +103,7 @@ filegroups:
- src/core/lib/profiling/stap_timers.c
- src/core/lib/support/alloc.c
- src/core/lib/support/arena.c
- src/core/lib/support/atm.c
- src/core/lib/support/avl.c
- src/core/lib/support/backoff.c
- src/core/lib/support/cmdline.c
@ -413,7 +414,6 @@ filegroups:
- src/core/ext/client_channel/connector.h
- src/core/ext/client_channel/http_connect_handshaker.h
- src/core/ext/client_channel/http_proxy.h
- src/core/ext/client_channel/initial_connect_string.h
- src/core/ext/client_channel/lb_policy.h
- src/core/ext/client_channel/lb_policy_factory.h
- src/core/ext/client_channel/lb_policy_registry.h
@ -423,6 +423,7 @@ filegroups:
- src/core/ext/client_channel/resolver.h
- src/core/ext/client_channel/resolver_factory.h
- src/core/ext/client_channel/resolver_registry.h
- src/core/ext/client_channel/retry_throttle.h
- src/core/ext/client_channel/subchannel.h
- src/core/ext/client_channel/subchannel_index.h
- src/core/ext/client_channel/uri_parser.h
@ -432,10 +433,8 @@ filegroups:
- src/core/ext/client_channel/client_channel_factory.c
- src/core/ext/client_channel/client_channel_plugin.c
- src/core/ext/client_channel/connector.c
- src/core/ext/client_channel/default_initial_connect_string.c
- src/core/ext/client_channel/http_connect_handshaker.c
- src/core/ext/client_channel/http_proxy.c
- src/core/ext/client_channel/initial_connect_string.c
- src/core/ext/client_channel/lb_policy.c
- src/core/ext/client_channel/lb_policy_factory.c
- src/core/ext/client_channel/lb_policy_registry.c
@ -445,6 +444,7 @@ filegroups:
- src/core/ext/client_channel/resolver.c
- src/core/ext/client_channel/resolver_factory.c
- src/core/ext/client_channel/resolver_registry.c
- src/core/ext/client_channel/retry_throttle.c
- src/core/ext/client_channel/subchannel.c
- src/core/ext/client_channel/subchannel_index.c
- src/core/ext/client_channel/uri_parser.c
@ -2712,20 +2712,6 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: set_initial_connect_string_test
cpu_cost: 0.1
build: test
language: c
src:
- test/core/client_channel/set_initial_connect_string_test.c
deps:
- test_tcp_server
- grpc_test_util
- grpc
- gpr_test_util
- gpr
exclude_iomgrs:
- uv
- name: slice_buffer_test
build: test
language: c
@ -3142,6 +3128,26 @@ targets:
- mac
- linux
- posix
- name: bm_chttp2_transport
build: test
language: c++
src:
- test/cpp/microbenchmarks/bm_chttp2_transport.cc
deps:
- grpc_benchmark
- benchmark
- grpc++_test_util
- grpc_test_util
- grpc++
- grpc
- gpr_test_util
- gpr
args:
- --benchmark_min_time=0
platforms:
- mac
- linux
- posix
- name: bm_closure
build: test
language: c++

@ -40,6 +40,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/profiling/stap_timers.c \
src/core/lib/support/alloc.c \
src/core/lib/support/arena.c \
src/core/lib/support/atm.c \
src/core/lib/support/avl.c \
src/core/lib/support/backoff.c \
src/core/lib/support/cmdline.c \
@ -260,10 +261,8 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/client_channel/client_channel_factory.c \
src/core/ext/client_channel/client_channel_plugin.c \
src/core/ext/client_channel/connector.c \
src/core/ext/client_channel/default_initial_connect_string.c \
src/core/ext/client_channel/http_connect_handshaker.c \
src/core/ext/client_channel/http_proxy.c \
src/core/ext/client_channel/initial_connect_string.c \
src/core/ext/client_channel/lb_policy.c \
src/core/ext/client_channel/lb_policy_factory.c \
src/core/ext/client_channel/lb_policy_registry.c \
@ -273,6 +272,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/retry_throttle.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \

@ -0,0 +1,158 @@
# Combiner Explanation
## Talk by ctiller, notes by vjpai
Typical way of doing critical section
```
mu.lock()
do_stuff()
mu.unlock()
```
An alternative way of doing it is
```
class combiner {
run(f) {
mu.lock()
f()
mu.unlock()
}
mutex mu;
}
combiner.run(do_stuff)
```
If you have two threads calling combiner, there will be some kind of
queuing in place. It's called `combiner` because you can pass in more
than one do_stuff at once and they will run under a common `mu`.
The implementation described above has the issue that you're blocking a thread
for a period of time, and this is considered harmful because it's an application thread that you're blocking.
Instead, get a new property:
* Keep things running in serial execution
* Don't ever sleep the thread
* But maybe allow things to end up running on a different thread from where they were started
* This means that `do_stuff` doesn't necessarily run to completion when `combiner.run` is invoked
```
class combiner {
mpscq q; // multi-producer single-consumer queue can be made non-blocking
state s; // is it empty or executing
run(f) {
if (q.push(f)) {
// q.push returns true if it's the first thing
while (q.pop(&f)) { // modulo some extra work to avoid races
f();
}
}
}
}
```
The basic idea is that the first one to push onto the combiner
executes the work and then keeps executing functions from the queue
until the combiner is drained.
Our combiner does some additional work, with the motivation of write-batching.
We have a second tier of `run` called `run_finally`. Anything queued
onto `run_finally` runs after we have drained the queue. That means
that there is essentially a finally-queue. This is not guaranteed to
be final, but it's best-effort. In the process of running the finally
item, we might put something onto the main combiner queue and so we'll
need to re-enter.
`chttp2` runs all ops in the run state except if it sees a write it puts that into a finally. That way anything else that gets put into the combiner can add to that write.
```
class combiner {
mpscq q; // multi-producer single-consumer queue can be made non-blocking
state s; // is it empty or executing
queue finally; // you can only do run_finally when you are already running something from the combiner
run(f) {
if (q.push(f)) {
// q.push returns true if it's the first thing
loop:
while (q.pop(&f)) { // modulo some extra work to avoid races
f();
}
while (finally.pop(&f)) {
f();
}
goto loop;
}
}
}
```
So that explains how combiners work in general. In gRPC, there is
`start_batch(..., tag)` and then work only gets activated by somebody
calling `cq::next` which returns a tag. This gives an API-level
guarantee that there will be a thread doing polling to actually make
work happen. However, some operations are not covered by a poller
thread, such as cancellation that doesn't have a completion. Other
callbacks that don't have a completion are the internal work that gets
done before the batch gets completed. We need a condition called
`covered_by_poller` that means that the item will definitely need some
thread at some point to call `cq::next` . This includes those
callbacks that directly cause a completion but also those that are
indirectly required before getting a completion. If we can't tell for
sure for a specific path, we have to assumed it is not covered by
poller.
The above combiner has the problem that it keeps draining for a
potentially infinite amount of time and that can lead to a huge tail
latency for some operations. So we can tweak it by returning to the application
if we know that it is valid to do so:
```
while (q.pop(&f)) {
f();
if (control_can_be_returned && some_still_queued_thing_is_covered_by_poller) {
offload_combiner_work_to_some_other_thread();
}
}
```
`offload` is more than `break`; it does `break` but also causes some
other thread that is currently waiting on a poll to break out of its
poll. This is done by setting up a per-polling-island work-queue
(distributor) wakeup FD. The work-queue is the converse of the combiner; it
tries to spray events onto as many threads as possible to get as much concurrency as possible.
So `offload` really does:
```
workqueue.run(continue_from_while_loop);
break;
```
This needs us to add another class variable for a `workqueue`
(which is really conceptually a distributor).
```
workqueue::run(f) {
q.push(f)
eventfd.wakeup()
}
workqueue::readable() {
eventfd.consume();
q.pop(&f);
f();
if (!q.empty()) {
eventfd.wakeup(); // spray across as many threads as are waiting on this workqueue
}
}
```
In principle, `run_finally` could get starved, but this hasn't
happened in practice. If we were concerned about this, we could put a
limit on how many things come off the regular `q` before the `finally`
queue gets processed.

@ -0,0 +1,160 @@
# gRPC Error
## Background
`grpc_error` is the c-core's opaque representation of an error. It holds a
collection of integers, strings, timestamps, and child errors that related to
the final error.
always present are:
* GRPC_ERROR_STR_FILE and GRPC_ERROR_INT_FILE_LINE - the source location where
the error was generated
* GRPC_ERROR_STR_DESCRIPTION - a human readable description of the error
* GRPC_ERROR_TIME_CREATED - a timestamp indicating when the error happened
An error can also have children; these are other errors that are believed to
have contributed to this one. By accumulating children, we can begin to root
cause high level failures from low level failures, without having to derive
execution paths from log lines.
grpc_errors are refcounted objects, which means they need strict ownership
semantics. An extra ref on an error can cause a memory leak, and a missing ref
can cause a crash.
This document serves as a detailed overview of grpc_error's ownership rules. It
should help people use the errors, as well as help people debug refcount related
errors.
## Clarification of Ownership
If a particular function is said to "own" an error, that means it has the
responsibility of calling unref on the error. A function may have access to an
error without ownership of it.
This means the function may use the error, but must not call unref on it, since
that will be done elsewhere in the code. A function that does not own an error
may explicitly take ownership of it by manually calling GRPC_ERROR_REF.
## Ownership Rules
There are three rules of error ownership, which we will go over in detail.
* If `grpc_error` is returned by a function, the caller owns a ref to that
instance.
* If a `grpc_error` is passed to a `grpc_closure` callback function, then that
function does not own a ref to the error.
* if a `grpc_error` is passed to *any other function*, then that function
takes ownership of the error.
### Rule 1
> If `grpc_error` is returned by a function, the caller owns a ref to that
> instance.*
For example, in the following code block, error1 and error2 are owned by the
current function.
```C
grpc_error* error1 = GRPC_ERROR_CREATE("Some error occured");
grpc_error* error2 = some_operation_that_might_fail(...);
```
The current function would have to explicitly call GRPC_ERROR_UNREF on the
errors, or pass them along to a function that would take over the ownership.
### Rule 2
> If a `grpc_error` is passed to a `grpc_closure` callback function, then that
> function does not own a ref to the error.
A `grpc_closure` callback function is any function that has the signature:
```C
void (*cb)(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
```
This means that the error ownership is NOT transferred when a functions calls:
```C
c->cb(exec_ctx, c->cb_arg, err);
```
The caller is still responsible for unref-ing the error.
However, the above line is currently being phased out! It is safer to invoke
callbacks with `grpc_closure_run` and `grpc_closure_sched`. These functions are
not callbacks, so they will take ownership of the error passed to them.
```C
grpc_error* error = GRPC_ERROR_CREATE("Some error occured");
grpc_closure_run(exec_ctx, cb, error);
// current function no longer has ownership of the error
```
If you schedule or run a closure, but still need ownership of the error, then
you must explicitly take a reference.
```C
grpc_error* error = GRPC_ERROR_CREATE("Some error occured");
grpc_closure_run(exec_ctx, cb, GRPC_ERROR_REF(error));
// do some other things with the error
GRPC_ERROR_UNREF(error);
```
Rule 2 is more important to keep in mind when **implementing** `grpc_closure`
callback functions. You must keep in mind that you do not own the error, and
must not unref it. More importantly, you cannot pass it to any function that
would take ownership of the error, without explicitly taking ownership yourself.
For example:
```C
void on_some_action(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
// this would cause a crash, because some_function will unref the error,
// and the caller of this callback will also unref it.
some_function(error);
// this callback function must take ownership, so it can give that
// ownership to the function it is calling.
some_function(GRPC_ERROR_REF(error));
}
```
### Rule 3
> if a `grpc_error` is passed to *any other function*, then that function takes
> ownership of the error.
Take the following example:
```C
grpc_error* error = GRPC_ERROR_CREATE("Some error occured");
// do some things
some_function(error);
// can't use error anymore! might be gone.
```
When some_function is called, it takes over the ownership of the error, and it
will eventually unref it. So the caller can no longer safely use the error.
If the caller needed to keep using the error (or passing it to other functions),
if would have to take on a reference to it. This is a common pattern seen.
```C
void func() {
grpc_error* error = GRPC_ERROR_CREATE("Some error occured");
some_function(GRPC_ERROR_REF(error));
// do things
some_other_function(GRPC_ERROR_REF(error));
// do more things
some_last_function(error);
}
```
The last call takes ownership and will eventually give the error its final
unref.
When **implementing** a function that takes an error (and is not a
`grpc_closure` callback function), you must ensure the error is unref-ed either
by doing it explicitly with GRPC_ERROR_UNREF, or by passing the error to a
function that takes over the ownership.

@ -1,7 +1,8 @@
This is the static code generation variant of the Node examples. Code in these examples is pre-generated using protoc and the Node gRPC protoc plugin, and the generated code can be found in various `*_pb.js` files. The command line sequence for generating those files is as follows (assuming that `protoc` and `grpc_node_plugin` are present, and starting in the base directory of this package):
This is the static code generation variant of the Node examples. Code in these examples is pre-generated using protoc and the Node gRPC protoc plugin, and the generated code can be found in various `*_pb.js` files. The command line sequence for generating those files is as follows (assuming that `protoc` and `grpc_node_plugin` are present, and starting in the directory which contains this README.md file):
```sh
cd ../protos
protoc --js_out=import_style=commonjs,binary:../node/static_codegen/ --grpc_out=../node/static_codegen --plugin=protoc-gen-grpc=grpc_node_plugin helloworld.proto
protoc --js_out=import_style=commonjs,binary:../node/static_codegen/route_guide/ --grpc_out=../node/static_codegen/route_guide/ --plugin=protoc-gen-grpc=grpc_node_plugin route_guide.proto
cd ../../protos
npm install -g grpc-tools
grpc_tools_node_protoc --js_out=import_style=commonjs,binary:../node/static_codegen/ --grpc_out=../node/static_codegen --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` helloworld.proto
grpc_tools_node_protoc --js_out=import_style=commonjs,binary:../node/static_codegen/route_guide/ --grpc_out=../node/static_codegen/route_guide/ --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` route_guide.proto
```

@ -214,6 +214,7 @@ Pod::Spec.new do |s|
'src/core/lib/profiling/stap_timers.c',
'src/core/lib/support/alloc.c',
'src/core/lib/support/arena.c',
'src/core/lib/support/atm.c',
'src/core/lib/support/avl.c',
'src/core/lib/support/backoff.c',
'src/core/lib/support/cmdline.c',
@ -412,7 +413,6 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/connector.h',
'src/core/ext/client_channel/http_connect_handshaker.h',
'src/core/ext/client_channel/http_proxy.h',
'src/core/ext/client_channel/initial_connect_string.h',
'src/core/ext/client_channel/lb_policy.h',
'src/core/ext/client_channel/lb_policy_factory.h',
'src/core/ext/client_channel/lb_policy_registry.h',
@ -422,6 +422,7 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/resolver.h',
'src/core/ext/client_channel/resolver_factory.h',
'src/core/ext/client_channel/resolver_registry.h',
'src/core/ext/client_channel/retry_throttle.h',
'src/core/ext/client_channel/subchannel.h',
'src/core/ext/client_channel/subchannel_index.h',
'src/core/ext/client_channel/uri_parser.h',
@ -633,10 +634,8 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/client_channel_factory.c',
'src/core/ext/client_channel/client_channel_plugin.c',
'src/core/ext/client_channel/connector.c',
'src/core/ext/client_channel/default_initial_connect_string.c',
'src/core/ext/client_channel/http_connect_handshaker.c',
'src/core/ext/client_channel/http_proxy.c',
'src/core/ext/client_channel/initial_connect_string.c',
'src/core/ext/client_channel/lb_policy.c',
'src/core/ext/client_channel/lb_policy_factory.c',
'src/core/ext/client_channel/lb_policy_registry.c',
@ -646,6 +645,7 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/resolver.c',
'src/core/ext/client_channel/resolver_factory.c',
'src/core/ext/client_channel/resolver_registry.c',
'src/core/ext/client_channel/retry_throttle.c',
'src/core/ext/client_channel/subchannel.c',
'src/core/ext/client_channel/subchannel_index.c',
'src/core/ext/client_channel/uri_parser.c',
@ -857,7 +857,6 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/connector.h',
'src/core/ext/client_channel/http_connect_handshaker.h',
'src/core/ext/client_channel/http_proxy.h',
'src/core/ext/client_channel/initial_connect_string.h',
'src/core/ext/client_channel/lb_policy.h',
'src/core/ext/client_channel/lb_policy_factory.h',
'src/core/ext/client_channel/lb_policy_registry.h',
@ -867,6 +866,7 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/resolver.h',
'src/core/ext/client_channel/resolver_factory.h',
'src/core/ext/client_channel/resolver_registry.h',
'src/core/ext/client_channel/retry_throttle.h',
'src/core/ext/client_channel/subchannel.h',
'src/core/ext/client_channel/subchannel_index.h',
'src/core/ext/client_channel/uri_parser.h',

@ -99,6 +99,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/profiling/stap_timers.c )
s.files += %w( src/core/lib/support/alloc.c )
s.files += %w( src/core/lib/support/arena.c )
s.files += %w( src/core/lib/support/atm.c )
s.files += %w( src/core/lib/support/avl.c )
s.files += %w( src/core/lib/support/backoff.c )
s.files += %w( src/core/lib/support/cmdline.c )
@ -328,7 +329,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_channel/connector.h )
s.files += %w( src/core/ext/client_channel/http_connect_handshaker.h )
s.files += %w( src/core/ext/client_channel/http_proxy.h )
s.files += %w( src/core/ext/client_channel/initial_connect_string.h )
s.files += %w( src/core/ext/client_channel/lb_policy.h )
s.files += %w( src/core/ext/client_channel/lb_policy_factory.h )
s.files += %w( src/core/ext/client_channel/lb_policy_registry.h )
@ -338,6 +338,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_channel/resolver.h )
s.files += %w( src/core/ext/client_channel/resolver_factory.h )
s.files += %w( src/core/ext/client_channel/resolver_registry.h )
s.files += %w( src/core/ext/client_channel/retry_throttle.h )
s.files += %w( src/core/ext/client_channel/subchannel.h )
s.files += %w( src/core/ext/client_channel/subchannel_index.h )
s.files += %w( src/core/ext/client_channel/uri_parser.h )
@ -549,10 +550,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_channel/client_channel_factory.c )
s.files += %w( src/core/ext/client_channel/client_channel_plugin.c )
s.files += %w( src/core/ext/client_channel/connector.c )
s.files += %w( src/core/ext/client_channel/default_initial_connect_string.c )
s.files += %w( src/core/ext/client_channel/http_connect_handshaker.c )
s.files += %w( src/core/ext/client_channel/http_proxy.c )
s.files += %w( src/core/ext/client_channel/initial_connect_string.c )
s.files += %w( src/core/ext/client_channel/lb_policy.c )
s.files += %w( src/core/ext/client_channel/lb_policy_factory.c )
s.files += %w( src/core/ext/client_channel/lb_policy_registry.c )
@ -562,6 +561,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_channel/resolver.c )
s.files += %w( src/core/ext/client_channel/resolver_factory.c )
s.files += %w( src/core/ext/client_channel/resolver_registry.c )
s.files += %w( src/core/ext/client_channel/retry_throttle.c )
s.files += %w( src/core/ext/client_channel/subchannel.c )
s.files += %w( src/core/ext/client_channel/subchannel_index.c )
s.files += %w( src/core/ext/client_channel/uri_parser.c )

@ -117,10 +117,10 @@ class ChannelArguments {
/// Return (by value) a c grpc_channel_args structure which points to
/// arguments owned by this ChannelArguments instance
grpc_channel_args c_channel_args() {
grpc_channel_args c_channel_args() const {
grpc_channel_args out;
out.num_args = args_.size();
out.args = args_.empty() ? NULL : &args_[0];
out.args = args_.empty() ? NULL : const_cast<grpc_arg*>(&args_[0]);
return out;
}

@ -92,4 +92,9 @@
#error could not determine platform for atm
#endif
/** Adds \a delta to \a *value, clamping the result to the range specified
by \a min and \a max. Returns the new value. */
gpr_atm gpr_atm_no_barrier_clamped_add(gpr_atm *value, gpr_atm delta,
gpr_atm min, gpr_atm max);
#endif /* GRPC_IMPL_CODEGEN_ATM_H */

@ -108,6 +108,7 @@
<file baseinstalldir="/" name="src/core/lib/profiling/stap_timers.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/alloc.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/arena.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/atm.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/avl.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/backoff.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/cmdline.c" role="src" />
@ -337,7 +338,6 @@
<file baseinstalldir="/" name="src/core/ext/client_channel/connector.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/http_connect_handshaker.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/http_proxy.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/initial_connect_string.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy_registry.h" role="src" />
@ -347,6 +347,7 @@
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/retry_throttle.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/subchannel.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/subchannel_index.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.h" role="src" />
@ -558,10 +559,8 @@
<file baseinstalldir="/" name="src/core/ext/client_channel/client_channel_factory.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/client_channel_plugin.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/connector.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/default_initial_connect_string.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/http_connect_handshaker.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/http_proxy.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/initial_connect_string.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy_factory.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/lb_policy_registry.c" role="src" />
@ -571,6 +570,7 @@
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/retry_throttle.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/subchannel.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/subchannel_index.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.c" role="src" />

@ -216,14 +216,13 @@ PACKAGE_DIRECTORIES = {
INSTALL_REQUIRES = (
'six>=1.5.2',
'enum34>=1.0.4',
# TODO(atash): eventually split the grpcio package into a metapackage
# depending on protobuf and the runtime component (independent of protobuf)
'protobuf>=3.2.0',
)
if not PY3:
INSTALL_REQUIRES += ('futures>=2.2.0',)
INSTALL_REQUIRES += ('futures>=2.2.0', 'enum34>=1.0.4')
SETUP_REQUIRES = INSTALL_REQUIRES + (
'sphinx>=1.3',

@ -47,6 +47,7 @@
#include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/ext/client_channel/retry_throttle.h"
#include "src/core/ext/client_channel/subchannel.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/connected_channel.h"
@ -189,6 +190,8 @@ typedef struct client_channel_channel_data {
grpc_combiner *combiner;
/** currently active load balancer */
grpc_lb_policy *lb_policy;
/** retry throttle data */
grpc_server_retry_throttle_data *retry_throttle_data;
/** maps method names to method_parameters structs */
grpc_slice_hash_table *method_params_table;
/** incoming resolver result - set by resolver.next() */
@ -284,6 +287,65 @@ static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
&w->on_changed);
}
typedef struct {
char *server_name;
grpc_server_retry_throttle_data *retry_throttle_data;
} service_config_parsing_state;
static void parse_retry_throttle_params(const grpc_json *field, void *arg) {
service_config_parsing_state *parsing_state = arg;
if (strcmp(field->key, "retryThrottling") == 0) {
if (parsing_state->retry_throttle_data != NULL) return; // Duplicate.
if (field->type != GRPC_JSON_OBJECT) return;
int max_milli_tokens = 0;
int milli_token_ratio = 0;
for (grpc_json *sub_field = field->child; sub_field != NULL;
sub_field = sub_field->next) {
if (sub_field->key == NULL) return;
if (strcmp(sub_field->key, "maxTokens") == 0) {
if (max_milli_tokens != 0) return; // Duplicate.
if (sub_field->type != GRPC_JSON_NUMBER) return;
max_milli_tokens = gpr_parse_nonnegative_int(sub_field->value);
if (max_milli_tokens == -1) return;
max_milli_tokens *= 1000;
} else if (strcmp(sub_field->key, "tokenRatio") == 0) {
if (milli_token_ratio != 0) return; // Duplicate.
if (sub_field->type != GRPC_JSON_NUMBER) return;
// We support up to 3 decimal digits.
size_t whole_len = strlen(sub_field->value);
uint32_t multiplier = 1;
uint32_t decimal_value = 0;
const char *decimal_point = strchr(sub_field->value, '.');
if (decimal_point != NULL) {
whole_len = (size_t)(decimal_point - sub_field->value);
multiplier = 1000;
size_t decimal_len = strlen(decimal_point + 1);
if (decimal_len > 3) decimal_len = 3;
if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len,
&decimal_value)) {
return;
}
uint32_t decimal_multiplier = 1;
for (size_t i = 0; i < (3 - decimal_len); ++i) {
decimal_multiplier *= 10;
}
decimal_value *= decimal_multiplier;
}
uint32_t whole_value;
if (!gpr_parse_bytes_to_uint32(sub_field->value, whole_len,
&whole_value)) {
return;
}
milli_token_ratio = (int)((whole_value * multiplier) + decimal_value);
if (milli_token_ratio <= 0) return;
}
}
parsing_state->retry_throttle_data =
grpc_retry_throttle_map_get_data_for_server(
parsing_state->server_name, max_milli_tokens, milli_token_ratio);
}
}
static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
void *arg, grpc_error *error) {
channel_data *chand = arg;
@ -295,6 +357,8 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
bool exit_idle = false;
grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
char *service_config_json = NULL;
service_config_parsing_state parsing_state;
memset(&parsing_state, 0, sizeof(parsing_state));
if (chand->resolver_result != NULL) {
// Find LB policy name.
@ -355,6 +419,19 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
grpc_service_config *service_config =
grpc_service_config_create(service_config_json);
if (service_config != NULL) {
channel_arg =
grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVER_URI);
GPR_ASSERT(channel_arg != NULL);
GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
grpc_uri *uri =
grpc_uri_parse(exec_ctx, channel_arg->value.string, true);
GPR_ASSERT(uri->path[0] != '\0');
parsing_state.server_name =
uri->path[0] == '/' ? uri->path + 1 : uri->path;
grpc_service_config_parse_global_params(
service_config, parse_retry_throttle_params, &parsing_state);
parsing_state.server_name = NULL;
grpc_uri_destroy(uri);
method_params_table = grpc_service_config_create_method_config_table(
exec_ctx, service_config, method_parameters_create_from_json,
&method_parameters_vtable);
@ -386,6 +463,11 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
chand->info_service_config_json = service_config_json;
}
gpr_mu_unlock(&chand->info_mu);
if (chand->retry_throttle_data != NULL) {
grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
}
chand->retry_throttle_data = parsing_state.retry_throttle_data;
if (chand->method_params_table != NULL) {
grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
}
@ -613,6 +695,9 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
}
gpr_free(chand->info_lb_policy_name);
gpr_free(chand->info_service_config_json);
if (chand->retry_throttle_data != NULL) {
grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
}
if (chand->method_params_table != NULL) {
grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
}
@ -654,6 +739,7 @@ typedef struct client_channel_call_data {
grpc_slice path; // Request path.
gpr_timespec call_start_time;
gpr_timespec deadline;
grpc_server_retry_throttle_data *retry_throttle_data;
method_parameters *method_params;
grpc_error *cancel_error;
@ -676,6 +762,9 @@ typedef struct client_channel_call_data {
grpc_call_stack *owning_call;
grpc_linked_mdelem lb_token_mdelem;
grpc_closure on_complete;
grpc_closure *original_on_complete;
} call_data;
grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
@ -728,7 +817,7 @@ static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
gpr_free(ops);
}
// Sets calld->method_params.
// Sets calld->method_params and calld->retry_throttle_data.
// If the method params specify a timeout, populates
// *per_method_deadline and returns true.
static bool set_call_method_params_from_service_config_locked(
@ -736,6 +825,10 @@ static bool set_call_method_params_from_service_config_locked(
gpr_timespec *per_method_deadline) {
channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data;
if (chand->retry_throttle_data != NULL) {
calld->retry_throttle_data =
grpc_server_retry_throttle_data_ref(chand->retry_throttle_data);
}
if (chand->method_params_table != NULL) {
calld->method_params = grpc_method_config_table_get(
exec_ctx, chand->method_params_table, calld->path);
@ -1056,6 +1149,26 @@ static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
add_waiting_locked(calld, op);
}
static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
grpc_call_element *elem = arg;
call_data *calld = elem->call_data;
if (calld->retry_throttle_data != NULL) {
if (error == GRPC_ERROR_NONE) {
grpc_server_retry_throttle_data_record_success(
calld->retry_throttle_data);
} else {
// TODO(roth): In a subsequent PR, check the return value here and
// decide whether or not to retry. Note that we should only
// record failures whose statuses match the configured retryable
// or non-fatal status codes.
grpc_server_retry_throttle_data_record_failure(
calld->retry_throttle_data);
}
}
grpc_closure_run(exec_ctx, calld->original_on_complete,
GRPC_ERROR_REF(error));
}
static void start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error_ignored) {
GPR_TIMER_BEGIN("start_transport_stream_op_locked", 0);
@ -1064,6 +1177,14 @@ static void start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_call_element *elem = op->handler_private.args[0];
call_data *calld = elem->call_data;
if (op->recv_trailing_metadata != NULL) {
GPR_ASSERT(op->on_complete != NULL);
calld->original_on_complete = op->on_complete;
grpc_closure_init(&calld->on_complete, on_complete, elem,
grpc_schedule_on_exec_ctx);
op->on_complete = &calld->on_complete;
}
start_transport_stream_op_locked_inner(exec_ctx, op, elem);
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,

@ -43,6 +43,7 @@
#include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/ext/client_channel/retry_throttle.h"
#include "src/core/ext/client_channel/subchannel_index.h"
#include "src/core/lib/surface/channel_init.h"
@ -82,6 +83,7 @@ static bool set_default_host_if_unset(grpc_exec_ctx *exec_ctx,
void grpc_client_channel_init(void) {
grpc_lb_policy_registry_init();
grpc_resolver_registry_init();
grpc_retry_throttle_map_init();
grpc_proxy_mapper_registry_init();
grpc_register_http_proxy_mapper();
grpc_subchannel_index_init();
@ -96,6 +98,7 @@ void grpc_client_channel_shutdown(void) {
grpc_subchannel_index_shutdown();
grpc_channel_init_shutdown();
grpc_proxy_mapper_registry_shutdown();
grpc_retry_throttle_map_shutdown();
grpc_resolver_registry_shutdown();
grpc_lb_policy_registry_shutdown();
}

@ -48,8 +48,6 @@ struct grpc_connector {
typedef struct {
/** set of pollsets interested in this connection */
grpc_pollset_set *interested_parties;
/** initial connect string to send */
grpc_slice initial_connect_string;
/** deadline for connection */
gpr_timespec deadline;
/** channel arguments (to be passed to transport) */

@ -1,50 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_INITIAL_CONNECT_STRING_H
#define GRPC_CORE_EXT_CLIENT_CHANNEL_INITIAL_CONNECT_STRING_H
#include <grpc/slice.h>
#include "src/core/lib/iomgr/resolve_address.h"
typedef void (*grpc_set_initial_connect_string_func)(
grpc_resolved_address **addr, grpc_slice *initial_str);
void grpc_test_set_initial_connect_string_function(
grpc_set_initial_connect_string_func func);
/** Set a string to be sent once connected. Optionally reset addr. */
void grpc_set_initial_connect_string(grpc_resolved_address **addr,
grpc_slice *connect_string);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_INITIAL_CONNECT_STRING_H */

@ -0,0 +1,210 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/ext/client_channel/retry_throttle.h"
#include <limits.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/atm.h>
#include <grpc/support/avl.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
//
// server_retry_throttle_data
//
struct grpc_server_retry_throttle_data {
gpr_refcount refs;
int max_milli_tokens;
int milli_token_ratio;
gpr_atm milli_tokens;
// A pointer to the replacement for this grpc_server_retry_throttle_data
// entry. If non-NULL, then this entry is stale and must not be used.
// We hold a reference to the replacement.
gpr_atm replacement;
};
static void get_replacement_throttle_data_if_needed(
grpc_server_retry_throttle_data** throttle_data) {
while (true) {
grpc_server_retry_throttle_data* new_throttle_data =
(grpc_server_retry_throttle_data*)gpr_atm_acq_load(
&(*throttle_data)->replacement);
if (new_throttle_data == NULL) return;
*throttle_data = new_throttle_data;
}
}
bool grpc_server_retry_throttle_data_record_failure(
grpc_server_retry_throttle_data* throttle_data) {
// First, check if we are stale and need to be replaced.
get_replacement_throttle_data_if_needed(&throttle_data);
// We decrement milli_tokens by 1000 (1 token) for each failure.
const int new_value = (int)gpr_atm_no_barrier_clamped_add(
&throttle_data->milli_tokens, (gpr_atm)-1000, (gpr_atm)0,
(gpr_atm)throttle_data->max_milli_tokens);
// Retries are allowed as long as the new value is above the threshold
// (max_milli_tokens / 2).
return new_value > throttle_data->max_milli_tokens / 2;
}
void grpc_server_retry_throttle_data_record_success(
grpc_server_retry_throttle_data* throttle_data) {
// First, check if we are stale and need to be replaced.
get_replacement_throttle_data_if_needed(&throttle_data);
// We increment milli_tokens by milli_token_ratio for each success.
gpr_atm_no_barrier_clamped_add(
&throttle_data->milli_tokens, (gpr_atm)throttle_data->milli_token_ratio,
(gpr_atm)0, (gpr_atm)throttle_data->max_milli_tokens);
}
grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_ref(
grpc_server_retry_throttle_data* throttle_data) {
gpr_ref(&throttle_data->refs);
return throttle_data;
}
void grpc_server_retry_throttle_data_unref(
grpc_server_retry_throttle_data* throttle_data) {
if (gpr_unref(&throttle_data->refs)) {
grpc_server_retry_throttle_data* replacement =
(grpc_server_retry_throttle_data*)gpr_atm_acq_load(
&throttle_data->replacement);
if (replacement != NULL) {
grpc_server_retry_throttle_data_unref(replacement);
}
gpr_free(throttle_data);
}
}
static grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_create(
int max_milli_tokens, int milli_token_ratio,
grpc_server_retry_throttle_data* old_throttle_data) {
grpc_server_retry_throttle_data* throttle_data =
gpr_malloc(sizeof(*throttle_data));
memset(throttle_data, 0, sizeof(*throttle_data));
gpr_ref_init(&throttle_data->refs, 1);
throttle_data->max_milli_tokens = max_milli_tokens;
throttle_data->milli_token_ratio = milli_token_ratio;
int initial_milli_tokens = max_milli_tokens;
// If there was a pre-existing entry for this server name, initialize
// the token count by scaling proportionately to the old data. This
// ensures that if we're already throttling retries on the old scale,
// we will start out doing the same thing on the new one.
if (old_throttle_data != NULL) {
double token_fraction =
(int)gpr_atm_acq_load(&old_throttle_data->milli_tokens) /
(double)old_throttle_data->max_milli_tokens;
initial_milli_tokens = (int)(token_fraction * max_milli_tokens);
}
gpr_atm_rel_store(&throttle_data->milli_tokens,
(gpr_atm)initial_milli_tokens);
// If there was a pre-existing entry, mark it as stale and give it a
// pointer to the new entry, which is its replacement.
if (old_throttle_data != NULL) {
grpc_server_retry_throttle_data_ref(throttle_data);
gpr_atm_rel_store(&old_throttle_data->replacement, (gpr_atm)throttle_data);
}
return throttle_data;
}
//
// avl vtable for string -> server_retry_throttle_data map
//
static void* copy_server_name(void* key) { return gpr_strdup(key); }
static long compare_server_name(void* key1, void* key2) {
return strcmp(key1, key2);
}
static void destroy_server_retry_throttle_data(void* value) {
grpc_server_retry_throttle_data* throttle_data = value;
grpc_server_retry_throttle_data_unref(throttle_data);
}
static void* copy_server_retry_throttle_data(void* value) {
grpc_server_retry_throttle_data* throttle_data = value;
return grpc_server_retry_throttle_data_ref(throttle_data);
}
static const gpr_avl_vtable avl_vtable = {
gpr_free /* destroy_key */, copy_server_name, compare_server_name,
destroy_server_retry_throttle_data, copy_server_retry_throttle_data};
//
// server_retry_throttle_map
//
static gpr_mu g_mu;
static gpr_avl g_avl;
void grpc_retry_throttle_map_init() {
gpr_mu_init(&g_mu);
g_avl = gpr_avl_create(&avl_vtable);
}
void grpc_retry_throttle_map_shutdown() {
gpr_mu_destroy(&g_mu);
gpr_avl_unref(g_avl);
}
grpc_server_retry_throttle_data* grpc_retry_throttle_map_get_data_for_server(
const char* server_name, int max_milli_tokens, int milli_token_ratio) {
gpr_mu_lock(&g_mu);
grpc_server_retry_throttle_data* throttle_data =
gpr_avl_get(g_avl, (char*)server_name);
if (throttle_data == NULL) {
// Entry not found. Create a new one.
throttle_data = grpc_server_retry_throttle_data_create(
max_milli_tokens, milli_token_ratio, NULL);
g_avl = gpr_avl_add(g_avl, (char*)server_name, throttle_data);
} else {
if (throttle_data->max_milli_tokens != max_milli_tokens ||
throttle_data->milli_token_ratio != milli_token_ratio) {
// Entry found but with old parameters. Create a new one based on
// the original one.
throttle_data = grpc_server_retry_throttle_data_create(
max_milli_tokens, milli_token_ratio, throttle_data);
g_avl = gpr_avl_add(g_avl, (char*)server_name, throttle_data);
} else {
// Entry found. Increase refcount.
grpc_server_retry_throttle_data_ref(throttle_data);
}
}
gpr_mu_unlock(&g_mu);
return throttle_data;
}

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -31,22 +31,35 @@
*
*/
#include "src/core/ext/client_channel/initial_connect_string.h"
#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_RETRY_THROTTLE_H
#define GRPC_CORE_EXT_CLIENT_CHANNEL_RETRY_THROTTLE_H
#include <stddef.h>
#include <stdbool.h>
extern void grpc_set_default_initial_connect_string(
grpc_resolved_address **addr, grpc_slice *initial_str);
/// Tracks retry throttling data for an individual server name.
typedef struct grpc_server_retry_throttle_data grpc_server_retry_throttle_data;
static grpc_set_initial_connect_string_func g_set_initial_connect_string_func =
grpc_set_default_initial_connect_string;
/// Records a failure. Returns true if it's okay to send a retry.
bool grpc_server_retry_throttle_data_record_failure(
grpc_server_retry_throttle_data* throttle_data);
/// Records a success.
void grpc_server_retry_throttle_data_record_success(
grpc_server_retry_throttle_data* throttle_data);
void grpc_test_set_initial_connect_string_function(
grpc_set_initial_connect_string_func func) {
g_set_initial_connect_string_func = func;
}
grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_ref(
grpc_server_retry_throttle_data* throttle_data);
void grpc_server_retry_throttle_data_unref(
grpc_server_retry_throttle_data* throttle_data);
void grpc_set_initial_connect_string(grpc_resolved_address **addr,
grpc_slice *initial_str) {
g_set_initial_connect_string_func(addr, initial_str);
}
/// Initializes global map of failure data for each server name.
void grpc_retry_throttle_map_init();
/// Shuts down global map of failure data for each server name.
void grpc_retry_throttle_map_shutdown();
/// Returns a reference to the failure data for \a server_name, creating
/// a new entry if needed.
/// Caller must eventually unref via \a grpc_server_retry_throttle_data_unref().
grpc_server_retry_throttle_data* grpc_retry_throttle_map_get_data_for_server(
const char* server_name, int max_milli_tokens, int milli_token_ratio);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RETRY_THROTTLE_H */

@ -41,7 +41,6 @@
#include <grpc/support/string_util.h>
#include "src/core/ext/client_channel/client_channel.h"
#include "src/core/ext/client_channel/initial_connect_string.h"
#include "src/core/ext/client_channel/parse_address.h"
#include "src/core/ext/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/client_channel/subchannel_index.h"
@ -103,9 +102,6 @@ struct grpc_subchannel {
grpc_subchannel_key *key;
/** initial string to send to peer */
grpc_slice initial_connect_string;
/** set during connection */
grpc_connect_out_args connecting_result;
@ -215,7 +211,6 @@ static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg,
grpc_subchannel *c = arg;
gpr_free((void *)c->filters);
grpc_channel_args_destroy(exec_ctx, c->args);
grpc_slice_unref_internal(exec_ctx, c->initial_connect_string);
grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker);
grpc_connector_unref(exec_ctx, c->connector);
grpc_pollset_set_destroy(exec_ctx, c->pollset_set);
@ -333,7 +328,6 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
c->pollset_set = grpc_pollset_set_create();
grpc_resolved_address *addr = gpr_malloc(sizeof(*addr));
grpc_get_subchannel_address_arg(exec_ctx, args->args, addr);
grpc_set_initial_connect_string(&addr, &c->initial_connect_string);
grpc_resolved_address *new_address = NULL;
grpc_channel_args *new_args = NULL;
if (grpc_proxy_mappers_map_address(exec_ctx, addr, args->args, &new_address,
@ -404,7 +398,6 @@ static void continue_connect_locked(grpc_exec_ctx *exec_ctx,
args.interested_parties = c->pollset_set;
args.deadline = c->next_attempt;
args.channel_args = c->args;
args.initial_connect_string = c->initial_connect_string;
grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE,

@ -423,11 +423,13 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
"This LB policy doesn't support user data. It will be ignored");
}
static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS};
memset(&sc_args, 0, sizeof(grpc_subchannel_args));
grpc_arg addr_arg =
grpc_create_subchannel_address_arg(&addresses->addresses[i].address);
grpc_channel_args *new_args =
grpc_channel_args_copy_and_add(args->args, &addr_arg, 1);
grpc_channel_args *new_args = grpc_channel_args_copy_and_add_and_remove(
args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &addr_arg,
1);
gpr_free(addr_arg.value.string);
sc_args.args = new_args;
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(

@ -709,11 +709,13 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
/* Skip balancer addresses, since we only know how to handle backends. */
if (addresses->addresses[i].is_balancer) continue;
static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS};
memset(&sc_args, 0, sizeof(grpc_subchannel_args));
grpc_arg addr_arg =
grpc_create_subchannel_address_arg(&addresses->addresses[i].address);
grpc_channel_args *new_args =
grpc_channel_args_copy_and_add(args->args, &addr_arg, 1);
grpc_channel_args *new_args = grpc_channel_args_copy_and_add_and_remove(
args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &addr_arg,
1);
gpr_free(addr_arg.value.string);
sc_args.args = new_args;
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(

@ -63,8 +63,6 @@ typedef struct {
grpc_closure *notify;
grpc_connect_in_args args;
grpc_connect_out_args *result;
grpc_closure initial_string_sent;
grpc_slice_buffer initial_string_buffer;
grpc_endpoint *endpoint; // Non-NULL until handshaking starts.
@ -82,7 +80,6 @@ static void chttp2_connector_unref(grpc_exec_ctx *exec_ctx,
grpc_connector *con) {
chttp2_connector *c = (chttp2_connector *)con;
if (gpr_unref(&c->refs)) {
/* c->initial_string_buffer does not need to be destroyed */
gpr_mu_destroy(&c->mu);
// If handshaking is not yet in progress, destroy the endpoint.
// Otherwise, the handshaker will do this for us.
@ -160,28 +157,6 @@ static void start_handshake_locked(grpc_exec_ctx *exec_ctx,
c->endpoint = NULL; // Endpoint handed off to handshake manager.
}
static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
chttp2_connector *c = arg;
gpr_mu_lock(&c->mu);
if (error != GRPC_ERROR_NONE || c->shutdown) {
if (error == GRPC_ERROR_NONE) {
error = GRPC_ERROR_CREATE("connector shutdown");
} else {
error = GRPC_ERROR_REF(error);
}
memset(c->result, 0, sizeof(*c->result));
grpc_closure *notify = c->notify;
c->notify = NULL;
grpc_closure_sched(exec_ctx, notify, error);
gpr_mu_unlock(&c->mu);
chttp2_connector_unref(exec_ctx, arg);
} else {
start_handshake_locked(exec_ctx, c);
gpr_mu_unlock(&c->mu);
}
}
static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
chttp2_connector *c = arg;
gpr_mu_lock(&c->mu);
@ -204,17 +179,7 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
chttp2_connector_unref(exec_ctx, arg);
} else {
GPR_ASSERT(c->endpoint != NULL);
if (!GRPC_SLICE_IS_EMPTY(c->args.initial_connect_string)) {
grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent,
c, grpc_schedule_on_exec_ctx);
grpc_slice_buffer_init(&c->initial_string_buffer);
grpc_slice_buffer_add(&c->initial_string_buffer,
c->args.initial_connect_string);
grpc_endpoint_write(exec_ctx, c->endpoint, &c->initial_string_buffer,
&c->initial_string_sent);
} else {
start_handshake_locked(exec_ctx, c);
}
start_handshake_locked(exec_ctx, c);
gpr_mu_unlock(&c->mu);
}
}

@ -1765,6 +1765,7 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_stream *s, grpc_error *error) {
grpc_slice hdr;
grpc_slice status_hdr;
grpc_slice http_status_hdr;
grpc_slice message_pfx;
uint8_t *p;
uint32_t len = 0;
@ -1780,6 +1781,26 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
It's complicated by the fact that our send machinery would be dead by
the time we got around to sending this, so instead we ignore HPACK
compression and just write the uncompressed bytes onto the wire. */
if (!s->sent_initial_metadata) {
http_status_hdr = grpc_slice_malloc(13);
p = GRPC_SLICE_START_PTR(http_status_hdr);
*p++ = 0x00;
*p++ = 7;
*p++ = ':';
*p++ = 's';
*p++ = 't';
*p++ = 'a';
*p++ = 't';
*p++ = 'u';
*p++ = 's';
*p++ = 3;
*p++ = '2';
*p++ = '0';
*p++ = '0';
GPR_ASSERT(p == GRPC_SLICE_END_PTR(http_status_hdr));
len += (uint32_t)GRPC_SLICE_LENGTH(http_status_hdr);
}
status_hdr = grpc_slice_malloc(15 + (grpc_status >= 10));
p = GRPC_SLICE_START_PTR(status_hdr);
*p++ = 0x00; /* literal header, not indexed */
@ -1847,6 +1868,9 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr));
grpc_slice_buffer_add(&t->qbuf, hdr);
if (!s->sent_initial_metadata) {
grpc_slice_buffer_add(&t->qbuf, http_status_hdr);
}
grpc_slice_buffer_add(&t->qbuf, status_hdr);
if (msg != NULL) {
grpc_slice_buffer_add(&t->qbuf, message_pfx);

@ -1620,13 +1620,18 @@ void grpc_chttp2_hpack_parser_destroy(grpc_exec_ctx *exec_ctx,
grpc_error *grpc_chttp2_hpack_parser_parse(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_parser *p,
grpc_slice slice) {
/* TODO(ctiller): limit the distance of end from beg, and perform multiple
steps in the event of a large chunk of data to limit
stack space usage when no tail call optimization is
available */
/* max number of bytes to parse at a time... limits call stack depth on
* compilers without TCO */
#define MAX_PARSE_LENGTH 1024
p->current_slice_refcount = slice.refcount;
grpc_error *error = p->state(exec_ctx, p, GRPC_SLICE_START_PTR(slice),
GRPC_SLICE_END_PTR(slice));
uint8_t *start = GRPC_SLICE_START_PTR(slice);
uint8_t *end = GRPC_SLICE_END_PTR(slice);
grpc_error *error = GRPC_ERROR_NONE;
while (start != end && error == GRPC_ERROR_NONE) {
uint8_t *target = start + GPR_MIN(MAX_PARSE_LENGTH, end - start);
error = p->state(exec_ctx, p, start, target);
start = target;
}
p->current_slice_refcount = NULL;
return error;
}

@ -128,6 +128,7 @@ struct read_state {
int received_bytes;
int remaining_bytes;
int length_field;
bool compressed;
char grpc_header_bytes[GRPC_HEADER_SIZE_IN_BYTES];
char *payload_field;
bool read_stream_closed;
@ -484,6 +485,16 @@ static void on_response_headers_received(
CRONET_LOG(GPR_DEBUG, "R: on_response_headers_received(%p, %p, %s)", stream,
headers, negotiated_protocol);
stream_obj *s = (stream_obj *)stream->annotation;
/* Identify if this is a header or a trailer (in a trailer-only response case)
*/
for (size_t i = 0; i < headers->count; i++) {
if (0 == strcmp("grpc-status", headers->headers[i].key)) {
on_response_trailers_received(stream, headers);
return;
}
}
gpr_mu_lock(&s->mu);
memset(&s->state.rs.initial_metadata, 0,
sizeof(s->state.rs.initial_metadata));
@ -507,6 +518,7 @@ static void on_response_headers_received(
is closed */
GPR_ASSERT(s->state.rs.length_field_received == false);
s->state.rs.read_buffer = s->state.rs.grpc_header_bytes;
s->state.rs.compressed = false;
s->state.rs.received_bytes = 0;
s->state.rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES;
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs);
@ -641,7 +653,7 @@ static void on_response_trailers_received(
*/
static void create_grpc_frame(grpc_slice_buffer *write_slice_buffer,
char **pp_write_buffer,
size_t *p_write_buffer_size) {
size_t *p_write_buffer_size, uint32_t flags) {
grpc_slice slice = grpc_slice_buffer_take_first(write_slice_buffer);
size_t length = GRPC_SLICE_LENGTH(slice);
*p_write_buffer_size = length + GRPC_HEADER_SIZE_IN_BYTES;
@ -650,7 +662,9 @@ static void create_grpc_frame(grpc_slice_buffer *write_slice_buffer,
*pp_write_buffer = write_buffer;
uint8_t *p = (uint8_t *)write_buffer;
/* Append 5 byte header */
*p++ = 0;
/* Compressed flag */
*p++ = (flags & GRPC_WRITE_INTERNAL_COMPRESS) ? 1 : 0;
/* Message length */
*p++ = (uint8_t)(length >> 24);
*p++ = (uint8_t)(length >> 16);
*p++ = (uint8_t)(length >> 8);
@ -728,14 +742,16 @@ static void convert_metadata_to_cronet_headers(
*p_num_headers = (size_t)num_headers;
}
static int parse_grpc_header(const uint8_t *data) {
static void parse_grpc_header(const uint8_t *data, int *length,
bool *compressed) {
const uint8_t c = *data;
const uint8_t *p = data + 1;
int length = 0;
length |= ((uint8_t)*p++) << 24;
length |= ((uint8_t)*p++) << 16;
length |= ((uint8_t)*p++) << 8;
length |= ((uint8_t)*p++);
return length;
*compressed = ((c & 0x01) == 0x01);
*length = 0;
*length |= ((uint8_t)*p++) << 24;
*length |= ((uint8_t)*p++) << 16;
*length |= ((uint8_t)*p++) << 8;
*length |= ((uint8_t)*p++);
}
static bool header_has_authority(grpc_linked_mdelem *head) {
@ -788,7 +804,8 @@ static bool op_can_be_run(grpc_transport_stream_op *curr_op,
else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA])
result = false;
/* we haven't received headers yet. */
else if (!stream_state->state_callback_received[OP_RECV_INITIAL_METADATA])
else if (!stream_state->state_callback_received[OP_RECV_INITIAL_METADATA] &&
!stream_state->state_op_done[OP_RECV_TRAILING_METADATA])
result = false;
} else if (op_id == OP_SEND_MESSAGE) {
/* already executed (note we're checking op specific state, not stream
@ -801,7 +818,8 @@ static bool op_can_be_run(grpc_transport_stream_op *curr_op,
/* already executed */
if (op_state->state_op_done[OP_RECV_MESSAGE]) result = false;
/* we haven't received headers yet. */
else if (!stream_state->state_callback_received[OP_RECV_INITIAL_METADATA])
else if (!stream_state->state_callback_received[OP_RECV_INITIAL_METADATA] &&
!stream_state->state_op_done[OP_RECV_TRAILING_METADATA])
result = false;
} else if (op_id == OP_RECV_TRAILING_METADATA) {
/* already executed */
@ -955,12 +973,6 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
grpc_slice_buffer_init(&write_slice_buffer);
grpc_byte_stream_next(NULL, stream_op->send_message, &slice,
stream_op->send_message->length, NULL);
/* Check that compression flag is OFF. We don't support compression yet.
*/
if (stream_op->send_message->flags != 0) {
gpr_log(GPR_ERROR, "Compression is not supported");
GPR_ASSERT(stream_op->send_message->flags == 0);
}
grpc_slice_buffer_add(&write_slice_buffer, slice);
if (write_slice_buffer.count != 1) {
/* Empty request not handled yet */
@ -970,7 +982,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
if (write_slice_buffer.count > 0) {
size_t write_buffer_size;
create_grpc_frame(&write_slice_buffer, &stream_state->ws.write_buffer,
&write_buffer_size);
&write_buffer_size, stream_op->send_message->flags);
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, %p)", s->cbs,
stream_state->ws.write_buffer);
stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
@ -1022,6 +1034,9 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
} else if (stream_state->state_callback_received[OP_FAILED]) {
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
GRPC_ERROR_NONE);
} else if (stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) {
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
GRPC_ERROR_NONE);
} else {
grpc_chttp2_incoming_metadata_buffer_publish(
exec_ctx, &oas->s->state.rs.initial_metadata,
@ -1066,8 +1081,9 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
stream_state->rs.remaining_bytes == 0) {
/* Start a read operation for data */
stream_state->rs.length_field_received = true;
stream_state->rs.length_field = stream_state->rs.remaining_bytes =
parse_grpc_header((const uint8_t *)stream_state->rs.read_buffer);
parse_grpc_header((const uint8_t *)stream_state->rs.read_buffer,
&stream_state->rs.length_field,
&stream_state->rs.compressed);
CRONET_LOG(GPR_DEBUG, "length field = %d",
stream_state->rs.length_field);
if (stream_state->rs.length_field > 0) {
@ -1089,6 +1105,9 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
grpc_slice_buffer_init(&stream_state->rs.read_slice_buffer);
grpc_slice_buffer_stream_init(&stream_state->rs.sbs,
&stream_state->rs.read_slice_buffer, 0);
if (stream_state->rs.compressed) {
stream_state->rs.sbs.base.flags |= GRPC_WRITE_INTERNAL_COMPRESS;
}
*((grpc_byte_buffer **)stream_op->recv_message) =
(grpc_byte_buffer *)&stream_state->rs.sbs;
grpc_closure_sched(exec_ctx, stream_op->recv_message_ready,
@ -1100,6 +1119,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes;
stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES;
stream_state->rs.received_bytes = 0;
stream_state->rs.compressed = false;
stream_state->rs.length_field_received = false;
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs);
stream_state->state_op_done[OP_READ_REQ_MADE] =
@ -1114,6 +1134,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes;
stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES;
stream_state->rs.received_bytes = 0;
stream_state->rs.compressed = false;
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs);
stream_state->state_op_done[OP_READ_REQ_MADE] =
true; /* Indicates that at least one read request has been made */
@ -1137,6 +1158,9 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
read_data_slice);
grpc_slice_buffer_stream_init(&stream_state->rs.sbs,
&stream_state->rs.read_slice_buffer, 0);
if (stream_state->rs.compressed) {
stream_state->rs.sbs.base.flags = GRPC_WRITE_INTERNAL_COMPRESS;
}
*((grpc_byte_buffer **)stream_op->recv_message) =
(grpc_byte_buffer *)&stream_state->rs.sbs;
grpc_closure_sched(exec_ctx, stream_op->recv_message_ready,
@ -1146,6 +1170,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
/* Do an extra read to trigger on_succeeded() callback in case connection
is closed */
stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes;
stream_state->rs.compressed = false;
stream_state->rs.received_bytes = 0;
stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES;
stream_state->rs.length_field_received = false;

@ -33,6 +33,7 @@
#include "src/core/lib/iomgr/closure.h"
#include <assert.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@ -124,6 +125,7 @@ void grpc_closure_run(grpc_exec_ctx *exec_ctx, grpc_closure *c,
grpc_error *error) {
GPR_TIMER_BEGIN("grpc_closure_run", 0);
if (c != NULL) {
assert(c->cb);
c->scheduler->vtable->run(exec_ctx, c, error);
} else {
GRPC_ERROR_UNREF(error);
@ -135,6 +137,7 @@ void grpc_closure_sched(grpc_exec_ctx *exec_ctx, grpc_closure *c,
grpc_error *error) {
GPR_TIMER_BEGIN("grpc_closure_sched", 0);
if (c != NULL) {
assert(c->cb);
c->scheduler->vtable->sched(exec_ctx, c, error);
} else {
GRPC_ERROR_UNREF(error);
@ -146,6 +149,7 @@ void grpc_closure_list_sched(grpc_exec_ctx *exec_ctx, grpc_closure_list *list) {
grpc_closure *c = list->head;
while (c != NULL) {
grpc_closure *next = c->next_data.next;
assert(c->cb);
c->scheduler->vtable->sched(exec_ctx, c, c->error_data.error);
c = next;
}

@ -33,6 +33,7 @@
#include "src/core/lib/iomgr/combiner.h"
#include <assert.h>
#include <string.h>
#include <grpc/support/alloc.h>
@ -216,6 +217,7 @@ static void combiner_exec(grpc_exec_ctx *exec_ctx, grpc_combiner *lock,
GPR_DEBUG, "C:%p grpc_combiner_execute c=%p cov=%d last=%" PRIdPTR, lock,
cl, covered_by_poller, last));
GPR_ASSERT(last & STATE_UNORPHANED); // ensure lock has not been destroyed
assert(cl->cb);
cl->error_data.scratch =
pack_error_data((error_data){error, covered_by_poller});
if (covered_by_poller) {

@ -45,28 +45,9 @@ extern "C" {
#endif
/// Opaque representation of an error.
/// Errors are refcounted objects that represent the result of an operation.
/// Ownership laws:
/// if a grpc_error is returned by a function, the caller owns a ref to that
/// instance
/// if a grpc_error is passed to a grpc_closure callback function (functions
/// with the signature:
/// void (*f)(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error))
/// then those functions do not own a ref to error (but are free to manually
/// take a reference).
/// if a grpc_error is passed to *ANY OTHER FUNCTION* then that function takes
/// ownership of the error
/// Errors have:
/// a set of ints, strings, and timestamps that describe the error
/// always present are:
/// GRPC_ERROR_STR_FILE, GRPC_ERROR_INT_FILE_LINE - source location the error
/// was generated
/// GRPC_ERROR_STR_DESCRIPTION - a human readable description of the error
/// GRPC_ERROR_TIME_CREATED - a timestamp indicating when the error happened
/// an error can also have children; these are other errors that are believed
/// to have contributed to this one. By accumulating children, we can begin
/// to root cause high level failures from low level failures, without having
/// to derive execution paths from log lines
/// See https://github.com/grpc/grpc/blob/master/doc/core/grpc-error.md for a
/// full write up of this object.
typedef struct grpc_error grpc_error;
typedef enum {

@ -1421,7 +1421,7 @@ static int cvfd_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
g_cvfds.pollcount++;
opt = gpr_thd_options_default();
gpr_thd_options_set_detached(&opt);
gpr_thd_new(&t_id, &run_poll, pargs, &opt);
GPR_ASSERT(gpr_thd_new(&t_id, &run_poll, pargs, &opt));
// We want the poll() thread to trigger the deadline, so wait forever here
gpr_cv_wait(pollcv, &g_cvfds.mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
if (gpr_atm_no_barrier_load(&pargs->status) == COMPLETED) {

@ -115,8 +115,8 @@ static void maybe_spawn_locked() {
/* All previous instances of the thread should have been joined at this point.
* Spawn time! */
g_executor.busy = 1;
gpr_thd_new(&g_executor.tid, closure_exec_thread_func, NULL,
&g_executor.options);
GPR_ASSERT(gpr_thd_new(&g_executor.tid, closure_exec_thread_func, NULL,
&g_executor.options));
g_executor.pending_join = 1;
}

@ -350,8 +350,20 @@ static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s,
}
}
if (*out_port > 0) {
GRPC_LOG_IF_ERROR("Failed to add :: listener", v6_err);
GRPC_LOG_IF_ERROR("Failed to add 0.0.0.0 listener", v4_err);
if (v6_err != GRPC_ERROR_NONE) {
gpr_log(GPR_INFO,
"Failed to add :: listener, "
"the environment may not support IPv6: %s",
grpc_error_string(v6_err));
GRPC_ERROR_UNREF(v6_err);
}
if (v4_err != GRPC_ERROR_NONE) {
gpr_log(GPR_INFO,
"Failed to add 0.0.0.0 listener, "
"the environment may not support IPv4: %s",
grpc_error_string(v4_err));
GRPC_ERROR_UNREF(v4_err);
}
return GRPC_ERROR_NONE;
} else {
grpc_error *root_err =

@ -218,7 +218,7 @@ void gpr_timers_set_log_filename(const char *filename) {
static void init_output() {
gpr_thd_options options = gpr_thd_options_default();
gpr_thd_options_set_joinable(&options);
gpr_thd_new(&g_writing_thread, writing_thread, NULL, &options);
GPR_ASSERT(gpr_thd_new(&g_writing_thread, writing_thread, NULL, &options));
atexit(finish_writing);
}

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -31,8 +31,17 @@
*
*/
#include <grpc/slice.h>
#include "src/core/lib/iomgr/resolve_address.h"
#include <grpc/support/atm.h>
#include <grpc/support/useful.h>
void grpc_set_default_initial_connect_string(grpc_resolved_address **addr,
grpc_slice *initial_str) {}
gpr_atm gpr_atm_no_barrier_clamped_add(gpr_atm *value, gpr_atm delta,
gpr_atm min, gpr_atm max) {
gpr_atm current;
gpr_atm new;
do {
current = gpr_atm_no_barrier_load(value);
new = GPR_CLAMP(current + delta, min, max);
if (new == current) break;
} while (!gpr_atm_no_barrier_cas(value, current, new));
return new;
}

@ -93,6 +93,18 @@ void grpc_service_config_destroy(grpc_service_config* service_config) {
gpr_free(service_config);
}
void grpc_service_config_parse_global_params(
const grpc_service_config* service_config,
void (*process_json)(const grpc_json* json, void* arg), void* arg) {
const grpc_json* json = service_config->json_tree;
if (json->type != GRPC_JSON_OBJECT || json->key != NULL) return;
for (grpc_json* field = json->child; field != NULL; field = field->next) {
if (field->key == NULL) return;
if (strcmp(field->key, "methodConfig") == 0) continue;
process_json(field, arg);
}
}
const char* grpc_service_config_get_lb_policy_name(
const grpc_service_config* service_config) {
const grpc_json* json = service_config->json_tree;

@ -42,6 +42,12 @@ typedef struct grpc_service_config grpc_service_config;
grpc_service_config* grpc_service_config_create(const char* json_string);
void grpc_service_config_destroy(grpc_service_config* service_config);
/// Invokes \a process_json() for each global parameter in the service
/// config. \a arg is passed as the second argument to \a process_json().
void grpc_service_config_parse_global_params(
const grpc_service_config* service_config,
void (*process_json)(const grpc_json* json, void* arg), void* arg);
/// Gets the LB policy name from \a service_config.
/// Returns NULL if no LB policy name was specified.
/// Caller does NOT take ownership.

@ -273,8 +273,7 @@ static char *roots_filename;
}
- (void)testCompressedPayload {
// NOT SUPPORTED
// [self testIndividualCase:"compressed_payload"];
[self testIndividualCase:"compressed_payload"];
}
- (void)testConnectivity {

@ -34,6 +34,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/profiling/stap_timers.c',
'src/core/lib/support/alloc.c',
'src/core/lib/support/arena.c',
'src/core/lib/support/atm.c',
'src/core/lib/support/avl.c',
'src/core/lib/support/backoff.c',
'src/core/lib/support/cmdline.c',
@ -254,10 +255,8 @@ CORE_SOURCE_FILES = [
'src/core/ext/client_channel/client_channel_factory.c',
'src/core/ext/client_channel/client_channel_plugin.c',
'src/core/ext/client_channel/connector.c',
'src/core/ext/client_channel/default_initial_connect_string.c',
'src/core/ext/client_channel/http_connect_handshaker.c',
'src/core/ext/client_channel/http_proxy.c',
'src/core/ext/client_channel/initial_connect_string.c',
'src/core/ext/client_channel/lb_policy.c',
'src/core/ext/client_channel/lb_policy_factory.c',
'src/core/ext/client_channel/lb_policy_registry.c',
@ -267,6 +266,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/client_channel/resolver.c',
'src/core/ext/client_channel/resolver_factory.c',
'src/core/ext/client_channel/resolver_registry.c',
'src/core/ext/client_channel/retry_throttle.c',
'src/core/ext/client_channel/subchannel.c',
'src/core/ext/client_channel/subchannel_index.c',
'src/core/ext/client_channel/uri_parser.c',

@ -32,7 +32,7 @@ from concurrent import futures
import unittest
import grpc
from src.proto.grpc.testing import test_pb2
from src.proto.grpc.testing import test_pb2_grpc
from tests.interop import _intraop_test_case
from tests.interop import methods
@ -44,11 +44,11 @@ class InsecureIntraopTest(_intraop_test_case.IntraopTestCase,
def setUp(self):
self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
test_pb2.add_TestServiceServicer_to_server(methods.TestService(),
self.server)
test_pb2_grpc.add_TestServiceServicer_to_server(methods.TestService(),
self.server)
port = self.server.add_insecure_port('[::]:0')
self.server.start()
self.stub = test_pb2.TestServiceStub(
self.stub = test_pb2_grpc.TestServiceStub(
grpc.insecure_channel('localhost:{}'.format(port)))

@ -32,7 +32,7 @@ from concurrent import futures
import unittest
import grpc
from src.proto.grpc.testing import test_pb2
from src.proto.grpc.testing import test_pb2_grpc
from tests.interop import _intraop_test_case
from tests.interop import methods
@ -45,14 +45,14 @@ class SecureIntraopTest(_intraop_test_case.IntraopTestCase, unittest.TestCase):
def setUp(self):
self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
test_pb2.add_TestServiceServicer_to_server(methods.TestService(),
self.server)
test_pb2_grpc.add_TestServiceServicer_to_server(methods.TestService(),
self.server)
port = self.server.add_secure_port(
'[::]:0',
grpc.ssl_server_credentials(
[(resources.private_key(), resources.certificate_chain())]))
self.server.start()
self.stub = test_pb2.TestServiceStub(
self.stub = test_pb2_grpc.TestServiceStub(
grpc.secure_channel('localhost:{}'.format(port),
grpc.ssl_channel_credentials(
resources.test_root_certificates()), (

@ -40,7 +40,7 @@ from grpc.beta import implementations
from src.proto.grpc.testing import empty_pb2
from src.proto.grpc.testing import messages_pb2
from src.proto.grpc.testing import test_pb2
from src.proto.grpc.testing import test_pb2_grpc
_INITIAL_METADATA_KEY = "x-grpc-test-echo-initial"
_TRAILING_METADATA_KEY = "x-grpc-test-echo-trailing-bin"
@ -66,7 +66,7 @@ def _maybe_echo_status_and_message(request, servicer_context):
servicer_context.set_details(request.response_status.message)
class TestService(test_pb2.TestServiceServicer):
class TestService(test_pb2_grpc.TestServiceServicer):
def EmptyCall(self, request, context):
_maybe_echo_metadata(context)

@ -34,7 +34,7 @@ import logging
import time
import grpc
from src.proto.grpc.testing import test_pb2
from src.proto.grpc.testing import test_pb2_grpc
from tests.interop import methods
from tests.interop import resources
@ -53,7 +53,8 @@ def serve():
args = parser.parse_args()
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
test_pb2.add_TestServiceServicer_to_server(methods.TestService(), server)
test_pb2_grpc.add_TestServiceServicer_to_server(methods.TestService(),
server)
if args.use_tls:
private_key = resources.private_key()
certificate_chain = resources.certificate_chain()

@ -33,7 +33,7 @@ import time
from concurrent import futures
import grpc
from src.proto.grpc.testing import services_pb2
from src.proto.grpc.testing import services_pb2_grpc
from tests.qps import worker_server
@ -41,7 +41,7 @@ from tests.qps import worker_server
def run_worker_server(port):
server = grpc.server(futures.ThreadPoolExecutor(max_workers=5))
servicer = worker_server.WorkerServer()
services_pb2.add_WorkerServiceServicer_to_server(servicer, server)
services_pb2_grpc.add_WorkerServiceServicer_to_server(servicer, server)
server.add_insecure_port('[::]:{}'.format(port))
server.start()
servicer.wait_for_quit()

@ -35,7 +35,7 @@ import time
from concurrent import futures
import grpc
from src.proto.grpc.testing import control_pb2
from src.proto.grpc.testing import services_pb2
from src.proto.grpc.testing import services_pb2_grpc
from src.proto.grpc.testing import stats_pb2
from tests.qps import benchmark_client
@ -45,7 +45,7 @@ from tests.qps import histogram
from tests.unit import resources
class WorkerServer(services_pb2.WorkerServiceServicer):
class WorkerServer(services_pb2_grpc.WorkerServiceServicer):
"""Python Worker Server implementation."""
def __init__(self):
@ -87,8 +87,8 @@ class WorkerServer(services_pb2.WorkerServiceServicer):
futures.ThreadPoolExecutor(max_workers=server_threads))
if config.server_type == control_pb2.ASYNC_SERVER:
servicer = benchmark_server.BenchmarkServer()
services_pb2.add_BenchmarkServiceServicer_to_server(servicer,
server)
services_pb2_grpc.add_BenchmarkServiceServicer_to_server(servicer,
server)
elif config.server_type == control_pb2.ASYNC_GENERIC_SERVER:
resp_size = config.payload_config.bytebuf_params.resp_size
servicer = benchmark_server.GenericBenchmarkServer(resp_size)

@ -34,6 +34,7 @@ import grpc
from grpc.framework.foundation import logging_pool
from grpc_reflection.v1alpha import reflection
from grpc_reflection.v1alpha import reflection_pb2
from grpc_reflection.v1alpha import reflection_pb2_grpc
from google.protobuf import descriptor_pool
from google.protobuf import descriptor_pb2
@ -61,12 +62,12 @@ class ReflectionServicerTest(unittest.TestCase):
server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY)
self._server = grpc.server(server_pool)
port = self._server.add_insecure_port('[::]:0')
reflection_pb2.add_ServerReflectionServicer_to_server(servicer,
self._server)
reflection_pb2_grpc.add_ServerReflectionServicer_to_server(servicer,
self._server)
self._server.start()
channel = grpc.insecure_channel('localhost:%d' % port)
self._stub = reflection_pb2.ServerReflectionStub(channel)
self._stub = reflection_pb2_grpc.ServerReflectionStub(channel)
def testFileByName(self):
requests = (reflection_pb2.ServerReflectionRequest(

@ -34,7 +34,7 @@ import threading
import grpc
from six.moves import queue
from src.proto.grpc.testing import metrics_pb2
from src.proto.grpc.testing import metrics_pb2_grpc
from src.proto.grpc.testing import test_pb2
from tests.interop import methods
@ -139,7 +139,7 @@ def run_test(args):
runners = []
server = grpc.server(futures.ThreadPoolExecutor(max_workers=25))
metrics_pb2.add_MetricsServiceServicer_to_server(
metrics_pb2_grpc.add_MetricsServiceServicer_to_server(
metrics_server.MetricsServer(hist), server)
server.add_insecure_port('[::]:{}'.format(args.metrics_port))
server.start()

@ -45,10 +45,3 @@ cc_test(
deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:cq_verifier"],
copts = ['-std=c99']
)
cc_test(
name = "set_initial_connect_string_test",
srcs = ["set_initial_connect_string_test.c"],
deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
copts = ['-std=c99']
)

@ -1,268 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when
using that endpoint. Because of various transitive includes in uv.h,
including windows.h on Windows, uv.h must be included before other system
headers. Therefore, sockaddr.h must always be included first */
#include "src/core/lib/iomgr/sockaddr.h"
#include <string.h>
#include <grpc/grpc.h>
#include <grpc/slice.h>
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/thd.h>
#include "src/core/ext/client_channel/initial_connect_string.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/security/credentials/fake/fake_credentials.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/core/util/test_tcp_server.h"
struct rpc_state {
char *target;
grpc_channel_credentials *creds;
grpc_completion_queue *cq;
grpc_channel *channel;
grpc_call *call;
grpc_op op;
grpc_slice_buffer incoming_buffer;
grpc_slice_buffer temp_incoming_buffer;
grpc_endpoint *tcp;
gpr_atm done_atm;
};
static const char *magic_connect_string = "magic initial string";
static int server_port;
static struct rpc_state state;
static grpc_closure on_read;
static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
GPR_ASSERT(error == GRPC_ERROR_NONE);
grpc_slice_buffer_move_into(&state.temp_incoming_buffer,
&state.incoming_buffer);
gpr_log(GPR_DEBUG, "got %" PRIuPTR " bytes, magic is %" PRIuPTR " bytes",
state.incoming_buffer.length, strlen(magic_connect_string));
if (state.incoming_buffer.length > strlen(magic_connect_string)) {
gpr_atm_rel_store(&state.done_atm, 1);
grpc_endpoint_shutdown(
exec_ctx, state.tcp,
GRPC_ERROR_CREATE("Incoming buffer longer than magic_connect_string"));
grpc_endpoint_destroy(exec_ctx, state.tcp);
} else {
grpc_endpoint_read(exec_ctx, state.tcp, &state.temp_incoming_buffer,
&on_read);
}
}
static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
grpc_pollset *accepting_pollset,
grpc_tcp_server_acceptor *acceptor) {
gpr_free(acceptor);
test_tcp_server *server = arg;
grpc_closure_init(&on_read, handle_read, NULL, grpc_schedule_on_exec_ctx);
grpc_slice_buffer_init(&state.incoming_buffer);
grpc_slice_buffer_init(&state.temp_incoming_buffer);
state.tcp = tcp;
grpc_endpoint_add_to_pollset(exec_ctx, tcp, server->pollset);
grpc_endpoint_read(exec_ctx, tcp, &state.temp_incoming_buffer, &on_read);
}
static void set_magic_initial_string(grpc_resolved_address **addr,
grpc_slice *connect_string) {
GPR_ASSERT(addr);
GPR_ASSERT((*addr)->len);
*connect_string = grpc_slice_from_copied_string(magic_connect_string);
}
static void reset_addr_and_set_magic_string(grpc_resolved_address **addr,
grpc_slice *connect_string) {
struct sockaddr_in target;
*connect_string = grpc_slice_from_copied_string(magic_connect_string);
gpr_free(*addr);
target.sin_family = AF_INET;
target.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
target.sin_port = htons((uint16_t)server_port);
*addr = (grpc_resolved_address *)gpr_malloc(sizeof(grpc_resolved_address));
(*addr)->len = sizeof(target);
memcpy((*addr)->addr, &target, sizeof(target));
}
static gpr_timespec n_sec_deadline(int seconds) {
return gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_seconds(seconds, GPR_TIMESPAN));
}
static void start_rpc(int use_creds, int target_port) {
state.cq = grpc_completion_queue_create(NULL);
if (use_creds) {
state.creds = grpc_fake_transport_security_credentials_create();
} else {
state.creds = NULL;
}
gpr_join_host_port(&state.target, "127.0.0.1", target_port);
if (use_creds) {
state.channel =
grpc_secure_channel_create(state.creds, state.target, NULL, NULL);
} else {
state.channel = grpc_insecure_channel_create(state.target, NULL, NULL);
}
grpc_slice host = grpc_slice_from_static_string("localhost");
state.call = grpc_channel_create_call(
state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq,
grpc_slice_from_static_string("/Service/Method"), &host,
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
memset(&state.op, 0, sizeof(state.op));
state.op.op = GRPC_OP_SEND_INITIAL_METADATA;
state.op.data.send_initial_metadata.count = 0;
state.op.flags = 0;
state.op.reserved = NULL;
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(state.call, &state.op,
(size_t)(1), NULL, NULL));
grpc_completion_queue_next(state.cq, n_sec_deadline(5), NULL);
}
static void cleanup_rpc(void) {
grpc_event ev;
grpc_slice_buffer_destroy(&state.incoming_buffer);
grpc_slice_buffer_destroy(&state.temp_incoming_buffer);
grpc_channel_credentials_release(state.creds);
grpc_call_destroy(state.call);
grpc_completion_queue_shutdown(state.cq);
do {
ev = grpc_completion_queue_next(state.cq, n_sec_deadline(1), NULL);
} while (ev.type != GRPC_QUEUE_SHUTDOWN);
grpc_completion_queue_destroy(state.cq);
grpc_channel_destroy(state.channel);
gpr_free(state.target);
}
typedef struct {
test_tcp_server *server;
gpr_event *signal_when_done;
} poll_args;
static void actually_poll_server(void *arg) {
poll_args *pa = arg;
gpr_timespec deadline = n_sec_deadline(10);
while (true) {
bool done = gpr_atm_acq_load(&state.done_atm) != 0;
gpr_timespec time_left =
gpr_time_sub(deadline, gpr_now(GPR_CLOCK_REALTIME));
gpr_log(GPR_DEBUG, "done=%d, time_left=%" PRId64 ".%09" PRId32, done,
time_left.tv_sec, time_left.tv_nsec);
if (done || gpr_time_cmp(time_left, gpr_time_0(GPR_TIMESPAN)) < 0) {
break;
}
test_tcp_server_poll(pa->server, 1);
}
gpr_event_set(pa->signal_when_done, (void *)1);
gpr_free(pa);
}
static void poll_server_until_read_done(test_tcp_server *server,
gpr_event *signal_when_done) {
gpr_atm_rel_store(&state.done_atm, 0);
gpr_thd_id id;
poll_args *pa = gpr_malloc(sizeof(*pa));
pa->server = server;
pa->signal_when_done = signal_when_done;
gpr_thd_new(&id, actually_poll_server, pa, NULL);
}
static void match_initial_magic_string(grpc_slice_buffer *buffer) {
size_t i, j, cmp_length;
size_t magic_length = strlen(magic_connect_string);
GPR_ASSERT(buffer->length >= magic_length);
for (i = 0, j = 0; i < state.incoming_buffer.count && j < magic_length; i++) {
char *dump = grpc_slice_to_c_string(state.incoming_buffer.slices[i]);
cmp_length = GPR_MIN(strlen(dump), magic_length - j);
GPR_ASSERT(strncmp(dump, magic_connect_string + j, cmp_length) == 0);
j += cmp_length;
gpr_free(dump);
}
}
static void test_initial_string(test_tcp_server *server, int secure) {
gpr_event ev;
gpr_event_init(&ev);
grpc_test_set_initial_connect_string_function(set_magic_initial_string);
poll_server_until_read_done(server, &ev);
start_rpc(secure, server_port);
gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
match_initial_magic_string(&state.incoming_buffer);
cleanup_rpc();
}
static void test_initial_string_with_redirect(test_tcp_server *server,
int secure) {
gpr_event ev;
gpr_event_init(&ev);
int another_port = grpc_pick_unused_port_or_die();
grpc_test_set_initial_connect_string_function(
reset_addr_and_set_magic_string);
poll_server_until_read_done(server, &ev);
start_rpc(secure, another_port);
gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
match_initial_magic_string(&state.incoming_buffer);
cleanup_rpc();
}
static void run_test(void (*test)(test_tcp_server *server, int secure),
int secure) {
test_tcp_server test_server;
server_port = grpc_pick_unused_port_or_die();
test_tcp_server_init(&test_server, on_connect, &test_server);
test_tcp_server_start(&test_server, server_port);
test(&test_server, secure);
test_tcp_server_destroy(&test_server);
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
grpc_init();
run_test(test_initial_string, 0);
run_test(test_initial_string, 1);
run_test(test_initial_string_with_redirect, 0);
run_test(test_initial_string_with_redirect, 1);
grpc_shutdown();
return 0;
}

@ -0,0 +1,587 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* Microbenchmarks around CHTTP2 transport operations */
#include <grpc++/support/channel_arguments.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <string.h>
#include <memory>
#include <queue>
#include <sstream>
extern "C" {
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/lib/iomgr/resource_quota.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/static_metadata.h"
}
#include "test/cpp/microbenchmarks/helpers.h"
#include "third_party/benchmark/include/benchmark/benchmark.h"
auto &force_library_initialization = Library::get();
////////////////////////////////////////////////////////////////////////////////
// Helper classes
//
class DummyEndpoint : public grpc_endpoint {
public:
DummyEndpoint() {
static const grpc_endpoint_vtable my_vtable = {read,
write,
get_workqueue,
add_to_pollset,
add_to_pollset_set,
shutdown,
destroy,
get_resource_user,
get_peer,
get_fd};
grpc_endpoint::vtable = &my_vtable;
ru_ = grpc_resource_user_create(Library::get().rq(), "dummy_endpoint");
}
void PushInput(grpc_exec_ctx *exec_ctx, grpc_slice slice) {
if (read_cb_ == nullptr) {
GPR_ASSERT(!have_slice_);
buffered_slice_ = slice;
have_slice_ = true;
return;
}
grpc_slice_buffer_add(slices_, slice);
grpc_closure_sched(exec_ctx, read_cb_, GRPC_ERROR_NONE);
read_cb_ = nullptr;
}
private:
grpc_resource_user *ru_;
grpc_closure *read_cb_ = nullptr;
grpc_slice_buffer *slices_ = nullptr;
bool have_slice_ = false;
grpc_slice buffered_slice_;
void QueueRead(grpc_exec_ctx *exec_ctx, grpc_slice_buffer *slices,
grpc_closure *cb) {
GPR_ASSERT(read_cb_ == nullptr);
if (have_slice_) {
have_slice_ = false;
grpc_slice_buffer_add(slices, buffered_slice_);
grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_NONE);
return;
}
read_cb_ = cb;
slices_ = slices;
}
static void read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_slice_buffer *slices, grpc_closure *cb) {
static_cast<DummyEndpoint *>(ep)->QueueRead(exec_ctx, slices, cb);
}
static void write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_slice_buffer *slices, grpc_closure *cb) {
grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_NONE);
}
static grpc_workqueue *get_workqueue(grpc_endpoint *ep) { return NULL; }
static void add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_pollset *pollset) {}
static void add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_pollset_set *pollset) {}
static void shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_error *why) {
grpc_resource_user_shutdown(exec_ctx,
static_cast<DummyEndpoint *>(ep)->ru_);
grpc_closure_sched(exec_ctx, static_cast<DummyEndpoint *>(ep)->read_cb_,
why);
}
static void destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
grpc_resource_user_unref(exec_ctx, static_cast<DummyEndpoint *>(ep)->ru_);
delete static_cast<DummyEndpoint *>(ep);
}
static grpc_resource_user *get_resource_user(grpc_endpoint *ep) {
return static_cast<DummyEndpoint *>(ep)->ru_;
}
static char *get_peer(grpc_endpoint *ep) { return gpr_strdup("test"); }
static int get_fd(grpc_endpoint *ep) { return 0; }
};
class Fixture {
public:
Fixture(const grpc::ChannelArguments &args, bool client) {
grpc_channel_args c_args = args.c_channel_args();
ep_ = new DummyEndpoint;
t_ = grpc_create_chttp2_transport(exec_ctx(), &c_args, ep_, client);
grpc_chttp2_transport_start_reading(exec_ctx(), t_, NULL);
FlushExecCtx();
}
void FlushExecCtx() { grpc_exec_ctx_flush(&exec_ctx_); }
~Fixture() {
grpc_transport_destroy(&exec_ctx_, t_);
grpc_exec_ctx_finish(&exec_ctx_);
}
grpc_chttp2_transport *chttp2_transport() {
return reinterpret_cast<grpc_chttp2_transport *>(t_);
}
grpc_transport *transport() { return t_; }
grpc_exec_ctx *exec_ctx() { return &exec_ctx_; }
void PushInput(grpc_slice slice) { ep_->PushInput(exec_ctx(), slice); }
private:
DummyEndpoint *ep_;
grpc_exec_ctx exec_ctx_ = GRPC_EXEC_CTX_INIT;
grpc_transport *t_;
};
static void DoNothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
class Stream {
public:
Stream(Fixture *f) : f_(f) {
GRPC_STREAM_REF_INIT(&refcount_, 1, DoNothing, nullptr, "test_stream");
stream_size_ = grpc_transport_stream_size(f->transport());
stream_ = gpr_malloc(stream_size_);
arena_ = gpr_arena_create(4096);
}
~Stream() {
gpr_free(stream_);
gpr_arena_destroy(arena_);
}
void Init(benchmark::State &state) {
memset(stream_, 0, stream_size_);
if ((state.iterations() & 0xffff) == 0) {
gpr_arena_destroy(arena_);
arena_ = gpr_arena_create(4096);
}
grpc_transport_init_stream(f_->exec_ctx(), f_->transport(),
static_cast<grpc_stream *>(stream_), &refcount_,
NULL, arena_);
}
void DestroyThen(grpc_closure *closure) {
grpc_transport_destroy_stream(f_->exec_ctx(), f_->transport(),
static_cast<grpc_stream *>(stream_), closure);
}
void Op(grpc_transport_stream_op *op) {
grpc_transport_perform_stream_op(f_->exec_ctx(), f_->transport(),
static_cast<grpc_stream *>(stream_), op);
}
grpc_chttp2_stream *chttp2_stream() {
return static_cast<grpc_chttp2_stream *>(stream_);
}
private:
Fixture *f_;
grpc_stream_refcount refcount_;
gpr_arena *arena_;
size_t stream_size_;
void *stream_;
};
class Closure : public grpc_closure {
public:
virtual ~Closure() {}
};
template <class F>
std::unique_ptr<Closure> MakeClosure(
F f, grpc_closure_scheduler *sched = grpc_schedule_on_exec_ctx) {
struct C : public Closure {
C(const F &f, grpc_closure_scheduler *sched) : f_(f) {
grpc_closure_init(this, Execute, this, sched);
}
F f_;
static void Execute(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
static_cast<C *>(arg)->f_(exec_ctx, error);
}
};
return std::unique_ptr<Closure>(new C(f, sched));
}
template <class F>
grpc_closure *MakeOnceClosure(
F f, grpc_closure_scheduler *sched = grpc_schedule_on_exec_ctx) {
struct C : public grpc_closure {
C(const F &f) : f_(f) {}
F f_;
static void Execute(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
static_cast<C *>(arg)->f_(exec_ctx, error);
delete static_cast<C *>(arg);
}
};
auto *c = new C{f};
return grpc_closure_init(c, C::Execute, c, sched);
}
////////////////////////////////////////////////////////////////////////////////
// Benchmarks
//
static void BM_StreamCreateDestroy(benchmark::State &state) {
TrackCounters track_counters;
Fixture f(grpc::ChannelArguments(), true);
Stream s(&f);
std::unique_ptr<Closure> next =
MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
if (!state.KeepRunning()) return;
s.Init(state);
s.DestroyThen(next.get());
});
grpc_closure_run(f.exec_ctx(), next.get(), GRPC_ERROR_NONE);
f.FlushExecCtx();
track_counters.Finish(state);
}
BENCHMARK(BM_StreamCreateDestroy);
class RepresentativeClientInitialMetadata {
public:
static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) {
return {
GRPC_MDELEM_SCHEME_HTTP, GRPC_MDELEM_METHOD_POST,
grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_PATH,
grpc_slice_intern(grpc_slice_from_static_string("/foo/bar"))),
grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_AUTHORITY,
grpc_slice_intern(grpc_slice_from_static_string(
"foo.test.google.fr:1234"))),
GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP,
GRPC_MDELEM_TE_TRAILERS,
GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC,
grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_USER_AGENT,
grpc_slice_intern(grpc_slice_from_static_string(
"grpc-c/3.0.0-dev (linux; chttp2; green)")))};
}
};
template <class Metadata>
static void BM_StreamCreateSendInitialMetadataDestroy(benchmark::State &state) {
TrackCounters track_counters;
Fixture f(grpc::ChannelArguments(), true);
Stream s(&f);
grpc_transport_stream_op op;
std::unique_ptr<Closure> start;
std::unique_ptr<Closure> done;
grpc_metadata_batch b;
grpc_metadata_batch_init(&b);
b.deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
std::vector<grpc_mdelem> elems = Metadata::GetElems(f.exec_ctx());
std::vector<grpc_linked_mdelem> storage(elems.size());
for (size_t i = 0; i < elems.size(); i++) {
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"addmd",
grpc_metadata_batch_add_tail(f.exec_ctx(), &b, &storage[i], elems[i])));
}
f.FlushExecCtx();
start = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
if (!state.KeepRunning()) return;
s.Init(state);
memset(&op, 0, sizeof(op));
op.on_complete = done.get();
op.send_initial_metadata = &b;
s.Op(&op);
});
done = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
memset(&op, 0, sizeof(op));
op.cancel_error = GRPC_ERROR_CANCELLED;
s.Op(&op);
s.DestroyThen(start.get());
});
grpc_closure_sched(f.exec_ctx(), start.get(), GRPC_ERROR_NONE);
f.FlushExecCtx();
grpc_metadata_batch_destroy(f.exec_ctx(), &b);
track_counters.Finish(state);
}
BENCHMARK_TEMPLATE(BM_StreamCreateSendInitialMetadataDestroy,
RepresentativeClientInitialMetadata);
static void BM_TransportEmptyOp(benchmark::State &state) {
TrackCounters track_counters;
Fixture f(grpc::ChannelArguments(), true);
Stream s(&f);
s.Init(state);
grpc_transport_stream_op op;
std::unique_ptr<Closure> c =
MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
if (!state.KeepRunning()) return;
memset(&op, 0, sizeof(op));
op.on_complete = c.get();
s.Op(&op);
});
grpc_closure_sched(f.exec_ctx(), c.get(), GRPC_ERROR_NONE);
f.FlushExecCtx();
s.DestroyThen(
MakeOnceClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {}));
f.FlushExecCtx();
track_counters.Finish(state);
}
BENCHMARK(BM_TransportEmptyOp);
static void BM_TransportStreamSend(benchmark::State &state) {
TrackCounters track_counters;
Fixture f(grpc::ChannelArguments(), true);
Stream s(&f);
s.Init(state);
grpc_transport_stream_op op;
grpc_slice_buffer_stream send_stream;
grpc_slice_buffer send_buffer;
grpc_slice_buffer_init(&send_buffer);
grpc_slice_buffer_add(&send_buffer, gpr_slice_malloc(state.range(0)));
memset(GRPC_SLICE_START_PTR(send_buffer.slices[0]), 0,
GRPC_SLICE_LENGTH(send_buffer.slices[0]));
grpc_metadata_batch b;
grpc_metadata_batch_init(&b);
b.deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
std::vector<grpc_mdelem> elems =
RepresentativeClientInitialMetadata::GetElems(f.exec_ctx());
std::vector<grpc_linked_mdelem> storage(elems.size());
for (size_t i = 0; i < elems.size(); i++) {
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"addmd",
grpc_metadata_batch_add_tail(f.exec_ctx(), &b, &storage[i], elems[i])));
}
std::unique_ptr<Closure> c =
MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
if (!state.KeepRunning()) return;
// force outgoing window to be yuge
s.chttp2_stream()->outgoing_window_delta = 1024 * 1024 * 1024;
f.chttp2_transport()->outgoing_window = 1024 * 1024 * 1024;
grpc_slice_buffer_stream_init(&send_stream, &send_buffer, 0);
memset(&op, 0, sizeof(op));
op.on_complete = c.get();
op.send_message = &send_stream.base;
s.Op(&op);
});
memset(&op, 0, sizeof(op));
op.send_initial_metadata = &b;
op.on_complete = c.get();
s.Op(&op);
f.FlushExecCtx();
memset(&op, 0, sizeof(op));
op.cancel_error = GRPC_ERROR_CANCELLED;
s.Op(&op);
s.DestroyThen(
MakeOnceClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {}));
f.FlushExecCtx();
track_counters.Finish(state);
grpc_metadata_batch_destroy(f.exec_ctx(), &b);
grpc_slice_buffer_destroy(&send_buffer);
}
BENCHMARK(BM_TransportStreamSend)->Range(0, 128 * 1024 * 1024);
#define SLICE_FROM_BUFFER(s) grpc_slice_from_static_buffer(s, sizeof(s) - 1)
static grpc_slice CreateIncomingDataSlice(size_t length, size_t frame_size) {
std::queue<char> unframed;
unframed.push(static_cast<uint8_t>(0));
unframed.push(static_cast<uint8_t>(length >> 24));
unframed.push(static_cast<uint8_t>(length >> 16));
unframed.push(static_cast<uint8_t>(length >> 8));
unframed.push(static_cast<uint8_t>(length));
for (size_t i = 0; i < length; i++) {
unframed.push('a');
}
std::vector<char> framed;
while (unframed.size() > frame_size) {
// frame size
framed.push_back(static_cast<uint8_t>(frame_size >> 16));
framed.push_back(static_cast<uint8_t>(frame_size >> 8));
framed.push_back(static_cast<uint8_t>(frame_size));
// data frame
framed.push_back(0);
// no flags
framed.push_back(0);
// stream id
framed.push_back(0);
framed.push_back(0);
framed.push_back(0);
framed.push_back(1);
// frame data
for (size_t i = 0; i < frame_size; i++) {
framed.push_back(unframed.front());
unframed.pop();
}
}
// frame size
framed.push_back(static_cast<uint8_t>(unframed.size() >> 16));
framed.push_back(static_cast<uint8_t>(unframed.size() >> 8));
framed.push_back(static_cast<uint8_t>(unframed.size()));
// data frame
framed.push_back(0);
// no flags
framed.push_back(0);
// stream id
framed.push_back(0);
framed.push_back(0);
framed.push_back(0);
framed.push_back(1);
while (!unframed.empty()) {
framed.push_back(unframed.front());
unframed.pop();
}
return grpc_slice_from_copied_buffer(framed.data(), framed.size());
}
static void BM_TransportStreamRecv(benchmark::State &state) {
TrackCounters track_counters;
Fixture f(grpc::ChannelArguments(), true);
Stream s(&f);
s.Init(state);
grpc_transport_stream_op op;
grpc_byte_stream *recv_stream;
grpc_slice incoming_data = CreateIncomingDataSlice(state.range(0), 16384);
grpc_metadata_batch b;
grpc_metadata_batch_init(&b);
grpc_metadata_batch b_recv;
grpc_metadata_batch_init(&b_recv);
b.deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
std::vector<grpc_mdelem> elems =
RepresentativeClientInitialMetadata::GetElems(f.exec_ctx());
std::vector<grpc_linked_mdelem> storage(elems.size());
for (size_t i = 0; i < elems.size(); i++) {
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"addmd",
grpc_metadata_batch_add_tail(f.exec_ctx(), &b, &storage[i], elems[i])));
}
std::unique_ptr<Closure> do_nothing =
MakeClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {});
uint32_t received;
std::unique_ptr<Closure> drain_start;
std::unique_ptr<Closure> drain;
std::unique_ptr<Closure> drain_continue;
grpc_slice recv_slice;
std::unique_ptr<Closure> c =
MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
if (!state.KeepRunning()) return;
// force outgoing window to be yuge
s.chttp2_stream()->incoming_window_delta = 1024 * 1024 * 1024;
f.chttp2_transport()->incoming_window = 1024 * 1024 * 1024;
received = 0;
memset(&op, 0, sizeof(op));
op.on_complete = do_nothing.get();
op.recv_message = &recv_stream;
op.recv_message_ready = drain_start.get();
s.Op(&op);
f.PushInput(grpc_slice_ref(incoming_data));
});
drain_start = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
if (recv_stream == NULL) {
GPR_ASSERT(!state.KeepRunning());
return;
}
grpc_closure_run(exec_ctx, drain.get(), GRPC_ERROR_NONE);
});
drain = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
do {
if (received == recv_stream->length) {
grpc_byte_stream_destroy(exec_ctx, recv_stream);
grpc_closure_sched(exec_ctx, c.get(), GRPC_ERROR_NONE);
return;
}
} while (grpc_byte_stream_next(exec_ctx, recv_stream, &recv_slice,
recv_stream->length - received,
drain_continue.get()));
});
drain_continue = MakeClosure([&](grpc_exec_ctx *exec_ctx, grpc_error *error) {
received += GRPC_SLICE_LENGTH(recv_slice);
grpc_slice_unref_internal(exec_ctx, recv_slice);
grpc_closure_run(exec_ctx, drain.get(), GRPC_ERROR_NONE);
});
memset(&op, 0, sizeof(op));
op.send_initial_metadata = &b;
op.recv_initial_metadata = &b_recv;
op.on_complete = c.get();
s.Op(&op);
f.PushInput(SLICE_FROM_BUFFER(
"\x00\x00\x00\x04\x00\x00\x00\x00\x00"
// Generated using:
// tools/codegen/core/gen_header_frame.py <
// test/cpp/microbenchmarks/representative_server_initial_metadata.headers
"\x00\x00X\x01\x04\x00\x00\x00\x01"
"\x10\x07:status\x03"
"200"
"\x10\x0c"
"content-type\x10"
"application/grpc"
"\x10\x14grpc-accept-encoding\x15identity,deflate,gzip"));
f.FlushExecCtx();
memset(&op, 0, sizeof(op));
op.cancel_error = GRPC_ERROR_CANCELLED;
s.Op(&op);
s.DestroyThen(
MakeOnceClosure([](grpc_exec_ctx *exec_ctx, grpc_error *error) {}));
f.FlushExecCtx();
track_counters.Finish(state);
grpc_metadata_batch_destroy(f.exec_ctx(), &b);
grpc_metadata_batch_destroy(f.exec_ctx(), &b_recv);
grpc_slice_unref(incoming_data);
}
BENCHMARK(BM_TransportStreamRecv)->Range(0, 128 * 1024 * 1024);
BENCHMARK_MAIN();

@ -63,7 +63,6 @@ static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
// the other from server to client):
template <class Fixture, class ClientContextMutator, class ServerContextMutator>
static void BM_StreamingPingPong(benchmark::State& state) {
TrackCounters track_counters;
const int msg_size = state.range(0);
const int max_ping_pongs = state.range(1);
@ -152,14 +151,12 @@ static void BM_StreamingPingPong(benchmark::State& state) {
fixture->Finish(state);
fixture.reset();
state.SetBytesProcessed(msg_size * state.iterations() * max_ping_pongs * 2);
track_counters.Finish(state);
}
// Repeatedly sends ping pong messages in a single streaming Bidi call in a loop
// First parmeter (i.e state.range(0)): Message size (in bytes) to use
template <class Fixture, class ClientContextMutator, class ServerContextMutator>
static void BM_StreamingPingPongMsgs(benchmark::State& state) {
TrackCounters track_counters;
const int msg_size = state.range(0);
EchoTestService::AsyncService service;
@ -241,7 +238,6 @@ static void BM_StreamingPingPongMsgs(benchmark::State& state) {
fixture->Finish(state);
fixture.reset();
state.SetBytesProcessed(msg_size * state.iterations() * 2);
track_counters.Finish(state);
}
/*******************************************************************************

@ -52,7 +52,7 @@ def mako_plugin(dictionary):
'exclude_iomgrs': ['uv'],
'exclude_configs': ['tsan'],
'uses_polling': False,
'platforms': ['linux'],
'platforms': ['mac', 'linux'],
'ci_platforms': ['linux'],
'flaky': False,
'language': 'c',

@ -764,6 +764,7 @@ INPUT = doc/PROTOCOL-HTTP2.md \
doc/PROTOCOL-WEB.md \
doc/binary-logging.md \
doc/c-style-guide.md \
doc/combiner-explainer.md \
doc/command_line_tool.md \
doc/compression.md \
doc/compression_cookbook.md \

@ -764,6 +764,7 @@ INPUT = doc/PROTOCOL-HTTP2.md \
doc/PROTOCOL-WEB.md \
doc/binary-logging.md \
doc/c-style-guide.md \
doc/combiner-explainer.md \
doc/command_line_tool.md \
doc/compression.md \
doc/compression_cookbook.md \

@ -764,12 +764,14 @@ INPUT = doc/PROTOCOL-HTTP2.md \
doc/PROTOCOL-WEB.md \
doc/binary-logging.md \
doc/c-style-guide.md \
doc/combiner-explainer.md \
doc/command_line_tool.md \
doc/compression.md \
doc/compression_cookbook.md \
doc/connection-backoff-interop-test-description.md \
doc/connection-backoff.md \
doc/connectivity-semantics-and-api.md \
doc/core/grpc-error.md \
doc/core/pending_api_cleanups.md \
doc/cpp-style-guide.md \
doc/environment_variables.md \

@ -764,12 +764,14 @@ INPUT = doc/PROTOCOL-HTTP2.md \
doc/PROTOCOL-WEB.md \
doc/binary-logging.md \
doc/c-style-guide.md \
doc/combiner-explainer.md \
doc/command_line_tool.md \
doc/compression.md \
doc/compression_cookbook.md \
doc/connection-backoff-interop-test-description.md \
doc/connection-backoff.md \
doc/connectivity-semantics-and-api.md \
doc/core/grpc-error.md \
doc/core/pending_api_cleanups.md \
doc/cpp-style-guide.md \
doc/environment_variables.md \
@ -903,13 +905,10 @@ src/core/ext/client_channel/client_channel_factory.h \
src/core/ext/client_channel/client_channel_plugin.c \
src/core/ext/client_channel/connector.c \
src/core/ext/client_channel/connector.h \
src/core/ext/client_channel/default_initial_connect_string.c \
src/core/ext/client_channel/http_connect_handshaker.c \
src/core/ext/client_channel/http_connect_handshaker.h \
src/core/ext/client_channel/http_proxy.c \
src/core/ext/client_channel/http_proxy.h \
src/core/ext/client_channel/initial_connect_string.c \
src/core/ext/client_channel/initial_connect_string.h \
src/core/ext/client_channel/lb_policy.c \
src/core/ext/client_channel/lb_policy.h \
src/core/ext/client_channel/lb_policy_factory.c \
@ -928,6 +927,8 @@ src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_factory.h \
src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/resolver_registry.h \
src/core/ext/client_channel/retry_throttle.c \
src/core/ext/client_channel/retry_throttle.h \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel.h \
src/core/ext/client_channel/subchannel_index.c \
@ -1239,6 +1240,7 @@ src/core/lib/slice/slice_string_helpers.h \
src/core/lib/support/alloc.c \
src/core/lib/support/arena.c \
src/core/lib/support/arena.h \
src/core/lib/support/atm.c \
src/core/lib/support/avl.c \
src/core/lib/support/backoff.c \
src/core/lib/support/backoff.h \

@ -101,6 +101,18 @@ _BM_SPECS = {
'BM_PollEmptyPollset_SpeedOfLight': {
'tpl': [],
'dyn': ['request_size', 'request_count'],
},
'BM_StreamCreateSendInitialMetadataDestroy': {
'tpl': ['fixture'],
'dyn': [],
},
'BM_TransportStreamSend': {
'tpl': [],
'dyn': ['request_size'],
},
'BM_TransportStreamRecv': {
'tpl': [],
'dyn': ['request_size'],
}
}

@ -1927,24 +1927,6 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util",
"test_tcp_server"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "set_initial_connect_string_test",
"src": [
"test/core/client_channel/set_initial_connect_string_test.c"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
@ -2507,6 +2489,27 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"benchmark",
"gpr",
"gpr_test_util",
"grpc",
"grpc++",
"grpc++_test_util",
"grpc_benchmark",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c++",
"name": "bm_chttp2_transport",
"src": [
"test/cpp/microbenchmarks/bm_chttp2_transport.cc"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"benchmark",
@ -7387,6 +7390,7 @@
"src/core/lib/support/alloc.c",
"src/core/lib/support/arena.c",
"src/core/lib/support/arena.h",
"src/core/lib/support/atm.c",
"src/core/lib/support/avl.c",
"src/core/lib/support/backoff.c",
"src/core/lib/support/backoff.h",
@ -7861,7 +7865,6 @@
"src/core/ext/client_channel/connector.h",
"src/core/ext/client_channel/http_connect_handshaker.h",
"src/core/ext/client_channel/http_proxy.h",
"src/core/ext/client_channel/initial_connect_string.h",
"src/core/ext/client_channel/lb_policy.h",
"src/core/ext/client_channel/lb_policy_factory.h",
"src/core/ext/client_channel/lb_policy_registry.h",
@ -7871,6 +7874,7 @@
"src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/retry_throttle.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h"
@ -7887,13 +7891,10 @@
"src/core/ext/client_channel/client_channel_plugin.c",
"src/core/ext/client_channel/connector.c",
"src/core/ext/client_channel/connector.h",
"src/core/ext/client_channel/default_initial_connect_string.c",
"src/core/ext/client_channel/http_connect_handshaker.c",
"src/core/ext/client_channel/http_connect_handshaker.h",
"src/core/ext/client_channel/http_proxy.c",
"src/core/ext/client_channel/http_proxy.h",
"src/core/ext/client_channel/initial_connect_string.c",
"src/core/ext/client_channel/initial_connect_string.h",
"src/core/ext/client_channel/lb_policy.c",
"src/core/ext/client_channel/lb_policy.h",
"src/core/ext/client_channel/lb_policy_factory.c",
@ -7912,6 +7913,8 @@
"src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/retry_throttle.c",
"src/core/ext/client_channel/retry_throttle.h",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.c",

File diff suppressed because it is too large Load Diff

@ -209,6 +209,8 @@ argp.add_argument('-b', '--benchmarks',
'bm_call_create',
'bm_error',
'bm_chttp2_hpack',
'bm_chttp2_transport',
'bm_pollset',
'bm_metadata',
'bm_fullstack_trickle',
],

@ -1395,18 +1395,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server_test", "vcxproj\test
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "set_initial_connect_string_test", "vcxproj\test\set_initial_connect_string_test\set_initial_connect_string_test.vcxproj", "{4A48E5A5-2E69-ED6D-063C-C297180A54D0}"
ProjectSection(myProperties) = preProject
lib = "False"
EndProjectSection
ProjectSection(ProjectDependencies) = postProject
{E3110C46-A148-FF65-08FD-3324829BE7FE} = {E3110C46-A148-FF65-08FD-3324829BE7FE}
{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple_request_bad_client_test", "vcxproj\test\simple_request_bad_client_test\simple_request_bad_client_test.vcxproj", "{63422647-93FA-46BB-4827-95473D9D503C}"
ProjectSection(myProperties) = preProject
lib = "False"
@ -3749,22 +3737,6 @@ Global
{E765AC67-E4E5-C350-59A1-C6CA2BD9F64B}.Release-DLL|Win32.Build.0 = Release|Win32
{E765AC67-E4E5-C350-59A1-C6CA2BD9F64B}.Release-DLL|x64.ActiveCfg = Release|x64
{E765AC67-E4E5-C350-59A1-C6CA2BD9F64B}.Release-DLL|x64.Build.0 = Release|x64
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug|Win32.ActiveCfg = Debug|Win32
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug|x64.ActiveCfg = Debug|x64
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release|Win32.ActiveCfg = Release|Win32
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release|x64.ActiveCfg = Release|x64
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug|Win32.Build.0 = Debug|Win32
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug|x64.Build.0 = Debug|x64
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release|Win32.Build.0 = Release|Win32
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release|x64.Build.0 = Release|x64
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug-DLL|Win32.Build.0 = Debug|Win32
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug-DLL|x64.ActiveCfg = Debug|x64
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug-DLL|x64.Build.0 = Debug|x64
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release-DLL|Win32.ActiveCfg = Release|Win32
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release-DLL|Win32.Build.0 = Release|Win32
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release-DLL|x64.ActiveCfg = Release|x64
{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release-DLL|x64.Build.0 = Release|x64
{63422647-93FA-46BB-4827-95473D9D503C}.Debug|Win32.ActiveCfg = Debug|Win32
{63422647-93FA-46BB-4827-95473D9D503C}.Debug|x64.ActiveCfg = Debug|x64
{63422647-93FA-46BB-4827-95473D9D503C}.Release|Win32.ActiveCfg = Release|Win32

@ -211,6 +211,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\arena.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\atm.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\avl.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\backoff.c">

@ -13,6 +13,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\arena.c">
<Filter>src\core\lib\support</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\atm.c">
<Filter>src\core\lib\support</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\support\avl.c">
<Filter>src\core\lib\support</Filter>
</ClCompile>

@ -457,7 +457,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\connector.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_factory.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_registry.h" />
@ -467,6 +466,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\retry_throttle.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h" />
@ -859,14 +859,10 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\connector.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\default_initial_connect_string.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_factory.c">
@ -885,6 +881,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\retry_throttle.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.c">

@ -538,18 +538,12 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\connector.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\default_initial_connect_string.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
@ -577,6 +571,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\retry_throttle.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
@ -1262,9 +1259,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
@ -1292,6 +1286,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\retry_throttle.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>

@ -423,7 +423,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\connector.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_factory.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_registry.h" />
@ -433,6 +432,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\retry_throttle.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h" />
@ -776,14 +776,10 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\connector.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\default_initial_connect_string.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_factory.c">
@ -802,6 +798,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\retry_throttle.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.c">

@ -466,18 +466,12 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\connector.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\default_initial_connect_string.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_connect_handshaker.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
@ -505,6 +499,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\retry_throttle.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
@ -1100,9 +1097,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\http_proxy.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\initial_connect_string.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
@ -1130,6 +1124,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\retry_throttle.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>

@ -1,202 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{4A48E5A5-2E69-ED6D-063C-C297180A54D0}</ProjectGuid>
<IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
<IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)\..\vsprojects\global.props" />
<Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
<Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
<Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<TargetName>set_initial_connect_string_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<TargetName>set_initial_connect_string_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\core\client_channel\set_initial_connect_string_test.c">
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\test_tcp_server\test_tcp_server.vcxproj">
<Project>{E3110C46-A148-FF65-08FD-3324829BE7FE}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
<Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
<Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
<Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
<Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
</Target>
</Project>

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\core\client_channel\set_initial_connect_string_test.c">
<Filter>test\core\client_channel</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="test">
<UniqueIdentifier>{413358e4-3165-f09d-071c-ee4f2ca0b826}</UniqueIdentifier>
</Filter>
<Filter Include="test\core">
<UniqueIdentifier>{a554b5ef-0c80-ac03-1848-bccd947a06a6}</UniqueIdentifier>
</Filter>
<Filter Include="test\core\client_channel">
<UniqueIdentifier>{4726253c-a562-0ace-2798-996807381208}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
Loading…
Cancel
Save