Merge branch 'master' into mutrace_fix

pull/8518/head
Sree Kuchibhotla 8 years ago
commit 8ddad0f485
  1. 24
      BUILD
  2. 9
      CMakeLists.txt
  3. 10
      Makefile
  4. 3
      binding.gyp
  5. 6
      build.yaml
  6. 3
      config.m4
  7. BIN
      doc/images/stress_test_framework.png
  8. 92
      doc/stress_test_framework.md
  9. 9
      gRPC-Core.podspec
  10. 6
      grpc.gemspec
  11. 7
      include/grpc/impl/codegen/grpc_types.h
  12. 2
      package.json
  13. 6
      package.xml
  14. 8
      setup.py
  15. 21
      src/core/ext/client_channel/README.md
  16. 61
      src/core/ext/client_channel/client_channel.c
  17. 4
      src/core/ext/client_channel/client_channel_factory.c
  18. 9
      src/core/ext/client_channel/client_channel_factory.h
  19. 78
      src/core/ext/client_channel/lb_policy_factory.c
  20. 40
      src/core/ext/client_channel/lb_policy_factory.h
  21. 3
      src/core/ext/client_channel/resolver.c
  22. 18
      src/core/ext/client_channel/resolver.h
  23. 7
      src/core/ext/client_channel/resolver_factory.h
  24. 12
      src/core/ext/client_channel/resolver_registry.c
  25. 7
      src/core/ext/client_channel/resolver_registry.h
  26. 94
      src/core/ext/client_channel/resolver_result.c
  27. 68
      src/core/ext/client_channel/resolver_result.h
  28. 2
      src/core/ext/client_channel/subchannel.c
  29. 2
      src/core/ext/client_channel/subchannel.h
  30. 6
      src/core/ext/client_channel/subchannel_index.c
  31. 4
      src/core/ext/client_channel/subchannel_index.h
  32. 106
      src/core/ext/lb_policy/grpclb/grpclb.c
  33. 30
      src/core/ext/lb_policy/pick_first/pick_first.c
  34. 29
      src/core/ext/lb_policy/round_robin/round_robin.c
  35. 50
      src/core/ext/resolver/dns/native/dns_resolver.c
  36. 35
      src/core/ext/resolver/sockaddr/sockaddr_resolver.c
  37. 63
      src/core/ext/transport/chttp2/client/insecure/channel_create.c
  38. 73
      src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
  39. 55
      src/core/lib/channel/channel_args.c
  40. 11
      src/core/lib/channel/channel_args.h
  41. 2
      src/core/lib/channel/message_size_filter.c
  42. 6
      src/core/lib/iomgr/ev_epoll_linux.c
  43. 3
      src/core/lib/iomgr/tcp_uv.c
  44. 2
      src/core/lib/transport/method_config.c
  45. 6
      src/core/lib/transport/method_config.h
  46. 291
      src/node/performance/benchmark_client_express.js
  47. 5
      src/node/performance/benchmark_server.js
  48. 109
      src/node/performance/benchmark_server_express.js
  49. 10
      src/node/performance/worker.js
  50. 228
      src/node/performance/worker_service_impl.js
  51. 3
      src/python/grpcio/grpc_core_dependencies.py
  52. 146
      src/ruby/lib/grpc/generic/active_call.rb
  53. 12
      src/ruby/lib/grpc/generic/client_stub.rb
  54. 43
      src/ruby/lib/grpc/generic/rpc_desc.rb
  55. 22
      src/ruby/spec/generic/active_call_spec.rb
  56. 123
      src/ruby/spec/generic/client_stub_spec.rb
  57. 24
      src/ruby/spec/generic/rpc_desc_spec.rb
  58. 1
      src/ruby/spec/generic/rpc_server_spec.rb
  59. 38
      src/ruby/spec/pb/health/checker_spec.rb
  60. 2
      templates/package.json.template
  61. 5
      test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
  62. 14
      test/core/client_channel/resolvers/sockaddr_resolver_test.c
  63. 44
      test/core/end2end/fake_resolver.c
  64. 2
      test/core/iomgr/udp_server_test.c
  65. 2
      test/cpp/end2end/end2end_test.cc
  66. 1
      tools/distrib/python/docgen.py
  67. 6
      tools/doxygen/Doxyfile.core.internal
  68. 14
      tools/run_tests/build_python.sh
  69. 70
      tools/run_tests/performance/scenario_config.py
  70. 48
      tools/run_tests/run_tests.py
  71. 9
      tools/run_tests/sources_and_headers.json
  72. 44
      tools/run_tests/tests.json
  73. 9
      vsprojects/vcxproj/grpc/grpc.vcxproj
  74. 18
      vsprojects/vcxproj/grpc/grpc.vcxproj.filters
  75. 3
      vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
  76. 6
      vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
  77. 9
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
  78. 18
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters

24
BUILD

@ -249,6 +249,7 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h",
@ -306,12 +307,10 @@ cc_library(
"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",
"src/core/ext/client_channel/method_config.h",
"src/core/ext/client_channel/parse_address.h",
"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/resolver_result.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h",
@ -433,6 +432,7 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c",
@ -499,12 +499,10 @@ cc_library(
"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",
"src/core/ext/client_channel/method_config.c",
"src/core/ext/client_channel/parse_address.c",
"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/resolver_result.c",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c",
@ -672,6 +670,7 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h",
@ -706,12 +705,10 @@ cc_library(
"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",
"src/core/ext/client_channel/method_config.h",
"src/core/ext/client_channel/parse_address.h",
"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/resolver_result.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h",
@ -841,6 +838,7 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c",
@ -882,12 +880,10 @@ cc_library(
"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",
"src/core/ext/client_channel/method_config.c",
"src/core/ext/client_channel/parse_address.c",
"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/resolver_result.c",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c",
@ -1050,6 +1046,7 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h",
@ -1083,12 +1080,10 @@ cc_library(
"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",
"src/core/ext/client_channel/method_config.h",
"src/core/ext/client_channel/parse_address.h",
"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/resolver_result.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h",
@ -1211,6 +1206,7 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c",
@ -1252,12 +1248,10 @@ cc_library(
"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",
"src/core/ext/client_channel/method_config.c",
"src/core/ext/client_channel/parse_address.c",
"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/resolver_result.c",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c",
@ -2136,6 +2130,7 @@ objc_library(
"src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c",
@ -2202,12 +2197,10 @@ objc_library(
"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",
"src/core/ext/client_channel/method_config.c",
"src/core/ext/client_channel/parse_address.c",
"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/resolver_result.c",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c",
@ -2354,6 +2347,7 @@ objc_library(
"src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h",
@ -2411,12 +2405,10 @@ objc_library(
"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",
"src/core/ext/client_channel/method_config.h",
"src/core/ext/client_channel/parse_address.h",
"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/resolver_result.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h",

@ -391,6 +391,7 @@ add_library(grpc
src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c
@ -457,12 +458,10 @@ add_library(grpc
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
src/core/ext/client_channel/method_config.c
src/core/ext/client_channel/parse_address.c
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/resolver_result.c
src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c
@ -663,6 +662,7 @@ add_library(grpc_cronet
src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c
@ -704,12 +704,10 @@ add_library(grpc_cronet
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
src/core/ext/client_channel/method_config.c
src/core/ext/client_channel/parse_address.c
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/resolver_result.c
src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c
@ -907,6 +905,7 @@ add_library(grpc_unsecure
src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c
@ -948,12 +947,10 @@ add_library(grpc_unsecure
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
src/core/ext/client_channel/method_config.c
src/core/ext/client_channel/parse_address.c
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/resolver_result.c
src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c

@ -2676,6 +2676,7 @@ LIBGRPC_SRC = \
src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \
@ -2742,12 +2743,10 @@ LIBGRPC_SRC = \
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 \
src/core/ext/client_channel/method_config.c \
src/core/ext/client_channel/parse_address.c \
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/resolver_result.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \
@ -2966,6 +2965,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \
@ -3007,12 +3007,10 @@ LIBGRPC_CRONET_SRC = \
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 \
src/core/ext/client_channel/method_config.c \
src/core/ext/client_channel/parse_address.c \
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/resolver_result.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \
@ -3247,6 +3245,7 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \
@ -3455,6 +3454,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \
@ -3496,12 +3496,10 @@ LIBGRPC_UNSECURE_SRC = \
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 \
src/core/ext/client_channel/method_config.c \
src/core/ext/client_channel/parse_address.c \
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/resolver_result.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \

@ -669,6 +669,7 @@
'src/core/lib/transport/mdstr_hash_table.c',
'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/method_config.c',
'src/core/lib/transport/static_metadata.c',
'src/core/lib/transport/timeout_encoding.c',
'src/core/lib/transport/transport.c',
@ -735,12 +736,10 @@
'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',
'src/core/ext/client_channel/method_config.c',
'src/core/ext/client_channel/parse_address.c',
'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/resolver_result.c',
'src/core/ext/client_channel/subchannel.c',
'src/core/ext/client_channel/subchannel_index.c',
'src/core/ext/client_channel/uri_parser.c',

@ -253,6 +253,7 @@ filegroups:
- src/core/lib/transport/mdstr_hash_table.h
- src/core/lib/transport/metadata.h
- src/core/lib/transport/metadata_batch.h
- src/core/lib/transport/method_config.h
- src/core/lib/transport/static_metadata.h
- src/core/lib/transport/timeout_encoding.h
- src/core/lib/transport/transport.h
@ -359,6 +360,7 @@ filegroups:
- src/core/lib/transport/mdstr_hash_table.c
- src/core/lib/transport/metadata.c
- src/core/lib/transport/metadata_batch.c
- src/core/lib/transport/method_config.c
- src/core/lib/transport/static_metadata.c
- src/core/lib/transport/timeout_encoding.c
- src/core/lib/transport/transport.c
@ -377,12 +379,10 @@ filegroups:
- 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
- src/core/ext/client_channel/method_config.h
- src/core/ext/client_channel/parse_address.h
- 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/resolver_result.h
- src/core/ext/client_channel/subchannel.h
- src/core/ext/client_channel/subchannel_index.h
- src/core/ext/client_channel/uri_parser.h
@ -398,12 +398,10 @@ filegroups:
- 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
- src/core/ext/client_channel/method_config.c
- src/core/ext/client_channel/parse_address.c
- 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/resolver_result.c
- src/core/ext/client_channel/subchannel.c
- src/core/ext/client_channel/subchannel_index.c
- src/core/ext/client_channel/uri_parser.c

@ -185,6 +185,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \
@ -251,12 +252,10 @@ if test "$PHP_GRPC" != "no"; then
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 \
src/core/ext/client_channel/method_config.c \
src/core/ext/client_channel/parse_address.c \
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/resolver_result.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

@ -0,0 +1,92 @@
# Stress Test framework for gRPC
(Sree Kuchibhotla - sreek@)
> Status: This is implemented. More details at [README.md](https://github.com/grpc/grpc/blob/master/tools/run_tests/stress_test/README.md)
**I. GOALS**
1) Build a stress test suite for gRPC:
* Build a stress test suite that can Identify bugs by testing the system (gRPC server/client) under extreme conditions:
* High load
* High concurrency
* Limited resources
* Intermittent failures
* Should be integrated with Jenkins CI
2) Make it generic enough (i.e build a generic test framework) that can be used for:
* Executing M instances of a client against N instances of a server with an arbitrarily defined connection matrix
* Execute heterogenous test configurations - for example: Java stress test clients against C++ servers or Node clients against Python servers or TSAN C++ clients vs ASAN C++ Servers etc.
* Easy and Flexible enough that Devs can use it to recreate complex test scenarios
The implementation effort is divided into two parts:
* Building a "Stress Test Framework" to run the stress test suites- More details in **Section II** (The idea is that the Stress Test framework is generic enough that it would be easier to modify it to run other suites like interop-tests or custom test scenarios)
* Building a 'Stress test suite' - More details in **section III**
**Terminology:**
GCE - Google compute engine
GKE - Google Container engine
Kubernetes - Google's open source service scheduler / orchestrator.
**Note:** The terms GKE and Kubernetes are used interchangeably in this document
# II. STRESS TEST FRAMEWORK
(The details of each step are explained below))
![image](images/stress_test_framework.png)
**Figure 1**
### Step 1 Read the test config, generate base docker images
**_Test Config:_** The test configuration contains the following information:
* _GKE info:_ GKE project and cluster info
* _Docker images:_ Instructions to build docker images
* _Client templates:_ One or more client templates each containing the following information:
* Which docker image to use
* Path to the client program to launch (within the docker image)
* Parameters to the client program
* _Server templates:_ Similar to Client templates - except that these are for servers
* Test matrix containing the following:
* _Server groups:_ One or more groups of servers containing the following info for each group
* Which server template to use
* How many instances to launch
* _Client groups:_ One or more groups of clients containing the following (for each group):
* Which client template to use
* How many instances to launch
* Which server group to talk to (all clients in this group will talk to all servers in the server group)
The first step is to read the test config and build the docker images
**_Stress server docker image:_** The following are the main files in the server docker images
* _Interop_server:_ The server program
* `run_server.py`: This is a python script which is the entry point of the docker image (i.e this is the script that is called when the docker image is run in GKE). This script launches the interop server and also updates the status in BigQuery. If the interop_server fails for whatever reason, the script launch_server.py logs that status in BigQuery
**_Stress client docker image:_**
* Stress client: The stress test client. In addition to talking to the interop_server, the stress client also exports metrics (which can be queried by the metrics_client described below)
* Metrics client: Metrics client connects to the stress_client to get the current qps metrics.
* `run_client.py`: This is a python script which is the entry point of the docker image (i.e this is the script that is called when the docker image is run in GKE). This script launches the stress client and also updates the status in BigQuery. The script then periodically launches metrics client to query the qps from the stress client and then uploads the qps to BigQuery.
### Step 2) Upload the docker images to GKE
The docker images are uploaded to the GKE registry
### Step 3) Launch the tests in GKE
The test driver reads the test matrix (described in step 1) and creates the necessary server and client pods in GKE.
### Step 4) Tests are run in GKE
GKE starts running the tests by calling the entry points in *each* docker image (i.e `run_server.py` or `run_client.py` depending on whcih docker image it is)
### Step 5) Upload the status to GKE and Monitor the status in GKE
* 5.1 The tests periodically update their status in BigQuery
* 5.2 The test driver periodically checks the status in Bigquery to see if any tests failed. If any tests failed, the driver immediately stops the tests. If not, the driver continues to run the tests for a configurable amount of time.
### Step 6) Create a summary report
The test driver creates a final summary report containing details about any test failures and information about how to connect the failed pods in GKE for debugging.

@ -336,6 +336,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/mdstr_hash_table.h',
'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/method_config.h',
'src/core/lib/transport/static_metadata.h',
'src/core/lib/transport/timeout_encoding.h',
'src/core/lib/transport/transport.h',
@ -393,12 +394,10 @@ Pod::Spec.new do |s|
'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',
'src/core/ext/client_channel/method_config.h',
'src/core/ext/client_channel/parse_address.h',
'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/resolver_result.h',
'src/core/ext/client_channel/subchannel.h',
'src/core/ext/client_channel/subchannel_index.h',
'src/core/ext/client_channel/uri_parser.h',
@ -524,6 +523,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/mdstr_hash_table.c',
'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/method_config.c',
'src/core/lib/transport/static_metadata.c',
'src/core/lib/transport/timeout_encoding.c',
'src/core/lib/transport/transport.c',
@ -590,12 +590,10 @@ Pod::Spec.new do |s|
'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',
'src/core/ext/client_channel/method_config.c',
'src/core/ext/client_channel/parse_address.c',
'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/resolver_result.c',
'src/core/ext/client_channel/subchannel.c',
'src/core/ext/client_channel/subchannel_index.c',
'src/core/ext/client_channel/uri_parser.c',
@ -731,6 +729,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/mdstr_hash_table.h',
'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/method_config.h',
'src/core/lib/transport/static_metadata.h',
'src/core/lib/transport/timeout_encoding.h',
'src/core/lib/transport/transport.h',
@ -788,12 +787,10 @@ Pod::Spec.new do |s|
'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',
'src/core/ext/client_channel/method_config.h',
'src/core/ext/client_channel/parse_address.h',
'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/resolver_result.h',
'src/core/ext/client_channel/subchannel.h',
'src/core/ext/client_channel/subchannel_index.h',
'src/core/ext/client_channel/uri_parser.h',

@ -256,6 +256,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/mdstr_hash_table.h )
s.files += %w( src/core/lib/transport/metadata.h )
s.files += %w( src/core/lib/transport/metadata_batch.h )
s.files += %w( src/core/lib/transport/method_config.h )
s.files += %w( src/core/lib/transport/static_metadata.h )
s.files += %w( src/core/lib/transport/timeout_encoding.h )
s.files += %w( src/core/lib/transport/transport.h )
@ -313,12 +314,10 @@ Gem::Specification.new do |s|
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 )
s.files += %w( src/core/ext/client_channel/method_config.h )
s.files += %w( src/core/ext/client_channel/parse_address.h )
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/resolver_result.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 )
@ -444,6 +443,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/mdstr_hash_table.c )
s.files += %w( src/core/lib/transport/metadata.c )
s.files += %w( src/core/lib/transport/metadata_batch.c )
s.files += %w( src/core/lib/transport/method_config.c )
s.files += %w( src/core/lib/transport/static_metadata.c )
s.files += %w( src/core/lib/transport/timeout_encoding.c )
s.files += %w( src/core/lib/transport/transport.c )
@ -510,12 +510,10 @@ Gem::Specification.new do |s|
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 )
s.files += %w( src/core/ext/client_channel/method_config.c )
s.files += %w( src/core/ext/client_channel/parse_address.c )
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/resolver_result.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 )

@ -204,6 +204,13 @@ typedef struct {
/** Service config data, to be passed to subchannels.
Not intended for external use. */
#define GRPC_ARG_SERVICE_CONFIG "grpc.service_config"
/** LB policy name. */
#define GRPC_ARG_LB_POLICY_NAME "grpc.lb_policy_name"
/** Server name. Not intended for external use. */
#define GRPC_ARG_SERVER_NAME "grpc.server_name"
/** Resolved addresses in a form used by the LB policy.
Not intended for external use. */
#define GRPC_ARG_LB_ADDRESSES "grpc.lb_addresses"
/** \} */
/** Result of a grpc call. If the caller satisfies the prerequisites of a

@ -34,6 +34,8 @@
},
"devDependencies": {
"async": "^1.5.0",
"body-parser": "^1.15.2",
"express": "^4.14.0",
"google-auth-library": "^0.9.2",
"google-protobuf": "^3.0.0",
"istanbul": "^0.3.21",

@ -263,6 +263,7 @@
<file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/method_config.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/static_metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/transport.h" role="src" />
@ -320,12 +321,10 @@
<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" />
<file baseinstalldir="/" name="src/core/ext/client_channel/method_config.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/parse_address.h" role="src" />
<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/resolver_result.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" />
@ -451,6 +450,7 @@
<file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/method_config.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/static_metadata.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/transport.c" role="src" />
@ -517,12 +517,10 @@
<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" />
<file baseinstalldir="/" name="src/core/ext/client_channel/method_config.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/parse_address.c" role="src" />
<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/resolver_result.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" />

@ -79,6 +79,11 @@ BUILD_WITH_CYTHON = os.environ.get('GRPC_PYTHON_BUILD_WITH_CYTHON', False)
ENABLE_CYTHON_TRACING = os.environ.get(
'GRPC_PYTHON_ENABLE_CYTHON_TRACING', False)
# Environment variable specifying whether or not there's interest in setting up
# documentation building.
ENABLE_DOCUMENTATION_BUILD = os.environ.get(
'GRPC_PYTHON_ENABLE_DOCUMENTATION_BUILD', False)
# There are some situations (like on Windows) where CC, CFLAGS, and LDFLAGS are
# entirely ignored/dropped/forgotten by distutils and its Cygwin/MinGW support.
# We use these environment variables to thus get around that without locking
@ -210,7 +215,8 @@ SETUP_REQUIRES = INSTALL_REQUIRES + (
'sphinx>=1.3',
'sphinx_rtd_theme>=0.1.8',
'six>=1.10',
)
) if ENABLE_DOCUMENTATION_BUILD else ()
if BUILD_WITH_CYTHON:
sys.stderr.write(
"You requested a Cython build via GRPC_PYTHON_BUILD_WITH_CYTHON, "

@ -5,28 +5,27 @@ This library provides high level configuration machinery to construct client
channels and load balance between them.
Each grpc_channel is created with a grpc_resolver. It is the resolver's duty
to resolve a name into configuration data for the channel. Such configuration
data might include:
to resolve a name into a set of arguments for the channel. Such arguments
might include:
- a list of (ip, port) addresses to connect to
- a load balancing policy to decide which server to send a request to
- a set of filters to mutate outgoing requests (say, by adding metadata)
The resolver provides this data as a stream of grpc_resolver_result objects to
the channel. We represent configuration as a stream so that it can be changed
by the resolver during execution, by reacting to external events (such as a
new configuration file being pushed to some store).
The resolver provides this data as a stream of grpc_channel_args objects to
the channel. We represent arguments as a stream so that they can be changed
by the resolver during execution, by reacting to external events (such as
new service configuration data being pushed to some store).
Load Balancing
--------------
Load balancing configuration is provided by a grpc_lb_policy object, stored as
part of grpc_resolver_result.
Load balancing configuration is provided by a grpc_lb_policy object.
The primary job of the load balancing policies is to pick a target server given only the
initial metadata for a request. It does this by providing a grpc_subchannel
object to the owning channel.
The primary job of the load balancing policies is to pick a target server
given only the initial metadata for a request. It does this by providing
a grpc_subchannel object to the owning channel.
Sub-Channels

@ -43,7 +43,6 @@
#include <grpc/support/useful.h>
#include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/method_config.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"
@ -56,6 +55,7 @@
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/method_config.h"
#include "src/core/lib/transport/static_metadata.h"
/* Client channel implementation */
@ -127,7 +127,7 @@ typedef struct client_channel_channel_data {
/** maps method names to method_parameters structs */
grpc_mdstr_hash_table *method_params_table;
/** incoming resolver result - set by resolver.next() */
grpc_resolver_result *resolver_result;
grpc_channel_args *resolver_result;
/** a list of closures that are all waiting for config to come in */
grpc_closure_list waiting_for_config_closures;
/** resolver callback */
@ -232,35 +232,42 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
if (chand->resolver_result != NULL) {
grpc_lb_policy_args lb_policy_args;
lb_policy_args.server_name =
grpc_resolver_result_get_server_name(chand->resolver_result);
lb_policy_args.addresses =
grpc_resolver_result_get_addresses(chand->resolver_result);
lb_policy_args.additional_args =
grpc_resolver_result_get_lb_policy_args(chand->resolver_result);
lb_policy_args.args = chand->resolver_result;
lb_policy_args.client_channel_factory = chand->client_channel_factory;
// Find LB policy name.
const char *lb_policy_name = NULL;
const grpc_arg *channel_arg =
grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_LB_POLICY_NAME);
if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
lb_policy_name = channel_arg->value.string;
}
// Special case: If all of the addresses are balancer addresses,
// assume that we should use the grpclb policy, regardless of what the
// resolver actually specified.
const char *lb_policy_name =
grpc_resolver_result_get_lb_policy_name(chand->resolver_result);
bool found_backend_address = false;
for (size_t i = 0; i < lb_policy_args.addresses->num_addresses; ++i) {
if (!lb_policy_args.addresses->addresses[i].is_balancer) {
found_backend_address = true;
break;
channel_arg =
grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_LB_ADDRESSES);
if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
bool found_backend_address = false;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (!addresses->addresses[i].is_balancer) {
found_backend_address = true;
break;
}
}
}
if (!found_backend_address) {
if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
gpr_log(GPR_INFO,
"resolver requested LB policy %s but provided only balancer "
"addresses, no backend addresses -- forcing use of grpclb LB "
"policy",
(lb_policy_name == NULL ? "(none)" : lb_policy_name));
if (!found_backend_address) {
if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
gpr_log(GPR_INFO,
"resolver requested LB policy %s but provided only balancer "
"addresses, no backend addresses -- forcing use of grpclb LB "
"policy",
lb_policy_name);
}
lb_policy_name = "grpclb";
}
lb_policy_name = "grpclb";
}
// Use pick_first if nothing was specified and we didn't select grpclb
// above.
@ -274,15 +281,15 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
state =
grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
}
const grpc_arg *channel_arg = grpc_channel_args_find(
lb_policy_args.additional_args, GRPC_ARG_SERVICE_CONFIG);
channel_arg =
grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_SERVICE_CONFIG);
if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
method_params_table = grpc_method_config_table_convert(
(grpc_method_config_table *)channel_arg->value.pointer.p,
method_config_convert_value, &method_parameters_vtable);
}
grpc_resolver_result_unref(exec_ctx, chand->resolver_result);
grpc_channel_args_destroy(chand->resolver_result);
chand->resolver_result = NULL;
}

@ -44,14 +44,14 @@ void grpc_client_channel_factory_unref(grpc_exec_ctx* exec_ctx,
grpc_subchannel* grpc_client_channel_factory_create_subchannel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory,
grpc_subchannel_args* args) {
const grpc_subchannel_args* args) {
return factory->vtable->create_subchannel(exec_ctx, factory, args);
}
grpc_channel* grpc_client_channel_factory_create_channel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory,
const char* target, grpc_client_channel_type type,
grpc_channel_args* args) {
const grpc_channel_args* args) {
return factory->vtable->create_client_channel(exec_ctx, factory, target, type,
args);
}

@ -60,12 +60,12 @@ struct grpc_client_channel_factory_vtable {
void (*unref)(grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory);
grpc_subchannel *(*create_subchannel)(grpc_exec_ctx *exec_ctx,
grpc_client_channel_factory *factory,
grpc_subchannel_args *args);
const grpc_subchannel_args *args);
grpc_channel *(*create_client_channel)(grpc_exec_ctx *exec_ctx,
grpc_client_channel_factory *factory,
const char *target,
grpc_client_channel_type type,
grpc_channel_args *args);
const grpc_channel_args *args);
};
void grpc_client_channel_factory_ref(grpc_client_channel_factory *factory);
@ -75,11 +75,12 @@ void grpc_client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
/** Create a new grpc_subchannel */
grpc_subchannel *grpc_client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
grpc_subchannel_args *args);
const grpc_subchannel_args *args);
/** Create a new grpc_channel */
grpc_channel *grpc_client_channel_factory_create_channel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
const char *target, grpc_client_channel_type type, grpc_channel_args *args);
const char *target, grpc_client_channel_type type,
const grpc_channel_args *args);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H */

@ -38,19 +38,20 @@
#include "src/core/ext/client_channel/lb_policy_factory.h"
grpc_lb_addresses* grpc_lb_addresses_create(size_t num_addresses) {
grpc_lb_addresses* grpc_lb_addresses_create(
size_t num_addresses, const grpc_lb_user_data_vtable* user_data_vtable) {
grpc_lb_addresses* addresses = gpr_malloc(sizeof(grpc_lb_addresses));
addresses->num_addresses = num_addresses;
addresses->user_data_vtable = user_data_vtable;
const size_t addresses_size = sizeof(grpc_lb_address) * num_addresses;
addresses->addresses = gpr_malloc(addresses_size);
memset(addresses->addresses, 0, addresses_size);
return addresses;
}
grpc_lb_addresses* grpc_lb_addresses_copy(grpc_lb_addresses* addresses,
void* (*user_data_copy)(void*)) {
grpc_lb_addresses* new_addresses =
grpc_lb_addresses_create(addresses->num_addresses);
grpc_lb_addresses* grpc_lb_addresses_copy(const grpc_lb_addresses* addresses) {
grpc_lb_addresses* new_addresses = grpc_lb_addresses_create(
addresses->num_addresses, addresses->user_data_vtable);
memcpy(new_addresses->addresses, addresses->addresses,
sizeof(grpc_lb_address) * addresses->num_addresses);
for (size_t i = 0; i < addresses->num_addresses; ++i) {
@ -58,9 +59,9 @@ grpc_lb_addresses* grpc_lb_addresses_copy(grpc_lb_addresses* addresses,
new_addresses->addresses[i].balancer_name =
gpr_strdup(new_addresses->addresses[i].balancer_name);
}
if (user_data_copy != NULL) {
new_addresses->addresses[i].user_data =
user_data_copy(new_addresses->addresses[i].user_data);
if (new_addresses->addresses[i].user_data != NULL) {
new_addresses->addresses[i].user_data = addresses->user_data_vtable->copy(
new_addresses->addresses[i].user_data);
}
}
return new_addresses;
@ -71,6 +72,7 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
bool is_balancer, char* balancer_name,
void* user_data) {
GPR_ASSERT(index < addresses->num_addresses);
if (user_data != NULL) GPR_ASSERT(addresses->user_data_vtable != NULL);
grpc_lb_address* target = &addresses->addresses[index];
memcpy(target->address.addr, address, address_len);
target->address.len = address_len;
@ -79,18 +81,70 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
target->user_data = user_data;
}
void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses,
void (*user_data_destroy)(void*)) {
int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1,
const grpc_lb_addresses* addresses2) {
if (addresses1->num_addresses > addresses2->num_addresses) return 1;
if (addresses1->num_addresses < addresses2->num_addresses) return -1;
if (addresses1->user_data_vtable > addresses2->user_data_vtable) return 1;
if (addresses1->user_data_vtable < addresses2->user_data_vtable) return -1;
for (size_t i = 0; i < addresses1->num_addresses; ++i) {
const grpc_lb_address* target1 = &addresses1->addresses[i];
const grpc_lb_address* target2 = &addresses2->addresses[i];
if (target1->address.len > target2->address.len) return 1;
if (target1->address.len < target2->address.len) return -1;
int retval = memcmp(target1->address.addr, target2->address.addr,
target1->address.len);
if (retval != 0) return retval;
if (target1->is_balancer > target2->is_balancer) return 1;
if (target1->is_balancer < target2->is_balancer) return -1;
const char* balancer_name1 =
target1->balancer_name != NULL ? target1->balancer_name : "";
const char* balancer_name2 =
target2->balancer_name != NULL ? target2->balancer_name : "";
retval = strcmp(balancer_name1, balancer_name2);
if (retval != 0) return retval;
if (addresses1->user_data_vtable != NULL) {
retval = addresses1->user_data_vtable->cmp(target1->user_data,
target2->user_data);
if (retval != 0) return retval;
}
}
return 0;
}
void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses) {
for (size_t i = 0; i < addresses->num_addresses; ++i) {
gpr_free(addresses->addresses[i].balancer_name);
if (user_data_destroy != NULL) {
user_data_destroy(addresses->addresses[i].user_data);
if (addresses->addresses[i].user_data != NULL) {
addresses->user_data_vtable->destroy(addresses->addresses[i].user_data);
}
}
gpr_free(addresses->addresses);
gpr_free(addresses);
}
static void* lb_addresses_copy(void* addresses) {
return grpc_lb_addresses_copy(addresses);
}
static void lb_addresses_destroy(void* addresses) {
grpc_lb_addresses_destroy(addresses);
}
static int lb_addresses_cmp(void* addresses1, void* addresses2) {
return grpc_lb_addresses_cmp(addresses1, addresses2);
}
static const grpc_arg_pointer_vtable lb_addresses_arg_vtable = {
lb_addresses_copy, lb_addresses_destroy, lb_addresses_cmp};
grpc_arg grpc_lb_addresses_create_channel_arg(
const grpc_lb_addresses* addresses) {
grpc_arg arg;
arg.type = GRPC_ARG_POINTER;
arg.key = GRPC_ARG_LB_ADDRESSES;
arg.value.pointer.p = (void*)addresses;
arg.value.pointer.vtable = &lb_addresses_arg_vtable;
return arg;
}
void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) {
factory->vtable->ref(factory);
}

@ -59,19 +59,26 @@ typedef struct grpc_lb_address {
void *user_data;
} grpc_lb_address;
typedef struct grpc_lb_user_data_vtable {
void *(*copy)(void *);
void (*destroy)(void *);
int (*cmp)(void *, void *);
} grpc_lb_user_data_vtable;
typedef struct grpc_lb_addresses {
size_t num_addresses;
grpc_lb_address *addresses;
const grpc_lb_user_data_vtable *user_data_vtable;
} grpc_lb_addresses;
/** Returns a grpc_addresses struct with enough space for
* \a num_addresses addresses. */
grpc_lb_addresses *grpc_lb_addresses_create(size_t num_addresses);
\a num_addresses addresses. The \a user_data_vtable argument may be
NULL if no user data will be added. */
grpc_lb_addresses *grpc_lb_addresses_create(
size_t num_addresses, const grpc_lb_user_data_vtable *user_data_vtable);
/** Creates a copy of \a addresses. If \a user_data_copy is not NULL,
* it will be invoked to copy the \a user_data field of each address. */
grpc_lb_addresses *grpc_lb_addresses_copy(grpc_lb_addresses *addresses,
void *(*user_data_copy)(void *));
/** Creates a copy of \a addresses. */
grpc_lb_addresses *grpc_lb_addresses_copy(const grpc_lb_addresses *addresses);
/** Sets the value of the address at index \a index of \a addresses.
* \a address is a socket address of length \a address_len.
@ -81,20 +88,21 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses *addresses, size_t index,
bool is_balancer, char *balancer_name,
void *user_data);
/** Destroys \a addresses. If \a user_data_destroy is not NULL, it will
* be invoked to destroy the \a user_data field of each address. */
void grpc_lb_addresses_destroy(grpc_lb_addresses *addresses,
void (*user_data_destroy)(void *));
/** Compares \a addresses1 and \a addresses2. */
int grpc_lb_addresses_cmp(const grpc_lb_addresses *addresses1,
const grpc_lb_addresses *addresses2);
/** Destroys \a addresses. */
void grpc_lb_addresses_destroy(grpc_lb_addresses *addresses);
/** Returns a channel arg containing \a addresses. */
grpc_arg grpc_lb_addresses_create_channel_arg(
const grpc_lb_addresses *addresses);
/** Arguments passed to LB policies. */
/* TODO(roth, ctiller): Consider replacing this struct with
grpc_channel_args. See comment in resolver_result.h for details. */
typedef struct grpc_lb_policy_args {
const char *server_name;
grpc_lb_addresses *addresses;
grpc_client_channel_factory *client_channel_factory;
/* Can be used to pass implementation-specific parameters to the LB policy. */
grpc_channel_args *additional_args;
grpc_channel_args *args;
} grpc_lb_policy_args;
struct grpc_lb_policy_factory_vtable {

@ -76,7 +76,6 @@ void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
}
void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_resolver_result **result,
grpc_closure *on_complete) {
grpc_channel_args **result, grpc_closure *on_complete) {
resolver->vtable->next(exec_ctx, resolver, result, on_complete);
}

@ -34,15 +34,13 @@
#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H
#define GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H
#include "src/core/ext/client_channel/resolver_result.h"
#include "src/core/ext/client_channel/subchannel.h"
#include "src/core/lib/iomgr/iomgr.h"
typedef struct grpc_resolver grpc_resolver;
typedef struct grpc_resolver_vtable grpc_resolver_vtable;
/** grpc_resolver provides grpc_resolver_result objects to grpc_channel
objects */
/** \a grpc_resolver provides \a grpc_channel_args objects to its caller */
struct grpc_resolver {
const grpc_resolver_vtable *vtable;
gpr_refcount refs;
@ -53,7 +51,7 @@ struct grpc_resolver_vtable {
void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
void (*next)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_resolver_result **result, grpc_closure *on_complete);
grpc_channel_args **result, grpc_closure *on_complete);
};
#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
@ -81,14 +79,12 @@ void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver);
/** Get the next client config. Called by the channel to fetch a new
configuration. Expected to set *result with a new configuration,
and then schedule on_complete for execution.
/** Get the next result from the resolver. Expected to set \a *result with
new channel args and then schedule \a on_complete for execution.
If resolution is fatally broken, set *result to NULL and
schedule on_complete. */
If resolution is fatally broken, set \a *result to NULL and
schedule \a on_complete. */
void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_resolver_result **result,
grpc_closure *on_complete);
grpc_channel_args **result, grpc_closure *on_complete);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H */

@ -41,13 +41,14 @@
typedef struct grpc_resolver_factory grpc_resolver_factory;
typedef struct grpc_resolver_factory_vtable grpc_resolver_factory_vtable;
/** grpc_resolver provides grpc_resolver_result objects to grpc_channel
objects */
struct grpc_resolver_factory {
const grpc_resolver_factory_vtable *vtable;
};
typedef struct grpc_resolver_args { grpc_uri *uri; } grpc_resolver_args;
typedef struct grpc_resolver_args {
grpc_uri *uri;
const grpc_channel_args *args;
} grpc_resolver_args;
struct grpc_resolver_factory_vtable {
void (*ref)(grpc_resolver_factory *factory);

@ -131,14 +131,16 @@ static grpc_resolver_factory *resolve_factory(const char *target,
return factory;
}
grpc_resolver *grpc_resolver_create(const char *target) {
grpc_resolver *grpc_resolver_create(const char *target,
const grpc_channel_args *args) {
grpc_uri *uri = NULL;
grpc_resolver_factory *factory = resolve_factory(target, &uri);
grpc_resolver *resolver;
grpc_resolver_args args;
memset(&args, 0, sizeof(args));
args.uri = uri;
resolver = grpc_resolver_factory_create_resolver(factory, &args);
grpc_resolver_args resolver_args;
memset(&resolver_args, 0, sizeof(resolver_args));
resolver_args.uri = uri;
resolver_args.args = args;
resolver = grpc_resolver_factory_create_resolver(factory, &resolver_args);
grpc_uri_destroy(uri);
return resolver;
}

@ -57,8 +57,11 @@ void grpc_register_resolver_type(grpc_resolver_factory *factory);
was not NULL).
If a resolver factory was found, use it to instantiate a resolver and
return it.
If a resolver factory was not found, return NULL. */
grpc_resolver *grpc_resolver_create(const char *target);
If a resolver factory was not found, return NULL.
\a args is a set of channel arguments to be included in the result
(typically the set of arguments passed in from the client API). */
grpc_resolver *grpc_resolver_create(const char *target,
const grpc_channel_args *args);
/** Find a resolver factory given a name and return an (owned-by-the-caller)
* reference to it */

@ -1,94 +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.
//
#include "src/core/ext/client_channel/resolver_result.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h"
struct grpc_resolver_result {
gpr_refcount refs;
char* server_name;
grpc_lb_addresses* addresses;
char* lb_policy_name;
grpc_channel_args* lb_policy_args;
};
grpc_resolver_result* grpc_resolver_result_create(
const char* server_name, grpc_lb_addresses* addresses,
const char* lb_policy_name, grpc_channel_args* lb_policy_args) {
grpc_resolver_result* result = gpr_malloc(sizeof(*result));
memset(result, 0, sizeof(*result));
gpr_ref_init(&result->refs, 1);
result->server_name = gpr_strdup(server_name);
result->addresses = addresses;
result->lb_policy_name = gpr_strdup(lb_policy_name);
result->lb_policy_args = lb_policy_args;
return result;
}
void grpc_resolver_result_ref(grpc_resolver_result* result) {
gpr_ref(&result->refs);
}
void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx,
grpc_resolver_result* result) {
if (gpr_unref(&result->refs)) {
gpr_free(result->server_name);
grpc_lb_addresses_destroy(result->addresses, NULL /* user_data_destroy */);
gpr_free(result->lb_policy_name);
grpc_channel_args_destroy(result->lb_policy_args);
gpr_free(result);
}
}
const char* grpc_resolver_result_get_server_name(grpc_resolver_result* result) {
return result->server_name;
}
grpc_lb_addresses* grpc_resolver_result_get_addresses(
grpc_resolver_result* result) {
return result->addresses;
}
const char* grpc_resolver_result_get_lb_policy_name(
grpc_resolver_result* result) {
return result->lb_policy_name;
}
grpc_channel_args* grpc_resolver_result_get_lb_policy_args(
grpc_resolver_result* result) {
return result->lb_policy_args;
}

@ -1,68 +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_RESOLVER_RESULT_H
#define GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H
#include "src/core/ext/client_channel/lb_policy_factory.h"
// TODO(roth, ctiller): In the long term, we are considering replacing
// the resolver_result data structure with grpc_channel_args. The idea is
// that the resolver will return a set of channel args that contains the
// information that is currently in the resolver_result struct. For
// example, there will be specific args indicating the set of addresses
// and the name of the LB policy to instantiate. Note that if we did
// this, we would probably want to change the data structure of
// grpc_channel_args such to a hash table or AVL or some other data
// structure that does not require linear search to find keys.
/// Results reported from a grpc_resolver.
typedef struct grpc_resolver_result grpc_resolver_result;
/// Takes ownership of \a addresses and \a lb_policy_args.
grpc_resolver_result* grpc_resolver_result_create(
const char* server_name, grpc_lb_addresses* addresses,
const char* lb_policy_name, grpc_channel_args* lb_policy_args);
void grpc_resolver_result_ref(grpc_resolver_result* result);
void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx,
grpc_resolver_result* result);
/// Accessors. Caller does NOT take ownership of results.
const char* grpc_resolver_result_get_server_name(grpc_resolver_result* result);
grpc_lb_addresses* grpc_resolver_result_get_addresses(
grpc_resolver_result* result);
const char* grpc_resolver_result_get_lb_policy_name(
grpc_resolver_result* result);
grpc_channel_args* grpc_resolver_result_get_lb_policy_args(
grpc_resolver_result* result);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H */

@ -297,7 +297,7 @@ void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
grpc_connector *connector,
grpc_subchannel_args *args) {
const grpc_subchannel_args *args) {
grpc_subchannel_key *key = grpc_subchannel_key_create(connector, args);
grpc_subchannel *c = grpc_subchannel_index_find(exec_ctx, key);
if (c) {

@ -173,6 +173,6 @@ struct grpc_subchannel_args {
/** create a subchannel given a connector */
grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
grpc_connector *connector,
grpc_subchannel_args *args);
const grpc_subchannel_args *args);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_SUBCHANNEL_H */

@ -73,7 +73,7 @@ static grpc_exec_ctx *current_ctx() {
}
static grpc_subchannel_key *create_key(
grpc_connector *connector, grpc_subchannel_args *args,
grpc_connector *connector, const grpc_subchannel_args *args,
grpc_channel_args *(*copy_channel_args)(const grpc_channel_args *args)) {
grpc_subchannel_key *k = gpr_malloc(sizeof(*k));
k->connector = grpc_connector_ref(connector);
@ -96,8 +96,8 @@ static grpc_subchannel_key *create_key(
return k;
}
grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *connector,
grpc_subchannel_args *args) {
grpc_subchannel_key *grpc_subchannel_key_create(
grpc_connector *connector, const grpc_subchannel_args *args) {
return create_key(connector, args, grpc_channel_args_normalize);
}

@ -43,8 +43,8 @@
typedef struct grpc_subchannel_key grpc_subchannel_key;
/** Create a key that can be used to uniquely identify a subchannel */
grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *con,
grpc_subchannel_args *args);
grpc_subchannel_key *grpc_subchannel_key_create(
grpc_connector *con, const grpc_subchannel_args *args);
/** Destroy a subchannel key */
void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx,

@ -343,6 +343,21 @@ static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
return true;
}
/* vtable for LB tokens in grpc_lb_addresses. */
static void *lb_token_copy(void *token) {
return token == NULL ? NULL : GRPC_MDELEM_REF(token);
}
static void lb_token_destroy(void *token) {
if (token != NULL) GRPC_MDELEM_UNREF(token);
}
static int lb_token_cmp(void *token1, void *token2) {
if (token1 > token2) return 1;
if (token1 < token2) return -1;
return 0;
}
static const grpc_lb_user_data_vtable lb_token_vtable = {
lb_token_copy, lb_token_destroy, lb_token_cmp};
/* Returns addresses extracted from \a serverlist. */
static grpc_lb_addresses *process_serverlist(
const grpc_grpclb_serverlist *serverlist) {
@ -354,7 +369,8 @@ static grpc_lb_addresses *process_serverlist(
}
if (num_valid == 0) return NULL;
grpc_lb_addresses *lb_addresses = grpc_lb_addresses_create(num_valid);
grpc_lb_addresses *lb_addresses =
grpc_lb_addresses_create(num_valid, &lb_token_vtable);
/* second pass: actually populate the addresses and LB tokens (aka user data
* to the outside world) to be read by the RR policy during its creation.
@ -415,11 +431,6 @@ static grpc_lb_addresses *process_serverlist(
return lb_addresses;
}
/* A plugin for grpc_lb_addresses_destroy that unrefs the LB token metadata. */
static void lb_token_destroy(void *token) {
if (token != NULL) GRPC_MDELEM_UNREF(token);
}
/* perform a pick over \a rr_policy. Given that a pick can return immediately
* (ignoring its completion callback) we need to perform the cleanups this
* callback would be otherwise resposible for */
@ -459,20 +470,27 @@ static grpc_lb_policy *create_rr_locked(
glb_lb_policy *glb_policy) {
GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0);
if (glb_policy->addresses != NULL) {
/* dispose of the previous version */
grpc_lb_addresses_destroy(glb_policy->addresses);
}
glb_policy->addresses = process_serverlist(serverlist);
grpc_lb_policy_args args;
memset(&args, 0, sizeof(args));
args.server_name = glb_policy->server_name;
args.client_channel_factory = glb_policy->cc_factory;
args.addresses = process_serverlist(serverlist);
args.additional_args = glb_policy->args;
grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
// Replace the LB addresses in the channel args that we pass down to
// the subchannel.
static const char *keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
const grpc_arg arg =
grpc_lb_addresses_create_channel_arg(glb_policy->addresses);
args.args = grpc_channel_args_copy_and_add_and_remove(
glb_policy->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg,
1);
if (glb_policy->addresses != NULL) {
/* dispose of the previous version */
grpc_lb_addresses_destroy(glb_policy->addresses, lb_token_destroy);
}
glb_policy->addresses = args.addresses;
grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
grpc_channel_args_destroy(args.args);
return rr;
}
@ -568,6 +586,12 @@ static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) {
/* Get server name. */
const grpc_arg *arg =
grpc_channel_args_find(args->args, GRPC_ARG_SERVER_NAME);
const char *server_name =
arg != NULL && arg->type == GRPC_ARG_STRING ? arg->value.string : NULL;
/* Count the number of gRPC-LB addresses. There must be at least one.
* TODO(roth): For now, we ignore non-balancer addresses, but in the
* future, we may change the behavior such that we fall back to using
@ -575,24 +599,27 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
* time, this should be changed to allow a list with no balancer addresses,
* since the resolver might fail to return a balancer address even when
* this is the right LB policy to use. */
arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
grpc_lb_addresses *addresses = arg->value.pointer.p;
size_t num_grpclb_addrs = 0;
for (size_t i = 0; i < args->addresses->num_addresses; ++i) {
if (args->addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
}
if (num_grpclb_addrs == 0) return NULL;
glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy));
memset(glb_policy, 0, sizeof(*glb_policy));
/* All input addresses in args->addresses come from a resolver that claims
/* All input addresses in addresses come from a resolver that claims
* they are LB services. It's the resolver's responsibility to make sure
* this
* policy is only instantiated and used in that case.
*
* Create a client channel over them to communicate with a LB service */
glb_policy->server_name = gpr_strdup(args->server_name);
glb_policy->server_name = gpr_strdup(server_name);
glb_policy->cc_factory = args->client_channel_factory;
glb_policy->args = grpc_channel_args_copy(args->additional_args);
glb_policy->args = grpc_channel_args_copy(args->args);
GPR_ASSERT(glb_policy->cc_factory != NULL);
/* construct a target from the addresses in args, given in the form
@ -600,19 +627,19 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
* TODO(dgq): support mixed ip version */
char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs);
size_t addr_index = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) {
if (args->addresses->addresses[i].user_data != NULL) {
for (size_t i = 0; i < addresses->num_addresses; i++) {
if (addresses->addresses[i].user_data != NULL) {
gpr_log(GPR_ERROR,
"This LB policy doesn't support user data. It will be ignored");
}
if (args->addresses->addresses[i].is_balancer) {
if (addresses->addresses[i].is_balancer) {
if (addr_index == 0) {
addr_strs[addr_index++] =
grpc_sockaddr_to_uri(&args->addresses->addresses[i].address);
grpc_sockaddr_to_uri(&addresses->addresses[i].address);
} else {
GPR_ASSERT(grpc_sockaddr_to_string(
&addr_strs[addr_index++],
&args->addresses->addresses[i].address, true) > 0);
GPR_ASSERT(grpc_sockaddr_to_string(&addr_strs[addr_index++],
&addresses->addresses[i].address,
true) > 0);
}
}
}
@ -620,10 +647,29 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
char *target_uri_str = gpr_strjoin_sep((const char **)addr_strs,
num_grpclb_addrs, ",", &uri_path_len);
/* will pick using pick_first */
/* Create a channel to talk to the LBs.
*
* We strip out the channel arg for the LB policy name, since we want
* to use the default (pick_first) in this case.
*
* We also strip out the channel arg for the resolved addresses, since
* that will be generated by the name resolver used in the LB channel.
* Note that the LB channel will use the sockaddr resolver, so this
* won't actually generate a query to DNS (or some other name service).
* However, the addresses returned by the sockaddr resolver will have
* is_balancer=false, whereas our own addresses have is_balancer=true.
* We need the LB channel to return addresses with is_balancer=false
* so that it does not wind up recursively using the grpclb LB policy,
* as per the special case logic in client_channel.c.
*/
static const char *keys_to_remove[] = {GRPC_ARG_LB_POLICY_NAME,
GRPC_ARG_LB_ADDRESSES};
grpc_channel_args *new_args = grpc_channel_args_copy_and_remove(
args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove));
glb_policy->lb_channel = grpc_client_channel_factory_create_channel(
exec_ctx, glb_policy->cc_factory, target_uri_str,
GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, NULL);
GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args);
grpc_channel_args_destroy(new_args);
gpr_free(target_uri_str);
for (size_t i = 0; i < num_grpclb_addrs; i++) {
@ -664,7 +710,7 @@ static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
}
gpr_mu_destroy(&glb_policy->mu);
grpc_lb_addresses_destroy(glb_policy->addresses, lb_token_destroy);
grpc_lb_addresses_destroy(glb_policy->addresses);
gpr_free(glb_policy);
}

@ -34,7 +34,9 @@
#include <string.h>
#include <grpc/support/alloc.h>
#include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/transport/connectivity_state.h"
typedef struct pending_pick {
@ -432,14 +434,22 @@ static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) {
GPR_ASSERT(args->addresses != NULL);
GPR_ASSERT(args->client_channel_factory != NULL);
/* Get server name. */
const grpc_arg *arg =
grpc_channel_args_find(args->args, GRPC_ARG_SERVER_NAME);
const char *server_name =
arg != NULL && arg->type == GRPC_ARG_STRING ? arg->value.string : NULL;
/* Find the number of backend addresses. We ignore balancer
* addresses, since we don't know how to handle them. */
arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
grpc_lb_addresses *addresses = arg->value.pointer.p;
size_t num_addrs = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) {
if (!args->addresses->addresses[i].is_balancer) ++num_addrs;
for (size_t i = 0; i < addresses->num_addresses; i++) {
if (!addresses->addresses[i].is_balancer) ++num_addrs;
}
if (num_addrs == 0) return NULL;
@ -450,21 +460,21 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs);
grpc_subchannel_args sc_args;
size_t subchannel_idx = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) {
for (size_t i = 0; i < addresses->num_addresses; i++) {
/* Skip balancer addresses, since we only know how to handle backends. */
if (args->addresses->addresses[i].is_balancer) continue;
if (addresses->addresses[i].is_balancer) continue;
if (args->addresses->addresses[i].user_data != NULL) {
if (addresses->addresses[i].user_data != NULL) {
gpr_log(GPR_ERROR,
"This LB policy doesn't support user data. It will be ignored");
}
memset(&sc_args, 0, sizeof(grpc_subchannel_args));
/* server_name will be copied as part of the subchannel creation. This makes
* the copying of args->server_name (a borrowed pointer) OK. */
sc_args.server_name = args->server_name;
sc_args.addr = &args->addresses->addresses[i].address;
sc_args.args = args->additional_args;
* the copying of server_name (a borrowed pointer) OK. */
sc_args.server_name = server_name;
sc_args.addr = &addresses->addresses[i].address;
sc_args.args = args->args;
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
exec_ctx, args->client_channel_factory, &sc_args);

@ -64,6 +64,7 @@
#include <grpc/support/alloc.h>
#include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/static_metadata.h"
@ -598,14 +599,22 @@ static void round_robin_factory_unref(grpc_lb_policy_factory *factory) {}
static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) {
GPR_ASSERT(args->addresses != NULL);
GPR_ASSERT(args->client_channel_factory != NULL);
/* Get server name. */
const grpc_arg *arg =
grpc_channel_args_find(args->args, GRPC_ARG_SERVER_NAME);
const char *server_name =
arg != NULL && arg->type == GRPC_ARG_STRING ? arg->value.string : NULL;
/* Find the number of backend addresses. We ignore balancer
* addresses, since we don't know how to handle them. */
arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
grpc_lb_addresses *addresses = arg->value.pointer.p;
size_t num_addrs = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) {
if (!args->addresses->addresses[i].is_balancer) ++num_addrs;
for (size_t i = 0; i < addresses->num_addresses; i++) {
if (!addresses->addresses[i].is_balancer) ++num_addrs;
}
if (num_addrs == 0) return NULL;
@ -618,16 +627,16 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
grpc_subchannel_args sc_args;
size_t subchannel_idx = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) {
for (size_t i = 0; i < addresses->num_addresses; i++) {
/* Skip balancer addresses, since we only know how to handle backends. */
if (args->addresses->addresses[i].is_balancer) continue;
if (addresses->addresses[i].is_balancer) continue;
memset(&sc_args, 0, sizeof(grpc_subchannel_args));
/* server_name will be copied as part of the subchannel creation. This makes
* the copying of args->server_name (a borrowed pointer) OK. */
sc_args.server_name = args->server_name;
sc_args.addr = &args->addresses->addresses[i].address;
sc_args.args = args->additional_args;
* the copying of server_name (a borrowed pointer) OK. */
sc_args.server_name = server_name;
sc_args.addr = &addresses->addresses[i].address;
sc_args.args = args->args;
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
exec_ctx, args->client_channel_factory, &sc_args);
@ -639,7 +648,7 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
sd->policy = p;
sd->index = subchannel_idx;
sd->subchannel = subchannel;
sd->user_data = args->addresses->addresses[i].user_data;
sd->user_data = addresses->addresses[i].user_data;
++subchannel_idx;
grpc_closure_init(&sd->connectivity_changed_closure,
rr_connectivity_changed, sd);

@ -40,6 +40,7 @@
#include "src/core/ext/client_channel/http_connect_handshaker.h"
#include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/support/backoff.h"
@ -53,12 +54,12 @@
typedef struct {
/** base class: must be first */
grpc_resolver base;
/** target name */
char *target_name;
/** name to resolve (usually the same as target_name) */
/** name to resolve */
char *name_to_resolve;
/** default port to use */
char *default_port;
/** channel args. */
grpc_channel_args *channel_args;
/** mutex guarding the rest of the state */
gpr_mu mu;
@ -71,9 +72,9 @@ typedef struct {
/** pending next completion, or NULL */
grpc_closure *next_completion;
/** target result address for next completion */
grpc_resolver_result **target_result;
grpc_channel_args **target_result;
/** current (fully resolved) result */
grpc_resolver_result *resolved_result;
grpc_channel_args *resolved_result;
/** retry timer */
bool have_retry_timer;
grpc_timer retry_timer;
@ -94,7 +95,7 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
grpc_resolver_result **target_result,
grpc_channel_args **target_result,
grpc_closure *on_complete);
static const grpc_resolver_vtable dns_resolver_vtable = {
@ -127,7 +128,7 @@ static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
}
static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_resolver_result **target_result,
grpc_channel_args **target_result,
grpc_closure *on_complete) {
dns_resolver *r = (dns_resolver *)resolver;
gpr_mu_lock(&r->mu);
@ -162,22 +163,23 @@ static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
dns_resolver *r = arg;
grpc_resolver_result *result = NULL;
grpc_channel_args *result = NULL;
gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving);
r->resolving = false;
if (r->addresses != NULL) {
grpc_lb_addresses *addresses =
grpc_lb_addresses_create(r->addresses->naddrs);
grpc_lb_addresses *addresses = grpc_lb_addresses_create(
r->addresses->naddrs, NULL /* user_data_vtable */);
for (size_t i = 0; i < r->addresses->naddrs; ++i) {
grpc_lb_addresses_set_address(
addresses, i, &r->addresses->addrs[i].addr,
r->addresses->addrs[i].len, false /* is_balancer */,
NULL /* balancer_name */, NULL /* user_data */);
}
grpc_arg new_arg = grpc_lb_addresses_create_channel_arg(addresses);
result = grpc_channel_args_copy_and_add(r->channel_args, &new_arg, 1);
grpc_resolved_addresses_destroy(r->addresses);
result = grpc_resolver_result_create(r->target_name, addresses,
NULL /* lb_policy_name */, NULL);
grpc_lb_addresses_destroy(addresses);
} else {
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
@ -197,8 +199,8 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_timer_init(exec_ctx, &r->retry_timer, next_try, dns_on_retry_timer, r,
now);
}
if (r->resolved_result) {
grpc_resolver_result_unref(exec_ctx, r->resolved_result);
if (r->resolved_result != NULL) {
grpc_channel_args_destroy(r->resolved_result);
}
r->resolved_result = result;
r->resolved_version++;
@ -222,10 +224,9 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
dns_resolver *r) {
if (r->next_completion != NULL &&
r->resolved_version != r->published_version) {
*r->target_result = r->resolved_result;
if (r->resolved_result) {
grpc_resolver_result_ref(r->resolved_result);
}
*r->target_result = r->resolved_result == NULL
? NULL
: grpc_channel_args_copy(r->resolved_result);
grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
r->next_completion = NULL;
r->published_version = r->resolved_version;
@ -235,12 +236,12 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
dns_resolver *r = (dns_resolver *)gr;
gpr_mu_destroy(&r->mu);
if (r->resolved_result) {
grpc_resolver_result_unref(exec_ctx, r->resolved_result);
if (r->resolved_result != NULL) {
grpc_channel_args_destroy(r->resolved_result);
}
gpr_free(r->target_name);
gpr_free(r->name_to_resolve);
gpr_free(r->default_port);
grpc_channel_args_destroy(r->channel_args);
gpr_free(r);
}
@ -260,9 +261,14 @@ static grpc_resolver *dns_create(grpc_resolver_args *args,
memset(r, 0, sizeof(*r));
gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &dns_resolver_vtable);
r->target_name = gpr_strdup(path);
r->name_to_resolve = proxy_name == NULL ? gpr_strdup(path) : proxy_name;
r->default_port = gpr_strdup(default_port);
grpc_arg server_name_arg;
server_name_arg.type = GRPC_ARG_STRING;
server_name_arg.key = GRPC_ARG_SERVER_NAME;
server_name_arg.value.string = (char *)path;
r->channel_args =
grpc_channel_args_copy_and_add(args->args, &server_name_arg, 1);
gpr_backoff_init(&r->backoff_state, BACKOFF_MULTIPLIER, BACKOFF_JITTER,
BACKOFF_MIN_SECONDS * 1000, BACKOFF_MAX_SECONDS * 1000);
return &r->base;

@ -41,8 +41,10 @@
#include <grpc/support/port_platform.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/client_channel/lb_policy_factory.h"
#include "src/core/ext/client_channel/parse_address.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/support/string.h"
@ -50,10 +52,10 @@
typedef struct {
/** base class: must be first */
grpc_resolver base;
/** the path component of the uri passed in */
char *target_name;
/** the addresses that we've 'resolved' */
grpc_lb_addresses *addresses;
/** channel args */
grpc_channel_args *channel_args;
/** mutex guarding the rest of the state */
gpr_mu mu;
/** have we published? */
@ -61,7 +63,7 @@ typedef struct {
/** pending next completion, or NULL */
grpc_closure *next_completion;
/** target result address for next completion */
grpc_resolver_result **target_result;
grpc_channel_args **target_result;
} sockaddr_resolver;
static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
@ -73,7 +75,7 @@ static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *r);
static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
grpc_resolver_result **target_result,
grpc_channel_args **target_result,
grpc_closure *on_complete);
static const grpc_resolver_vtable sockaddr_resolver_vtable = {
@ -102,7 +104,7 @@ static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
}
static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_resolver_result **target_result,
grpc_channel_args **target_result,
grpc_closure *on_complete) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
gpr_mu_lock(&r->mu);
@ -117,10 +119,9 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
sockaddr_resolver *r) {
if (r->next_completion != NULL && !r->published) {
r->published = true;
*r->target_result = grpc_resolver_result_create(
r->target_name,
grpc_lb_addresses_copy(r->addresses, NULL /* user_data_copy */),
NULL /* lb_policy_name */, NULL /* lb_policy_args */);
grpc_arg arg = grpc_lb_addresses_create_channel_arg(r->addresses);
*r->target_result =
grpc_channel_args_copy_and_add(r->channel_args, &arg, 1);
grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
r->next_completion = NULL;
}
@ -129,8 +130,8 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
sockaddr_resolver *r = (sockaddr_resolver *)gr;
gpr_mu_destroy(&r->mu);
gpr_free(r->target_name);
grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */);
grpc_lb_addresses_destroy(r->addresses);
grpc_channel_args_destroy(r->channel_args);
gpr_free(r);
}
@ -173,7 +174,8 @@ static grpc_resolver *sockaddr_create(grpc_resolver_args *args,
gpr_slice_buffer path_parts;
gpr_slice_buffer_init(&path_parts);
gpr_slice_split(path_slice, ",", &path_parts);
grpc_lb_addresses *addresses = grpc_lb_addresses_create(path_parts.count);
grpc_lb_addresses *addresses =
grpc_lb_addresses_create(path_parts.count, NULL /* user_data_vtable */);
bool errors_found = false;
for (size_t i = 0; i < addresses->num_addresses; i++) {
grpc_uri ith_uri = *args->uri;
@ -188,14 +190,19 @@ static grpc_resolver *sockaddr_create(grpc_resolver_args *args,
gpr_slice_buffer_destroy(&path_parts);
gpr_slice_unref(path_slice);
if (errors_found) {
grpc_lb_addresses_destroy(addresses, NULL /* user_data_destroy */);
grpc_lb_addresses_destroy(addresses);
return NULL;
}
/* Instantiate resolver. */
sockaddr_resolver *r = gpr_malloc(sizeof(sockaddr_resolver));
memset(r, 0, sizeof(*r));
r->target_name = gpr_strdup(args->uri->path);
r->addresses = addresses;
grpc_arg server_name_arg;
server_name_arg.type = GRPC_ARG_STRING;
server_name_arg.key = GRPC_ARG_SERVER_NAME;
server_name_arg.value.string = args->uri->path;
r->channel_args =
grpc_channel_args_copy_and_add(args->args, &server_name_arg, 1);
gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
return &r->base;

@ -52,6 +52,10 @@
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/channel.h"
//
// connector
//
typedef struct {
grpc_connector base;
gpr_refcount refs;
@ -156,35 +160,20 @@ static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
static const grpc_connector_vtable connector_vtable = {
connector_ref, connector_unref, connector_shutdown, connector_connect};
typedef struct {
grpc_client_channel_factory base;
gpr_refcount refs;
grpc_channel_args *merge_args;
} client_channel_factory;
//
// client_channel_factory
//
static void client_channel_factory_ref(
grpc_client_channel_factory *cc_factory) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
gpr_ref(&f->refs);
}
grpc_client_channel_factory *cc_factory) {}
static void client_channel_factory_unref(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
if (gpr_unref(&f->refs)) {
grpc_channel_args_destroy(f->merge_args);
gpr_free(f);
}
}
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {}
static grpc_subchannel *client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
grpc_subchannel_args *args) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
const grpc_subchannel_args *args) {
connector *c = gpr_malloc(sizeof(*c));
grpc_channel_args *final_args =
grpc_channel_args_merge(args->args, f->merge_args);
grpc_subchannel *s;
memset(c, 0, sizeof(*c));
c->base.vtable = &connector_vtable;
gpr_ref_init(&c->refs, 1);
@ -196,23 +185,18 @@ static grpc_subchannel *client_channel_factory_create_subchannel(
grpc_http_connect_handshaker_create(proxy_name, args->server_name));
gpr_free(proxy_name);
}
args->args = final_args;
s = grpc_subchannel_create(exec_ctx, &c->base, args);
grpc_subchannel *s = grpc_subchannel_create(exec_ctx, &c->base, args);
grpc_connector_unref(exec_ctx, &c->base);
grpc_channel_args_destroy(final_args);
return s;
}
static grpc_channel *client_channel_factory_create_channel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
const char *target, grpc_client_channel_type type,
grpc_channel_args *args) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args);
grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args,
GRPC_CLIENT_CHANNEL, NULL);
grpc_channel_args_destroy(final_args);
grpc_resolver *resolver = grpc_resolver_create(target);
const grpc_channel_args *args) {
grpc_channel *channel =
grpc_channel_create(exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL);
grpc_resolver *resolver = grpc_resolver_create(target, args);
if (!resolver) {
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel,
"client_channel_factory_create_channel");
@ -220,7 +204,7 @@ static grpc_channel *client_channel_factory_create_channel(
}
grpc_client_channel_finish_initialization(
exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base);
exec_ctx, grpc_channel_get_channel_stack(channel), resolver, cc_factory);
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create_channel");
return channel;
@ -231,6 +215,9 @@ static const grpc_client_channel_factory_vtable client_channel_factory_vtable =
client_channel_factory_create_subchannel,
client_channel_factory_create_channel};
static grpc_client_channel_factory client_channel_factory = {
&client_channel_factory_vtable};
/* Create a client channel:
Asynchronously: - resolve target
- connect to it (trying alternatives as presented)
@ -244,16 +231,12 @@ grpc_channel *grpc_insecure_channel_create(const char *target,
(target, args, reserved));
GPR_ASSERT(!reserved);
client_channel_factory *f = gpr_malloc(sizeof(*f));
memset(f, 0, sizeof(*f));
f->base.vtable = &client_channel_factory_vtable;
gpr_ref_init(&f->refs, 1);
f->merge_args = grpc_channel_args_copy(args);
grpc_client_channel_factory *factory =
(grpc_client_channel_factory *)&client_channel_factory;
grpc_channel *channel = client_channel_factory_create_channel(
&exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL);
&exec_ctx, factory, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, args);
grpc_client_channel_factory_unref(&exec_ctx, &f->base);
grpc_client_channel_factory_unref(&exec_ctx, factory);
grpc_exec_ctx_finish(&exec_ctx);
return channel != NULL ? channel : grpc_lame_client_channel_create(

@ -54,6 +54,10 @@
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/tsi/transport_security_interface.h"
//
// connector
//
typedef struct {
grpc_connector base;
gpr_refcount refs;
@ -216,10 +220,13 @@ static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
static const grpc_connector_vtable connector_vtable = {
connector_ref, connector_unref, connector_shutdown, connector_connect};
//
// client_channel_factory
//
typedef struct {
grpc_client_channel_factory base;
gpr_refcount refs;
grpc_channel_args *merge_args;
grpc_channel_security_connector *security_connector;
} client_channel_factory;
@ -235,19 +242,15 @@ static void client_channel_factory_unref(
if (gpr_unref(&f->refs)) {
GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
"client_channel_factory");
grpc_channel_args_destroy(f->merge_args);
gpr_free(f);
}
}
static grpc_subchannel *client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
grpc_subchannel_args *args) {
const grpc_subchannel_args *args) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
connector *c = gpr_malloc(sizeof(*c));
grpc_channel_args *final_args =
grpc_channel_args_merge(args->args, f->merge_args);
grpc_subchannel *s;
memset(c, 0, sizeof(*c));
c->base.vtable = &connector_vtable;
c->security_connector = f->security_connector;
@ -261,25 +264,19 @@ static grpc_subchannel *client_channel_factory_create_subchannel(
}
gpr_mu_init(&c->mu);
gpr_ref_init(&c->refs, 1);
args->args = final_args;
s = grpc_subchannel_create(exec_ctx, &c->base, args);
grpc_subchannel *s = grpc_subchannel_create(exec_ctx, &c->base, args);
grpc_connector_unref(exec_ctx, &c->base);
grpc_channel_args_destroy(final_args);
return s;
}
static grpc_channel *client_channel_factory_create_channel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
const char *target, grpc_client_channel_type type,
grpc_channel_args *args) {
const grpc_channel_args *args) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args);
grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args,
GRPC_CLIENT_CHANNEL, NULL);
grpc_channel_args_destroy(final_args);
grpc_resolver *resolver = grpc_resolver_create(target);
grpc_channel *channel =
grpc_channel_create(exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL);
grpc_resolver *resolver = grpc_resolver_create(target, args);
if (resolver != NULL) {
grpc_client_channel_finish_initialization(
exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base);
@ -289,7 +286,6 @@ static grpc_channel *client_channel_factory_create_channel(
"client_channel_factory_create_channel");
channel = NULL;
}
return channel;
}
@ -306,19 +302,13 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
const char *target,
const grpc_channel_args *args,
void *reserved) {
grpc_arg connector_arg;
grpc_channel_args *args_copy;
grpc_channel_args *new_args_from_connector;
grpc_channel_security_connector *security_connector;
client_channel_factory *f;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GRPC_API_TRACE(
"grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
"reserved=%p)",
4, (creds, target, args, reserved));
GPR_ASSERT(reserved == NULL);
// Make sure security connector does not already exist in args.
if (grpc_find_security_connector_in_args(args) != NULL) {
gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
grpc_exec_ctx_finish(&exec_ctx);
@ -326,7 +316,9 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
target, GRPC_STATUS_INTERNAL,
"Security connector exists in channel args.");
}
// Create security connector and construct new channel args.
grpc_channel_security_connector *security_connector;
grpc_channel_args *new_args_from_connector;
if (grpc_channel_credentials_create_security_connector(
creds, target, args, &security_connector, &new_args_from_connector) !=
GRPC_SECURITY_OK) {
@ -334,35 +326,30 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
return grpc_lame_client_channel_create(
target, GRPC_STATUS_INTERNAL, "Failed to create security connector.");
}
connector_arg = grpc_security_connector_to_arg(&security_connector->base);
args_copy = grpc_channel_args_copy_and_add(
grpc_arg connector_arg =
grpc_security_connector_to_arg(&security_connector->base);
grpc_channel_args *new_args = grpc_channel_args_copy_and_add(
new_args_from_connector != NULL ? new_args_from_connector : args,
&connector_arg, 1);
f = gpr_malloc(sizeof(*f));
memset(f, 0, sizeof(*f));
f->base.vtable = &client_channel_factory_vtable;
gpr_ref_init(&f->refs, 1);
f->merge_args = grpc_channel_args_copy(args_copy);
grpc_channel_args_destroy(args_copy);
if (new_args_from_connector != NULL) {
grpc_channel_args_destroy(new_args_from_connector);
}
// Create client channel factory.
client_channel_factory *f = gpr_malloc(sizeof(*f));
memset(f, 0, sizeof(*f));
f->base.vtable = &client_channel_factory_vtable;
gpr_ref_init(&f->refs, 1);
GRPC_SECURITY_CONNECTOR_REF(&security_connector->base,
"grpc_secure_channel_create");
f->security_connector = security_connector;
// Create channel.
grpc_channel *channel = client_channel_factory_create_channel(
&exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL);
&exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args);
// Clean up.
GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
"client_channel_factory_create_channel");
grpc_channel_args_destroy(new_args);
grpc_client_channel_factory_unref(&exec_ctx, &f->base);
grpc_exec_ctx_finish(&exec_ctx);
return channel; /* may be NULL */
}

@ -66,22 +66,59 @@ static grpc_arg copy_arg(const grpc_arg *src) {
grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src,
const grpc_arg *to_add,
size_t num_to_add) {
return grpc_channel_args_copy_and_add_and_remove(src, NULL, 0, to_add,
num_to_add);
}
grpc_channel_args *grpc_channel_args_copy_and_remove(
const grpc_channel_args *src, const char **to_remove,
size_t num_to_remove) {
return grpc_channel_args_copy_and_add_and_remove(src, to_remove,
num_to_remove, NULL, 0);
}
static bool should_remove_arg(const grpc_arg *arg, const char **to_remove,
size_t num_to_remove) {
for (size_t i = 0; i < num_to_remove; ++i) {
if (strcmp(arg->key, to_remove[i]) == 0) return true;
}
return false;
}
grpc_channel_args *grpc_channel_args_copy_and_add_and_remove(
const grpc_channel_args *src, const char **to_remove, size_t num_to_remove,
const grpc_arg *to_add, size_t num_to_add) {
// Figure out how many args we'll be copying.
size_t num_args_to_copy = 0;
if (src != NULL) {
for (size_t i = 0; i < src->num_args; ++i) {
if (!should_remove_arg(&src->args[i], to_remove, num_to_remove)) {
++num_args_to_copy;
}
}
}
// Create result.
grpc_channel_args *dst = gpr_malloc(sizeof(grpc_channel_args));
size_t i;
size_t src_num_args = (src == NULL) ? 0 : src->num_args;
if (!src && !to_add) {
dst->num_args = 0;
dst->num_args = num_args_to_copy + num_to_add;
if (dst->num_args == 0) {
dst->args = NULL;
return dst;
}
dst->num_args = src_num_args + num_to_add;
dst->args = gpr_malloc(sizeof(grpc_arg) * dst->num_args);
for (i = 0; i < src_num_args; i++) {
dst->args[i] = copy_arg(&src->args[i]);
// Copy args from src that are not being removed.
size_t dst_idx = 0;
if (src != NULL) {
for (size_t i = 0; i < src->num_args; ++i) {
if (!should_remove_arg(&src->args[i], to_remove, num_to_remove)) {
dst->args[dst_idx++] = copy_arg(&src->args[i]);
}
}
}
for (i = 0; i < num_to_add; i++) {
dst->args[i + src_num_args] = copy_arg(&to_add[i]);
// Add args from to_add.
for (size_t i = 0; i < num_to_add; ++i) {
dst->args[dst_idx++] = copy_arg(&to_add[i]);
}
GPR_ASSERT(dst_idx == dst->num_args);
return dst;
}

@ -51,6 +51,17 @@ grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src,
const grpc_arg *to_add,
size_t num_to_add);
/** Copies the arguments in \a src except for those whose keys are in
\a to_remove. */
grpc_channel_args *grpc_channel_args_copy_and_remove(
const grpc_channel_args *src, const char **to_remove, size_t num_to_remove);
/** Copies the arguments from \a src except for those whose keys are in
\a to_remove and appends the arguments in \a to_add. */
grpc_channel_args *grpc_channel_args_copy_and_add_and_remove(
const grpc_channel_args *src, const char **to_remove, size_t num_to_remove,
const grpc_arg *to_add, size_t num_to_add);
/** Concatenate args from \a a and \a b into a new instance */
grpc_channel_args *grpc_channel_args_merge(const grpc_channel_args *a,
const grpc_channel_args *b);

@ -38,8 +38,8 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/client_channel/method_config.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/transport/method_config.h"
#define DEFAULT_MAX_SEND_MESSAGE_LENGTH -1 // Unlimited.
// The protobuf library will (by default) start warning at 100 megs.

@ -1711,6 +1711,12 @@ retry:
"pollset_add_fd: Raced creating new polling island. pi_new: %p "
"(fd: %d, pollset: %p)",
(void *)pi_new, fd->fd, (void *)pollset);
/* No need to lock 'pi_new' here since this is a new polling island and
* no one has a reference to it yet */
polling_island_remove_all_fds_locked(pi_new, true, &error);
/* Ref and unref so that the polling island gets deleted during unref */
PI_ADD_REF(pi_new, "dance_of_destruction");
PI_UNREF(exec_ctx, pi_new, "dance_of_destruction");
goto retry;

@ -315,6 +315,9 @@ grpc_endpoint *grpc_tcp_create(uv_tcp_t *handle, char *peer_string) {
gpr_log(GPR_DEBUG, "Creating TCP endpoint %p", tcp);
}
/* Disable Nagle's Algorithm */
uv_tcp_nodelay(handle, 1);
memset(tcp, 0, sizeof(grpc_tcp));
tcp->base.vtable = &vtable;
tcp->handle = handle;

@ -29,7 +29,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#include "src/core/ext/client_channel/method_config.h"
#include "src/core/lib/transport/method_config.h"
#include <string.h>

@ -29,8 +29,8 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_METHOD_CONFIG_H
#define GRPC_CORE_EXT_CLIENT_CHANNEL_METHOD_CONFIG_H
#ifndef GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H
#define GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H
#include <stdbool.h>
@ -133,4 +133,4 @@ grpc_mdstr_hash_table* grpc_method_config_table_convert(
void* (*convert_value)(const grpc_method_config* method_config),
const grpc_mdstr_hash_table_vtable* vtable);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_METHOD_CONFIG_H */
#endif /* GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H */

@ -0,0 +1,291 @@
/*
*
* 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.
*
*/
/**
* Benchmark client module
* @module
*/
'use strict';
var fs = require('fs');
var path = require('path');
var util = require('util');
var EventEmitter = require('events');
var http = require('http');
var https = require('https');
var async = require('async');
var _ = require('lodash');
var PoissonProcess = require('poisson-process');
var Histogram = require('./histogram');
/**
* Convert a time difference, as returned by process.hrtime, to a number of
* nanoseconds.
* @param {Array.<number>} time_diff The time diff, represented as
* [seconds, nanoseconds]
* @return {number} The total number of nanoseconds
*/
function timeDiffToNanos(time_diff) {
return time_diff[0] * 1e9 + time_diff[1];
}
function BenchmarkClient(server_targets, channels, histogram_params,
security_params) {
var options = {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
}
};
var protocol;
if (security_params) {
var ca_path;
protocol = https;
this.request = _.bind(https.request, https);
if (security_params.use_test_ca) {
ca_path = path.join(__dirname, '../test/data/ca.pem');
var ca_data = fs.readFileSync(ca_path);
options.ca = ca_data;
}
if (security_params.server_host_override) {
var host_override = security_params.server_host_override;
options.servername = host_override;
}
} else {
protocol = http;
}
this.request = _.bind(protocol.request, protocol);
this.client_options = [];
for (var i = 0; i < channels; i++) {
var host_port;
host_port = server_targets[i % server_targets.length].split(':')
var new_options = _.assign({hostname: host_port[0], port: +host_port[1]}, options);
new_options.agent = new protocol.Agent(new_options);
this.client_options[i] = new_options;
}
this.histogram = new Histogram(histogram_params.resolution,
histogram_params.max_possible);
this.running = false;
this.pending_calls = 0;
}
util.inherits(BenchmarkClient, EventEmitter);
function startAllClients(client_options_list, outstanding_rpcs_per_channel,
makeCall, emitter) {
_.each(client_options_list, function(client_options) {
_.times(outstanding_rpcs_per_channel, function() {
makeCall(client_options);
});
});
}
BenchmarkClient.prototype.startClosedLoop = function(
outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, generic) {
var self = this;
var options = {};
self.running = true;
if (rpc_type == 'UNARY') {
options.path = '/serviceProto.BenchmarkService.service/unaryCall';
} else {
self.emit('error', new Error('Unsupported rpc_type: ' + rpc_type));
}
if (generic) {
self.emit('error', new Error('Generic client not supported'));
}
self.last_wall_time = process.hrtime();
var argument = {
response_size: resp_size,
payload: {
body: '0'.repeat(req_size)
}
};
function makeCall(client_options) {
if (self.running) {
self.pending_calls++;
var start_time = process.hrtime();
var req = self.request(client_options, function(res) {
var res_data = '';
res.on('data', function(data) {
res_data += data;
});
res.on('end', function() {
JSON.parse(res_data);
var time_diff = process.hrtime(start_time);
self.histogram.add(timeDiffToNanos(time_diff));
makeCall(client_options);
self.pending_calls--;
if ((!self.running) && self.pending_calls == 0) {
self.emit('finished');
}
});
});
req.write(JSON.stringify(argument));
req.end();
req.on('error', function(error) {
self.emit('error', new Error('Client error: ' + error.message));
self.running = false;
});
}
}
startAllClients(_.map(self.client_options, _.partial(_.assign, options)),
outstanding_rpcs_per_channel, makeCall, self);
};
BenchmarkClient.prototype.startPoisson = function(
outstanding_rpcs_per_channel, rpc_type, req_size, resp_size, offered_load,
generic) {
var self = this;
var options = {};
self.running = true;
if (rpc_type == 'UNARY') {
options.path = '/serviceProto.BenchmarkService.service/unaryCall';
} else {
self.emit('error', new Error('Unsupported rpc_type: ' + rpc_type));
}
if (generic) {
self.emit('error', new Error('Generic client not supported'));
}
self.last_wall_time = process.hrtime();
var argument = {
response_size: resp_size,
payload: {
body: '0'.repeat(req_size)
}
};
function makeCall(client_options, poisson) {
if (self.running) {
self.pending_calls++;
var start_time = process.hrtime();
var req = self.request(client_options, function(res) {
var res_data = '';
res.on('data', function(data) {
res_data += data;
});
res.on('end', function() {
JSON.parse(res_data);
var time_diff = process.hrtime(start_time);
self.histogram.add(timeDiffToNanos(time_diff));
self.pending_calls--;
if ((!self.running) && self.pending_calls == 0) {
self.emit('finished');
}
});
});
req.write(JSON.stringify(argument));
req.end();
req.on('error', function(error) {
self.emit('error', new Error('Client error: ' + error.message));
self.running = false;
});
} else {
poisson.stop();
}
}
var averageIntervalMs = (1 / offered_load) * 1000;
startAllClients(_.map(self.client_options, _.partial(_.assign, options)),
outstanding_rpcs_per_channel, function(opts){
var p = PoissonProcess.create(averageIntervalMs, function() {
makeCall(opts, p);
});
p.start();
}, self);
};
/**
* Return curent statistics for the client. If reset is set, restart
* statistic collection.
* @param {boolean} reset Indicates that statistics should be reset
* @return {object} Client statistics
*/
BenchmarkClient.prototype.mark = function(reset) {
var wall_time_diff = process.hrtime(this.last_wall_time);
var histogram = this.histogram;
if (reset) {
this.last_wall_time = process.hrtime();
this.histogram = new Histogram(histogram.resolution,
histogram.max_possible);
}
return {
latencies: {
bucket: histogram.getContents(),
min_seen: histogram.minimum(),
max_seen: histogram.maximum(),
sum: histogram.getSum(),
sum_of_squares: histogram.sumOfSquares(),
count: histogram.getCount()
},
time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9,
// Not sure how to measure these values
time_user: 0,
time_system: 0
};
};
/**
* Stop the clients.
* @param {function} callback Called when the clients have finished shutting
* down
*/
BenchmarkClient.prototype.stop = function(callback) {
this.running = false;
this.on('finished', callback);
};
module.exports = BenchmarkClient;

@ -40,6 +40,8 @@
var fs = require('fs');
var path = require('path');
var EventEmitter = require('events');
var util = require('util');
var genericService = require('./generic_service');
@ -138,12 +140,15 @@ function BenchmarkServer(host, port, tls, generic, response_size) {
this.server = server;
}
util.inherits(BenchmarkServer, EventEmitter);
/**
* Start the benchmark server.
*/
BenchmarkServer.prototype.start = function() {
this.server.start();
this.last_wall_time = process.hrtime();
this.emit('started');
};
/**

@ -0,0 +1,109 @@
/*
*
* Copyright 2016, 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.
*
*/
/**
* Benchmark server module
* @module
*/
'use strict';
var fs = require('fs');
var path = require('path');
var http = require('http');
var https = require('https');
var EventEmitter = require('events');
var util = require('util');
var express = require('express');
var bodyParser = require('body-parser')
function unaryCall(req, res) {
var reqObj = req.body;
var payload = {body: '0'.repeat(reqObj.response_size)};
res.json(payload);
}
function BenchmarkServer(host, port, tls, generic, response_size) {
var app = express();
app.use(bodyParser.json())
app.put('/serviceProto.BenchmarkService.service/unaryCall', unaryCall);
this.input_host = host;
this.input_port = port;
if (tls) {
var credentials = {};
var key_path = path.join(__dirname, '../test/data/server1.key');
var pem_path = path.join(__dirname, '../test/data/server1.pem');
var key_data = fs.readFileSync(key_path);
var pem_data = fs.readFileSync(pem_path);
credentials['key'] = key_data;
credentials['cert'] = pem_data;
this.server = https.createServer(credentials, app);
} else {
this.server = http.createServer(app);
}
}
util.inherits(BenchmarkServer, EventEmitter);
BenchmarkServer.prototype.start = function() {
var self = this;
this.server.listen(this.input_port, this.input_hostname, function() {
self.last_wall_time = process.hrtime();
self.emit('started');
});
};
BenchmarkServer.prototype.getPort = function() {
return this.server.address().port;
};
BenchmarkServer.prototype.mark = function(reset) {
var wall_time_diff = process.hrtime(this.last_wall_time);
if (reset) {
this.last_wall_time = process.hrtime();
}
return {
time_elapsed: wall_time_diff[0] + wall_time_diff[1] / 1e9,
// Not sure how to measure these values
time_user: 0,
time_system: 0
};
};
BenchmarkServer.prototype.stop = function(callback) {
this.server.close(callback);
};
module.exports = BenchmarkServer;

@ -34,18 +34,18 @@
'use strict';
var console = require('console');
var worker_service_impl = require('./worker_service_impl');
var WorkerServiceImpl = require('./worker_service_impl');
var grpc = require('../../../');
var serviceProto = grpc.load({
root: __dirname + '/../../..',
file: 'src/proto/grpc/testing/services.proto'}).grpc.testing;
function runServer(port) {
function runServer(port, benchmark_impl) {
var server_creds = grpc.ServerCredentials.createInsecure();
var server = new grpc.Server();
server.addProtoService(serviceProto.WorkerService.service,
worker_service_impl);
new WorkerServiceImpl(benchmark_impl, server));
var address = '0.0.0.0:' + port;
server.bind(address, server_creds);
server.start();
@ -57,9 +57,9 @@ if (require.main === module) {
Error.stackTraceLimit = Infinity;
var parseArgs = require('minimist');
var argv = parseArgs(process.argv, {
string: ['driver_port']
string: ['driver_port', 'benchmark_impl']
});
runServer(argv.driver_port);
runServer(argv.driver_port, argv.benchmark_impl);
}
exports.runServer = runServer;

@ -38,121 +38,141 @@ var console = require('console');
var BenchmarkClient = require('./benchmark_client');
var BenchmarkServer = require('./benchmark_server');
exports.quitWorker = function quitWorker(call, callback) {
callback(null, {});
process.exit(0);
}
module.exports = function WorkerServiceImpl(benchmark_impl, server) {
var BenchmarkClient;
var BenchmarkServer;
switch (benchmark_impl) {
case 'grpc':
BenchmarkClient = require('./benchmark_client');
BenchmarkServer = require('./benchmark_server');
break;
case 'express':
BenchmarkClient = require('./benchmark_client_express');
BenchmarkServer = require('./benchmark_server_express');
break;
default:
throw new Error('Unrecognized benchmark impl: ' + benchmark_impl);
}
exports.runClient = function runClient(call) {
var client;
call.on('data', function(request) {
var stats;
switch (request.argtype) {
case 'setup':
var setup = request.setup;
console.log('ClientConfig %j', setup);
client = new BenchmarkClient(setup.server_targets,
setup.client_channels,
setup.histogram_params,
setup.security_params);
client.on('error', function(error) {
call.emit('error', error);
});
var req_size, resp_size, generic;
switch (setup.payload_config.payload) {
case 'bytebuf_params':
req_size = setup.payload_config.bytebuf_params.req_size;
resp_size = setup.payload_config.bytebuf_params.resp_size;
generic = true;
this.quitWorker = function quitWorker(call, callback) {
server.tryShutdown(function() {
callback(null, {});
});
};
this.runClient = function runClient(call) {
var client;
call.on('data', function(request) {
var stats;
switch (request.argtype) {
case 'setup':
var setup = request.setup;
console.log('ClientConfig %j', setup);
client = new BenchmarkClient(setup.server_targets,
setup.client_channels,
setup.histogram_params,
setup.security_params);
client.on('error', function(error) {
call.emit('error', error);
});
var req_size, resp_size, generic;
switch (setup.payload_config.payload) {
case 'bytebuf_params':
req_size = setup.payload_config.bytebuf_params.req_size;
resp_size = setup.payload_config.bytebuf_params.resp_size;
generic = true;
break;
case 'simple_params':
req_size = setup.payload_config.simple_params.req_size;
resp_size = setup.payload_config.simple_params.resp_size;
generic = false;
break;
default:
call.emit('error', new Error('Unsupported PayloadConfig type' +
setup.payload_config.payload));
}
switch (setup.load_params.load) {
case 'closed_loop':
client.startClosedLoop(setup.outstanding_rpcs_per_channel,
setup.rpc_type, req_size, resp_size, generic);
break;
case 'poisson':
client.startPoisson(setup.outstanding_rpcs_per_channel,
setup.rpc_type, req_size, resp_size,
setup.load_params.poisson.offered_load, generic);
break;
default:
call.emit('error', new Error('Unsupported LoadParams type' +
setup.load_params.load));
}
stats = client.mark();
call.write({
stats: stats
});
break;
case 'simple_params':
req_size = setup.payload_config.simple_params.req_size;
resp_size = setup.payload_config.simple_params.resp_size;
generic = false;
case 'mark':
if (client) {
stats = client.mark(request.mark.reset);
call.write({
stats: stats
});
} else {
call.emit('error', new Error('Got Mark before ClientConfig'));
}
break;
default:
call.emit('error', new Error('Unsupported PayloadConfig type' +
setup.payload_config.payload));
throw new Error('Nonexistent client argtype option: ' + request.argtype);
}
switch (setup.load_params.load) {
case 'closed_loop':
client.startClosedLoop(setup.outstanding_rpcs_per_channel,
setup.rpc_type, req_size, resp_size, generic);
});
call.on('end', function() {
client.stop(function() {
call.end();
});
});
};
this.runServer = function runServer(call) {
var server;
call.on('data', function(request) {
var stats;
switch (request.argtype) {
case 'setup':
console.log('ServerConfig %j', request.setup);
server = new BenchmarkServer('[::]', request.setup.port,
request.setup.security_params);
server.on('started', function() {
stats = server.mark();
call.write({
stats: stats,
port: server.getPort()
});
});
server.start();
break;
case 'poisson':
client.startPoisson(setup.outstanding_rpcs_per_channel,
setup.rpc_type, req_size, resp_size,
setup.load_params.poisson.offered_load, generic);
case 'mark':
if (server) {
stats = server.mark(request.mark.reset);
call.write({
stats: stats,
port: server.getPort(),
cores: 1
});
} else {
call.emit('error', new Error('Got Mark before ServerConfig'));
}
break;
default:
call.emit('error', new Error('Unsupported LoadParams type' +
setup.load_params.load));
throw new Error('Nonexistent server argtype option');
}
stats = client.mark();
call.write({
stats: stats
});
break;
case 'mark':
if (client) {
stats = client.mark(request.mark.reset);
call.write({
stats: stats
});
} else {
call.emit('error', new Error('Got Mark before ClientConfig'));
}
break;
default:
throw new Error('Nonexistent client argtype option: ' + request.argtype);
}
});
call.on('end', function() {
client.stop(function() {
call.end();
});
});
};
exports.runServer = function runServer(call) {
var server;
call.on('data', function(request) {
var stats;
switch (request.argtype) {
case 'setup':
console.log('ServerConfig %j', request.setup);
server = new BenchmarkServer('[::]', request.setup.port,
request.setup.security_params);
server.start();
stats = server.mark();
call.write({
stats: stats,
port: server.getPort()
call.on('end', function() {
server.stop(function() {
call.end();
});
break;
case 'mark':
if (server) {
stats = server.mark(request.mark.reset);
call.write({
stats: stats,
port: server.getPort(),
cores: 1
});
} else {
call.emit('error', new Error('Got Mark before ServerConfig'));
}
break;
default:
throw new Error('Nonexistent server argtype option');
}
});
call.on('end', function() {
server.stop(function() {
call.end();
});
});
};
};
exports.coreCount = function coreCount(call, callback) {
callback(null, {cores: os.cpus().length});
this.coreCount = function coreCount(call, callback) {
callback(null, {cores: os.cpus().length});
};
};

@ -179,6 +179,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/transport/mdstr_hash_table.c',
'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/method_config.c',
'src/core/lib/transport/static_metadata.c',
'src/core/lib/transport/timeout_encoding.c',
'src/core/lib/transport/transport.c',
@ -245,12 +246,10 @@ CORE_SOURCE_FILES = [
'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',
'src/core/ext/client_channel/method_config.c',
'src/core/ext/client_channel/parse_address.c',
'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/resolver_result.c',
'src/core/ext/client_channel/subchannel.c',
'src/core/ext/client_channel/subchannel_index.c',
'src/core/ext/client_channel/uri_parser.c',

@ -43,7 +43,8 @@ class Struct
GRPC.logger.debug("Failing with status #{status}")
# raise BadStatus, propagating the metadata if present.
md = status.metadata
fail GRPC::BadStatus.new(status.code, status.details, md)
fail GRPC::BadStatus.new(status.code, status.details, md),
"status code: #{status.code}, details: #{status.details}"
end
status
end
@ -156,41 +157,25 @@ module GRPC
Operation.new(self)
end
# writes_done indicates that all writes are completed.
#
# It blocks until the remote endpoint acknowledges with at status unless
# assert_finished is set to false. Any calls to #remote_send after this
# call will fail.
#
# @param assert_finished [true, false] when true(default), waits for
# FINISHED.
def writes_done(assert_finished = true)
ops = {
SEND_CLOSE_FROM_CLIENT => nil
}
ops[RECV_STATUS_ON_CLIENT] = nil if assert_finished
batch_result = @call.run_batch(ops)
return unless assert_finished
unless batch_result.status.nil?
@call.trailing_metadata = batch_result.status.metadata
end
@call.status = batch_result.status
op_is_done
batch_result.check_status
end
# finished waits until a client call is completed.
#
# It blocks until the remote endpoint acknowledges by sending a status.
def finished
batch_result = @call.run_batch(RECV_STATUS_ON_CLIENT => nil)
unless batch_result.status.nil?
@call.trailing_metadata = batch_result.status.metadata
attach_status_results_and_complete_call(batch_result)
end
def attach_status_results_and_complete_call(recv_status_batch_result)
unless recv_status_batch_result.status.nil?
@call.trailing_metadata = recv_status_batch_result.status.metadata
end
@call.status = batch_result.status
op_is_done
batch_result.check_status
@call.status = recv_status_batch_result.status
@call.close
op_is_done
# The RECV_STATUS in run_batch always succeeds
# Check the status for a bad status or failed run batch
recv_status_batch_result.check_status
end
# remote_send sends a request to the remote endpoint.
@ -226,6 +211,23 @@ module GRPC
nil
end
def server_unary_response(req, trailing_metadata: {},
code: Core::StatusCodes::OK, details: 'OK')
ops = {}
@send_initial_md_mutex.synchronize do
ops[SEND_INITIAL_METADATA] = @metadata_to_send unless @metadata_sent
@metadata_sent = true
end
payload = @marshal.call(req)
ops[SEND_MESSAGE] = payload
ops[SEND_STATUS_FROM_SERVER] = Struct::Status.new(
code, details, trailing_metadata)
ops[RECV_CLOSE_ON_SERVER] = nil
@call.run_batch(ops)
end
# remote_read reads a response from the remote endpoint.
#
# It blocks until the remote endpoint replies with a message or status.
@ -240,9 +242,13 @@ module GRPC
@call.metadata = batch_result.metadata
@metadata_received = true
end
unless batch_result.nil? || batch_result.message.nil?
res = @unmarshal.call(batch_result.message)
return res
get_message_from_batch_result(batch_result)
end
def get_message_from_batch_result(recv_message_batch_result)
unless recv_message_batch_result.nil? ||
recv_message_batch_result.message.nil?
return @unmarshal.call(recv_message_batch_result.message)
end
GRPC.logger.debug('found nil; the final response has been sent')
nil
@ -298,7 +304,6 @@ module GRPC
return enum_for(:each_remote_read_then_finish) unless block_given?
loop do
resp = remote_read
break if resp.is_a? Struct::Status # is an OK status
if resp.nil? # the last response was received, but not finished yet
finished
break
@ -315,15 +320,25 @@ module GRPC
# a list, multiple metadata for its key are sent
# @return [Object] the response received from the server
def request_response(req, metadata: {})
merge_metadata_to_send(metadata) && send_initial_metadata
remote_send(req)
writes_done(false)
response = remote_read
finished unless response.is_a? Struct::Status
response
rescue GRPC::Core::CallError => e
finished # checks for Cancelled
raise e
ops = {
SEND_MESSAGE => @marshal.call(req),
SEND_CLOSE_FROM_CLIENT => nil,
RECV_INITIAL_METADATA => nil,
RECV_MESSAGE => nil,
RECV_STATUS_ON_CLIENT => nil
}
@send_initial_md_mutex.synchronize do
# Metadata might have already been sent if this is an operation view
unless @metadata_sent
ops[SEND_INITIAL_METADATA] = @metadata_to_send.merge!(metadata)
end
@metadata_sent = true
end
batch_result = @call.run_batch(ops)
@call.metadata = batch_result.metadata
attach_status_results_and_complete_call(batch_result)
get_message_from_batch_result(batch_result)
end
# client_streamer sends a stream of requests to a GRPC server, and
@ -339,12 +354,20 @@ module GRPC
# a list, multiple metadata for its key are sent
# @return [Object] the response received from the server
def client_streamer(requests, metadata: {})
merge_metadata_to_send(metadata) && send_initial_metadata
requests.each { |r| remote_send(r) }
writes_done(false)
response = remote_read
finished unless response.is_a? Struct::Status
response
# Metadata might have already been sent if this is an operation view
merge_metadata_and_send_if_not_already_sent(metadata)
requests.each { |r| @call.run_batch(SEND_MESSAGE => @marshal.call(r)) }
batch_result = @call.run_batch(
SEND_CLOSE_FROM_CLIENT => nil,
RECV_INITIAL_METADATA => nil,
RECV_MESSAGE => nil,
RECV_STATUS_ON_CLIENT => nil
)
@call.metadata = batch_result.metadata
attach_status_results_and_complete_call(batch_result)
get_message_from_batch_result(batch_result)
rescue GRPC::Core::CallError => e
finished # checks for Cancelled
raise e
@ -365,9 +388,18 @@ module GRPC
# a list, multiple metadata for its key are sent
# @return [Enumerator|nil] a response Enumerator
def server_streamer(req, metadata: {})
merge_metadata_to_send(metadata) && send_initial_metadata
remote_send(req)
writes_done(false)
ops = {
SEND_MESSAGE => @marshal.call(req),
SEND_CLOSE_FROM_CLIENT => nil
}
@send_initial_md_mutex.synchronize do
# Metadata might have already been sent if this is an operation view
unless @metadata_sent
ops[SEND_INITIAL_METADATA] = @metadata_to_send.merge!(metadata)
end
@metadata_sent = true
end
@call.run_batch(ops)
replies = enum_for(:each_remote_read_then_finish)
return replies unless block_given?
replies.each { |r| yield r }
@ -404,7 +436,8 @@ module GRPC
# a list, multiple metadata for its key are sent
# @return [Enumerator, nil] a response Enumerator
def bidi_streamer(requests, metadata: {}, &blk)
merge_metadata_to_send(metadata) && send_initial_metadata
# Metadata might have already been sent if this is an operation view
merge_metadata_and_send_if_not_already_sent(metadata)
bd = BidiCall.new(@call,
@marshal,
@unmarshal,
@ -457,6 +490,15 @@ module GRPC
end
end
def merge_metadata_and_send_if_not_already_sent(new_metadata = {})
@send_initial_md_mutex.synchronize do
return if @metadata_sent
@metadata_to_send.merge!(new_metadata)
@call.run_batch(SEND_INITIAL_METADATA => @metadata_to_send)
@metadata_sent = true
end
end
private
# Starts the call if not already started

@ -168,6 +168,7 @@ module GRPC
# return the operation view of the active_call; define #execute as a
# new method for this instance that invokes #request_response.
c.merge_metadata_to_send(metadata)
op = c.operation
op.define_singleton_method(:execute) do
c.request_response(req, metadata: metadata)
@ -231,9 +232,10 @@ module GRPC
# return the operation view of the active_call; define #execute as a
# new method for this instance that invokes #client_streamer.
c.merge_metadata_to_send(metadata)
op = c.operation
op.define_singleton_method(:execute) do
c.client_streamer(requests, metadata: metadata)
c.client_streamer(requests)
end
op
end
@ -309,9 +311,10 @@ module GRPC
# return the operation view of the active_call; define #execute
# as a new method for this instance that invokes #server_streamer
c.merge_metadata_to_send(metadata)
op = c.operation
op.define_singleton_method(:execute) do
c.server_streamer(req, metadata: metadata, &blk)
c.server_streamer(req, &blk)
end
op
end
@ -417,15 +420,15 @@ module GRPC
deadline: deadline,
parent: parent,
credentials: credentials)
return c.bidi_streamer(requests, metadata: metadata,
&blk) unless return_op
# return the operation view of the active_call; define #execute
# as a new method for this instance that invokes #bidi_streamer
c.merge_metadata_to_send(metadata)
op = c.operation
op.define_singleton_method(:execute) do
c.bidi_streamer(requests, metadata: metadata, &blk)
c.bidi_streamer(requests, &blk)
end
op
end
@ -445,7 +448,6 @@ module GRPC
deadline: nil,
parent: nil,
credentials: nil)
deadline = from_relative_time(@timeout) if deadline.nil?
# Provide each new client call with its own completion queue
call = @ch.create_call(parent, # parent call

@ -62,25 +62,44 @@ module GRPC
proc { |o| unmarshal_class.method(unmarshal_method).call(o) }
end
def handle_request_response(active_call, mth)
req = active_call.remote_read
resp = mth.call(req, active_call.single_req_view)
active_call.server_unary_response(
resp, trailing_metadata: active_call.output_metadata)
end
def handle_client_streamer(active_call, mth)
resp = mth.call(active_call.multi_req_view)
active_call.server_unary_response(
resp, trailing_metadata: active_call.output_metadata)
end
def handle_server_streamer(active_call, mth)
req = active_call.remote_read
replys = mth.call(req, active_call.single_req_view)
replys.each { |r| active_call.remote_send(r) }
send_status(active_call, OK, 'OK', active_call.output_metadata)
end
def handle_bidi_streamer(active_call, mth)
active_call.run_server_bidi(mth)
send_status(active_call, OK, 'OK', active_call.output_metadata)
end
def run_server_method(active_call, mth)
# While a server method is running, it might be cancelled, its deadline
# might be reached, the handler could throw an unknown error, or a
# well-behaved handler could throw a StatusError.
if request_response?
req = active_call.remote_read
resp = mth.call(req, active_call.single_req_view)
active_call.remote_send(resp)
handle_request_response(active_call, mth)
elsif client_streamer?
resp = mth.call(active_call.multi_req_view)
active_call.remote_send(resp)
handle_client_streamer(active_call, mth)
elsif server_streamer?
req = active_call.remote_read
replys = mth.call(req, active_call.single_req_view)
replys.each { |r| active_call.remote_send(r) }
handle_server_streamer(active_call, mth)
else # is a bidi_stream
active_call.run_server_bidi(mth)
handle_bidi_streamer(active_call, mth)
end
send_status(active_call, OK, 'OK', active_call.output_metadata)
rescue BadStatus => e
# this is raised by handlers that want GRPC to send an application error
# code and detail message and some additional app-specific metadata.
@ -91,7 +110,7 @@ module GRPC
# Log it, but don't notify the other endpoint..
GRPC.logger.warn("failed call: #{active_call}\n#{e}")
rescue Core::OutOfTime
# This is raised when active_call#method.call exceeeds the deadline
# This is raised when active_call#method.call exceeds the deadline
# event. Send a status of deadline exceeded
GRPC.logger.warn("late call: #{active_call}")
send_status(active_call, DEADLINE_EXCEEDED, 'late')
@ -100,7 +119,7 @@ module GRPC
# Send back a UNKNOWN status to the client
GRPC.logger.warn("failed handler: #{active_call}; sending status:UNKNOWN")
GRPC.logger.warn(e)
send_status(active_call, UNKNOWN, 'no reason given')
send_status(active_call, UNKNOWN, 'unkown error handling call on server')
end
def assert_arity_matches(mth)

@ -402,7 +402,7 @@ describe GRPC::ActiveCall do
@pass_through, deadline)
msg = 'message is a string'
client_call.remote_send(msg)
client_call.writes_done(false)
call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil)
server_call = expect_server_to_receive(msg)
server_call.remote_send('server_response')
server_call.send_status(OK, 'OK')
@ -460,7 +460,7 @@ describe GRPC::ActiveCall do
msg = 'message is a string'
reply = 'server_response'
client_call.remote_send(msg)
client_call.writes_done(false)
call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil)
server_call = expect_server_to_receive(msg)
e = client_call.each_remote_read
n = 3 # arbitrary value > 1
@ -473,7 +473,7 @@ describe GRPC::ActiveCall do
end
end
describe '#writes_done' do
describe '#closing the call from the client' do
it 'finishes ok if the server sends a status response' do
call = make_test_call
ActiveCall.client_invoke(call)
@ -481,7 +481,9 @@ describe GRPC::ActiveCall do
@pass_through, deadline)
msg = 'message is a string'
client_call.remote_send(msg)
expect { client_call.writes_done(false) }.to_not raise_error
expect do
call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil)
end.to_not raise_error
server_call = expect_server_to_receive(msg)
server_call.remote_send('server_response')
expect(client_call.remote_read).to eq('server_response')
@ -500,11 +502,13 @@ describe GRPC::ActiveCall do
server_call.remote_send('server_response')
server_call.send_status(OK, 'status code is OK')
expect(client_call.remote_read).to eq('server_response')
expect { client_call.writes_done(false) }.to_not raise_error
expect do
call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil)
end.to_not raise_error
expect { client_call.finished }.to_not raise_error
end
it 'finishes ok if writes_done is true' do
it 'finishes ok if SEND_CLOSE and RECV_STATUS has been sent' do
call = make_test_call
ActiveCall.client_invoke(call)
client_call = ActiveCall.new(call, @pass_through,
@ -515,7 +519,11 @@ describe GRPC::ActiveCall do
server_call.remote_send('server_response')
server_call.send_status(OK, 'status code is OK')
expect(client_call.remote_read).to eq('server_response')
expect { client_call.writes_done(true) }.to_not raise_error
expect do
call.run_batch(
CallOps::SEND_CLOSE_FROM_CLIENT => nil,
CallOps::RECV_STATUS_ON_CLIENT => nil)
end.to_not raise_error
end
end

@ -180,30 +180,44 @@ describe 'ClientStub' do
end
describe 'via a call operation' do
def get_response(stub)
def get_response(stub, run_start_call_first: false)
op = stub.request_response(@method, @sent_msg, noop, noop,
return_op: true,
metadata: { k1: 'v1', k2: 'v2' },
deadline: from_relative_time(2))
expect(op).to be_a(GRPC::ActiveCall::Operation)
op.execute
op.start_call if run_start_call_first
result = op.execute
op.wait # make sure wait doesn't hang
result
end
it_behaves_like 'request response'
end
end
describe '#client_streamer' do
shared_examples 'client streaming' do
before(:each) do
it 'sends metadata to the server ok when running start_call first' do
server_port = create_test_server
host = "localhost:#{server_port}"
@stub = GRPC::ClientStub.new(host, :this_channel_is_insecure)
@metadata = { k1: 'v1', k2: 'v2' }
@sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
@resp = 'a_reply'
th = run_request_response(@sent_msg, @resp, @pass,
k1: 'v1', k2: 'v2')
stub = GRPC::ClientStub.new(host, :this_channel_is_insecure)
expect(get_response(stub)).to eq(@resp)
th.join
end
end
end
describe '#client_streamer' do
before(:each) do
Thread.abort_on_exception = true
server_port = create_test_server
host = "localhost:#{server_port}"
@stub = GRPC::ClientStub.new(host, :this_channel_is_insecure)
@metadata = { k1: 'v1', k2: 'v2' }
@sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
@resp = 'a_reply'
end
shared_examples 'client streaming' do
it 'should send requests to/receive a reply from a server' do
th = run_client_streamer(@sent_msgs, @resp, @pass)
expect(get_response(@stub)).to eq(@resp)
@ -242,24 +256,33 @@ describe 'ClientStub' do
end
describe 'via a call operation' do
def get_response(stub)
def get_response(stub, run_start_call_first: false)
op = stub.client_streamer(@method, @sent_msgs, noop, noop,
return_op: true, metadata: @metadata)
expect(op).to be_a(GRPC::ActiveCall::Operation)
op.execute
op.start_call if run_start_call_first
result = op.execute
op.wait # make sure wait doesn't hang
result
end
it_behaves_like 'client streaming'
it 'sends metadata to the server ok when running start_call first' do
th = run_client_streamer(@sent_msgs, @resp, @pass, **@metadata)
expect(get_response(@stub, run_start_call_first: true)).to eq(@resp)
th.join
end
end
end
describe '#server_streamer' do
shared_examples 'server streaming' do
before(:each) do
@sent_msg = 'a_msg'
@replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s }
end
before(:each) do
@sent_msg = 'a_msg'
@replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s }
end
shared_examples 'server streaming' do
it 'should send a request to/receive replies from a server' do
server_port = create_test_server
host = "localhost:#{server_port}"
@ -303,29 +326,44 @@ describe 'ClientStub' do
end
describe 'via a call operation' do
def get_responses(stub)
op = stub.server_streamer(@method, @sent_msg, noop, noop,
return_op: true,
metadata: { k1: 'v1', k2: 'v2' })
expect(op).to be_a(GRPC::ActiveCall::Operation)
e = op.execute
after(:each) do
@op.wait # make sure wait doesn't hang
end
def get_responses(stub, run_start_call_first: false)
@op = stub.server_streamer(@method, @sent_msg, noop, noop,
return_op: true,
metadata: { k1: 'v1', k2: 'v2' })
expect(@op).to be_a(GRPC::ActiveCall::Operation)
@op.start_call if run_start_call_first
e = @op.execute
expect(e).to be_a(Enumerator)
e
end
it_behaves_like 'server streaming'
it 'should send metadata to the server ok when start_call is run first' do
server_port = create_test_server
host = "localhost:#{server_port}"
th = run_server_streamer(@sent_msg, @replys, @fail,
k1: 'v1', k2: 'v2')
stub = GRPC::ClientStub.new(host, :this_channel_is_insecure)
e = get_responses(stub, run_start_call_first: true)
expect { e.collect { |r| r } }.to raise_error(GRPC::BadStatus)
th.join
end
end
end
describe '#bidi_streamer' do
shared_examples 'bidi streaming' do
before(:each) do
@sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
@replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s }
server_port = create_test_server
@host = "localhost:#{server_port}"
end
before(:each) do
@sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
@replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s }
server_port = create_test_server
@host = "localhost:#{server_port}"
end
shared_examples 'bidi streaming' do
it 'supports sending all the requests first', bidi: true do
th = run_bidi_streamer_handle_inputs_first(@sent_msgs, @replys,
@pass)
@ -363,16 +401,29 @@ describe 'ClientStub' do
end
describe 'via a call operation' do
def get_responses(stub)
op = stub.bidi_streamer(@method, @sent_msgs, noop, noop,
return_op: true)
expect(op).to be_a(GRPC::ActiveCall::Operation)
e = op.execute
after(:each) do
@op.wait # make sure wait doesn't hang
end
def get_responses(stub, run_start_call_first: false)
@op = stub.bidi_streamer(@method, @sent_msgs, noop, noop,
return_op: true)
expect(@op).to be_a(GRPC::ActiveCall::Operation)
@op.start_call if run_start_call_first
e = @op.execute
expect(e).to be_a(Enumerator)
e
end
it_behaves_like 'bidi streaming'
it 'can run start_call before executing the call' do
th = run_bidi_streamer_handle_inputs_first(@sent_msgs, @replys,
@pass)
stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure)
e = get_responses(stub, run_start_call_first: true)
expect(e.collect { |r| r }).to eq(@replys)
th.join
end
end
end

@ -48,7 +48,7 @@ describe GRPC::RpcDesc do
@bidi_streamer = RpcDesc.new('ss', Stream.new(Object.new),
Stream.new(Object.new), 'encode', 'decode')
@bs_code = INTERNAL
@no_reason = 'no reason given'
@no_reason = 'unkown error handling call on server'
@ok_response = Object.new
end
@ -83,6 +83,7 @@ describe GRPC::RpcDesc do
before(:each) do
@call = double('active_call')
allow(@call).to receive(:single_req_view).and_return(@call)
allow(@call).to receive(:output_metadata).and_return(@call)
end
it_behaves_like 'it handles errors'
@ -90,10 +91,10 @@ describe GRPC::RpcDesc do
it 'sends a response and closes the stream if there no errors' do
req = Object.new
expect(@call).to receive(:remote_read).once.and_return(req)
expect(@call).to receive(:remote_send).once.with(@ok_response)
expect(@call).to receive(:output_metadata).and_return(fake_md)
expect(@call).to receive(:send_status).once.with(OK, 'OK', true,
metadata: fake_md)
expect(@call).to receive(:output_metadata).once.and_return(fake_md)
expect(@call).to receive(:server_unary_response).once
.with(@ok_response, trailing_metadata: fake_md)
this_desc.run_server_method(@call, method(:fake_reqresp))
end
end
@ -117,7 +118,9 @@ describe GRPC::RpcDesc do
end
it 'absorbs CallError with no further action' do
expect(@call).to receive(:remote_send).once.and_raise(CallError)
expect(@call).to receive(:server_unary_response).once.and_raise(
CallError)
allow(@call).to receive(:output_metadata).and_return({})
blk = proc do
@client_streamer.run_server_method(@call, method(:fake_clstream))
end
@ -125,10 +128,11 @@ describe GRPC::RpcDesc do
end
it 'sends a response and closes the stream if there no errors' do
expect(@call).to receive(:remote_send).once.with(@ok_response)
expect(@call).to receive(:output_metadata).and_return(fake_md)
expect(@call).to receive(:send_status).once.with(OK, 'OK', true,
metadata: fake_md)
expect(@call).to receive(:output_metadata).and_return(
fake_md)
expect(@call).to receive(:server_unary_response).once
.with(@ok_response, trailing_metadata: fake_md)
@client_streamer.run_server_method(@call, method(:fake_clstream))
end
end

@ -462,6 +462,7 @@ describe GRPC::RpcServer do
'connect_k1' => 'connect_v1'
}
wanted_md.each do |key, value|
puts "key: #{key}"
expect(op.metadata[key]).to eq(value)
end
@srv.stop

@ -97,15 +97,17 @@ describe Grpc::Health::Checker do
context 'initialization' do
it 'can be constructed with no args' do
expect(subject).to_not be(nil)
checker = Grpc::Health::Checker.new
expect(checker).to_not be(nil)
end
end
context 'method `add_status` and `check`' do
success_tests.each do |t|
it "should succeed when #{t[:desc]}" do
subject.add_status(t[:service], ServingStatus::NOT_SERVING)
got = subject.check(HCReq.new(service: t[:service]), nil)
checker = Grpc::Health::Checker.new
checker.add_status(t[:service], ServingStatus::NOT_SERVING)
got = checker.check(HCReq.new(service: t[:service]), nil)
want = HCResp.new(status: ServingStatus::NOT_SERVING)
expect(got).to eq(want)
end
@ -115,8 +117,9 @@ describe Grpc::Health::Checker do
context 'method `check`' do
success_tests.each do |t|
it "should fail with NOT_FOUND when #{t[:desc]}" do
checker = Grpc::Health::Checker.new
blk = proc do
subject.check(HCReq.new(service: t[:service]), nil)
checker.check(HCReq.new(service: t[:service]), nil)
end
expected_msg = /#{StatusCodes::NOT_FOUND}/
expect(&blk).to raise_error GRPC::BadStatus, expected_msg
@ -127,14 +130,15 @@ describe Grpc::Health::Checker do
context 'method `clear_status`' do
success_tests.each do |t|
it "should fail after clearing status when #{t[:desc]}" do
subject.add_status(t[:service], ServingStatus::NOT_SERVING)
got = subject.check(HCReq.new(service: t[:service]), nil)
checker = Grpc::Health::Checker.new
checker.add_status(t[:service], ServingStatus::NOT_SERVING)
got = checker.check(HCReq.new(service: t[:service]), nil)
want = HCResp.new(status: ServingStatus::NOT_SERVING)
expect(got).to eq(want)
subject.clear_status(t[:service])
checker.clear_status(t[:service])
blk = proc do
subject.check(HCReq.new(service: t[:service]), nil)
checker.check(HCReq.new(service: t[:service]), nil)
end
expected_msg = /#{StatusCodes::NOT_FOUND}/
expect(&blk).to raise_error GRPC::BadStatus, expected_msg
@ -144,18 +148,19 @@ describe Grpc::Health::Checker do
context 'method `clear_all`' do
it 'should return NOT_FOUND after being invoked' do
checker = Grpc::Health::Checker.new
success_tests.each do |t|
subject.add_status(t[:service], ServingStatus::NOT_SERVING)
got = subject.check(HCReq.new(service: t[:service]), nil)
checker.add_status(t[:service], ServingStatus::NOT_SERVING)
got = checker.check(HCReq.new(service: t[:service]), nil)
want = HCResp.new(status: ServingStatus::NOT_SERVING)
expect(got).to eq(want)
end
subject.clear_all
checker.clear_all
success_tests.each do |t|
blk = proc do
subject.check(HCReq.new(service: t[:service]), nil)
checker.check(HCReq.new(service: t[:service]), nil)
end
expected_msg = /#{StatusCodes::NOT_FOUND}/
expect(&blk).to raise_error GRPC::BadStatus, expected_msg
@ -184,8 +189,10 @@ describe Grpc::Health::Checker do
end
it 'should receive the correct status', server: true do
@srv.handle(subject)
subject.add_status('', ServingStatus::NOT_SERVING)
Thread.abort_on_exception = true
checker = Grpc::Health::Checker.new
@srv.handle(checker)
checker.add_status('', ServingStatus::NOT_SERVING)
t = Thread.new { @srv.run }
@srv.wait_till_running
@ -198,7 +205,8 @@ describe Grpc::Health::Checker do
end
it 'should fail on unknown services', server: true do
@srv.handle(subject)
checker = Grpc::Health::Checker.new
@srv.handle(checker)
t = Thread.new { @srv.run }
@srv.wait_till_running
blk = proc do

@ -36,6 +36,8 @@
},
"devDependencies": {
"async": "^1.5.0",
"body-parser": "^1.15.2",
"express": "^4.14.0",
"google-auth-library": "^0.9.2",
"google-protobuf": "^3.0.0",
"istanbul": "^0.3.21",

@ -37,6 +37,7 @@
#include <grpc/support/alloc.h>
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h"
#include "test/core/util/test_config.h"
@ -103,7 +104,7 @@ int main(int argc, char **argv) {
grpc_resolver *resolver = create_resolver("dns:test");
grpc_resolver_result *result = (grpc_resolver_result *)1;
grpc_channel_args *result = (grpc_channel_args *)1;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
gpr_event ev1;
@ -122,7 +123,7 @@ int main(int argc, char **argv) {
GPR_ASSERT(wait_loop(30, &ev2));
GPR_ASSERT(result != NULL);
grpc_resolver_result_unref(&exec_ctx, result);
grpc_channel_args_destroy(result);
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test");
grpc_exec_ctx_finish(&exec_ctx);

@ -38,21 +38,23 @@
#include <grpc/support/string_util.h>
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/ext/client_channel/resolver_result.h"
#include "src/core/lib/channel/channel_args.h"
#include "test/core/util/test_config.h"
typedef struct on_resolution_arg {
char *expected_server_name;
grpc_resolver_result *resolver_result;
grpc_channel_args *resolver_result;
} on_resolution_arg;
void on_resolution_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
on_resolution_arg *res = arg;
const char *server_name =
grpc_resolver_result_get_server_name(res->resolver_result);
GPR_ASSERT(strcmp(res->expected_server_name, server_name) == 0);
grpc_resolver_result_unref(exec_ctx, res->resolver_result);
const grpc_arg *channel_arg =
grpc_channel_args_find(res->resolver_result, GRPC_ARG_SERVER_NAME);
GPR_ASSERT(channel_arg != NULL);
GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
GPR_ASSERT(strcmp(res->expected_server_name, channel_arg->value.string) == 0);
grpc_channel_args_destroy(res->resolver_result);
}
static void test_succeeds(grpc_resolver_factory *factory, const char *string) {

@ -42,13 +42,14 @@
#include <grpc/support/port_platform.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/client_channel/method_config.h"
#include "src/core/ext/client_channel/lb_policy_factory.h"
#include "src/core/ext/client_channel/parse_address.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/method_config.h"
//
// fake_resolver
@ -59,7 +60,7 @@ typedef struct {
grpc_resolver base;
// passed-in parameters
char* target_name; // the path component of the uri passed in
grpc_channel_args* channel_args;
grpc_lb_addresses* addresses;
char* lb_policy_name;
grpc_method_config_table* method_config_table;
@ -71,14 +72,14 @@ typedef struct {
// pending next completion, or NULL
grpc_closure* next_completion;
// target result address for next completion
grpc_resolver_result** target_result;
grpc_channel_args** target_result;
} fake_resolver;
static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) {
fake_resolver* r = (fake_resolver*)gr;
gpr_mu_destroy(&r->mu);
gpr_free(r->target_name);
grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */);
grpc_channel_args_destroy(r->channel_args);
grpc_lb_addresses_destroy(r->addresses);
gpr_free(r->lb_policy_name);
grpc_method_config_table_unref(r->method_config_table);
gpr_free(r);
@ -100,16 +101,21 @@ static void fake_resolver_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx,
fake_resolver* r) {
if (r->next_completion != NULL && !r->published) {
r->published = true;
grpc_channel_args* lb_policy_args = NULL;
grpc_arg new_args[3];
size_t num_args = 0;
new_args[num_args++] = grpc_lb_addresses_create_channel_arg(r->addresses);
if (r->method_config_table != NULL) {
const grpc_arg arg =
new_args[num_args++] =
grpc_method_config_table_create_channel_arg(r->method_config_table);
lb_policy_args = grpc_channel_args_copy_and_add(NULL /* src */, &arg, 1);
}
*r->target_result = grpc_resolver_result_create(
r->target_name,
grpc_lb_addresses_copy(r->addresses, NULL /* user_data_copy */),
r->lb_policy_name, lb_policy_args);
if (r->lb_policy_name != NULL) {
new_args[num_args].type = GRPC_ARG_STRING;
new_args[num_args].key = GRPC_ARG_LB_POLICY_NAME;
new_args[num_args].value.string = r->lb_policy_name;
++num_args;
}
*r->target_result =
grpc_channel_args_copy_and_add(r->channel_args, new_args, num_args);
grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
r->next_completion = NULL;
}
@ -125,7 +131,7 @@ static void fake_resolver_channel_saw_error(grpc_exec_ctx* exec_ctx,
}
static void fake_resolver_next(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver,
grpc_resolver_result** target_result,
grpc_channel_args** target_result,
grpc_closure* on_complete) {
fake_resolver* r = (fake_resolver*)resolver;
gpr_mu_lock(&r->mu);
@ -168,7 +174,8 @@ static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory,
gpr_slice_buffer path_parts;
gpr_slice_buffer_init(&path_parts);
gpr_slice_split(path_slice, ",", &path_parts);
grpc_lb_addresses* addresses = grpc_lb_addresses_create(path_parts.count);
grpc_lb_addresses* addresses =
grpc_lb_addresses_create(path_parts.count, NULL /* user_data_vtable */);
bool errors_found = false;
for (size_t i = 0; i < addresses->num_addresses; i++) {
grpc_uri ith_uri = *args->uri;
@ -184,7 +191,7 @@ static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory,
gpr_slice_buffer_destroy(&path_parts);
gpr_slice_unref(path_slice);
if (errors_found) {
grpc_lb_addresses_destroy(addresses, NULL /* user_data_destroy */);
grpc_lb_addresses_destroy(addresses);
return NULL;
}
// Construct method config table.
@ -229,7 +236,12 @@ static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory,
// Instantiate resolver.
fake_resolver* r = gpr_malloc(sizeof(fake_resolver));
memset(r, 0, sizeof(*r));
r->target_name = gpr_strdup(args->uri->path);
grpc_arg server_name_arg;
server_name_arg.type = GRPC_ARG_STRING;
server_name_arg.key = GRPC_ARG_SERVER_NAME;
server_name_arg.value.string = args->uri->path;
r->channel_args =
grpc_channel_args_copy_and_add(args->args, &server_name_arg, 1);
r->addresses = addresses;
r->lb_policy_name =
gpr_strdup(grpc_uri_get_query_arg(args->uri, "lb_policy"));

@ -185,7 +185,7 @@ static void test_receive(int number_of_clients) {
/* Create a socket, send a packet to the UDP server. */
clifd = socket(addr->ss_family, SOCK_DGRAM, 0);
GPR_ASSERT(clifd >= 0);
GPR_ASSERT(connect(clifd, (struct sockaddr *)&addr,
GPR_ASSERT(connect(clifd, (struct sockaddr *)addr,
(socklen_t)resolved_addr.len) == 0);
GPR_ASSERT(5 == write(clifd, "hello", 5));
while (g_number_of_reads == number_of_reads_before &&

@ -636,7 +636,7 @@ TEST_P(End2endTest, SimpleRpcWithCustomeUserAgentPrefix) {
auto iter = trailing_metadata.find("user-agent");
EXPECT_TRUE(iter != trailing_metadata.end());
grpc::string expected_prefix = user_agent_prefix_ + " grpc-c++/";
EXPECT_TRUE(iter->second.starts_with(expected_prefix));
EXPECT_TRUE(iter->second.starts_with(expected_prefix)) << iter->second;
}
TEST_P(End2endTest, MultipleRpcsWithVariedBinaryMetadataValue) {

@ -67,6 +67,7 @@ environment.update({
'LDFLAGS': '-L{}'.format(LIBRARY_PATH),
'LD_LIBRARY_PATH': LIBRARY_PATH,
'GRPC_PYTHON_BUILD_WITH_CYTHON': '1',
'GRPC_PYTHON_ENABLE_DOCUMENTATION_BUILD': '1',
})
subprocess_arguments_list = [

@ -873,6 +873,7 @@ src/core/lib/transport/connectivity_state.h \
src/core/lib/transport/mdstr_hash_table.h \
src/core/lib/transport/metadata.h \
src/core/lib/transport/metadata_batch.h \
src/core/lib/transport/method_config.h \
src/core/lib/transport/static_metadata.h \
src/core/lib/transport/timeout_encoding.h \
src/core/lib/transport/transport.h \
@ -930,12 +931,10 @@ 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 \
src/core/ext/client_channel/method_config.h \
src/core/ext/client_channel/parse_address.h \
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/resolver_result.h \
src/core/ext/client_channel/subchannel.h \
src/core/ext/client_channel/subchannel_index.h \
src/core/ext/client_channel/uri_parser.h \
@ -1061,6 +1060,7 @@ src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \
@ -1127,12 +1127,10 @@ 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 \
src/core/ext/client_channel/method_config.c \
src/core/ext/client_channel/parse_address.c \
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/resolver_result.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \

@ -39,6 +39,14 @@ cd $(dirname $0)/../..
PLATFORM=`uname -s`
function is_msys() {
if [ "${PLATFORM/MSYS}" != "$PLATFORM" ]; then
echo true
else
exit 1
fi
}
function is_mingw() {
if [ "${PLATFORM/MINGW}" != "$PLATFORM" ]; then
echo true
@ -108,6 +116,12 @@ VENV=${2:-$(venv $PYTHON)}
VENV_RELATIVE_PYTHON=${3:-$(venv_relative_python)}
TOOLCHAIN=${4:-$(toolchain)}
if [ $(is_msys) ]; then
echo "MSYS doesn't directly provide the right compiler(s);"
echo "switch to a MinGW shell."
exit 1
fi
ROOT=`pwd`
export CFLAGS="-I$ROOT/include -std=gnu99 -fno-wrapv $CFLAGS"
export GRPC_PYTHON_BUILD_WITH_CYTHON=1

@ -229,6 +229,15 @@ class CXXLanguage:
secure=secure,
categories=smoketest_categories + [SCALABLE])
yield _ping_pong_scenario(
'cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_%s' % secstr,
rpc_type='STREAMING',
client_type='ASYNC_CLIENT',
server_type='SYNC_SERVER',
unconstrained_client='async',
secure=secure,
categories=smoketest_categories+[SCALABLE])
for rpc_type in ['unary', 'streaming']:
for synchronicity in ['sync', 'async']:
yield _ping_pong_scenario(
@ -348,7 +357,8 @@ class NodeLanguage:
self.safename = str(self)
def worker_cmdline(self):
return ['tools/run_tests/performance/run_worker_node.sh']
return ['tools/run_tests/performance/run_worker_node.sh',
'--benchmark_impl=grpc']
def worker_port_offset(self):
return 200
@ -651,11 +661,69 @@ class GoLanguage:
def __str__(self):
return 'go'
class NodeExpressLanguage:
def __init__(self):
pass
self.safename = str(self)
def worker_cmdline(self):
return ['tools/run_tests/performance/run_worker_node.sh',
'--benchmark_impl=express']
def worker_port_offset(self):
return 700
def scenarios(self):
# TODO(jtattermusch): make this scenario work
#yield _ping_pong_scenario(
# 'node_generic_async_streaming_ping_pong', rpc_type='STREAMING',
# client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
# use_generic_payload=True)
# TODO(jtattermusch): make this scenario work
#yield _ping_pong_scenario(
# 'node_protobuf_async_streaming_ping_pong', rpc_type='STREAMING',
# client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER')
yield _ping_pong_scenario(
'node_protobuf_unary_ping_pong', rpc_type='UNARY',
client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
categories=[SCALABLE, SMOKETEST])
yield _ping_pong_scenario(
'node_protobuf_async_unary_qps_unconstrained', rpc_type='UNARY',
client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
unconstrained_client='async',
categories=[SCALABLE, SMOKETEST])
# TODO(jtattermusch): make this scenario work
#yield _ping_pong_scenario(
# 'node_protobuf_async_streaming_qps_unconstrained', rpc_type='STREAMING',
# client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
# unconstrained_client='async')
# TODO(jtattermusch): make this scenario work
#yield _ping_pong_scenario(
# 'node_to_cpp_protobuf_async_unary_ping_pong', rpc_type='UNARY',
# client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
# server_language='c++', server_core_limit=1, async_server_threads=1)
# TODO(jtattermusch): make this scenario work
#yield _ping_pong_scenario(
# 'node_to_cpp_protobuf_async_streaming_ping_pong', rpc_type='STREAMING',
# client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
# server_language='c++', server_core_limit=1, async_server_threads=1)
def __str__(self):
return 'node_express'
LANGUAGES = {
'c++' : CXXLanguage(),
'csharp' : CSharpLanguage(),
'node' : NodeLanguage(),
'node_express': NodeExpressLanguage(),
'ruby' : RubyLanguage(),
'java' : JavaLanguage(),
'python' : PythonLanguage(),

@ -842,6 +842,53 @@ class Sanity(object):
def __str__(self):
return 'sanity'
class NodeExpressLanguage(object):
"""Dummy Node express test target to enable running express performance
benchmarks"""
def __init__(self):
self.platform = platform_string()
def configure(self, config, args):
self.config = config
self.args = args
_check_compiler(self.args.compiler, ['default', 'node0.12',
'node4', 'node5', 'node6'])
if self.args.compiler == 'default':
self.node_version = '4'
else:
# Take off the word "node"
self.node_version = self.args.compiler[4:]
def test_specs(self):
return []
def pre_build_steps(self):
if self.platform == 'windows':
return [['tools\\run_tests\\pre_build_node.bat']]
else:
return [['tools/run_tests/pre_build_node.sh', self.node_version]]
def make_targets(self):
return []
def make_options(self):
return []
def build_steps(self):
return []
def post_tests_steps(self):
return []
def makefile_name(self):
return 'Makefile'
def dockerfile_dir(self):
return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(self.args.arch)
def __str__(self):
return 'node_express'
# different configurations we can run under
with open('tools/run_tests/configs.json') as f:
@ -852,6 +899,7 @@ _LANGUAGES = {
'c++': CLanguage('cxx', 'c++'),
'c': CLanguage('c', 'c'),
'node': NodeLanguage(),
'node_express': NodeExpressLanguage(),
'php': PhpLanguage(),
'php7': Php7Language(),
'python': PythonLanguage(),

@ -6583,6 +6583,7 @@
"src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h",
@ -6787,6 +6788,8 @@
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.c",
@ -6813,12 +6816,10 @@
"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",
"src/core/ext/client_channel/method_config.h",
"src/core/ext/client_channel/parse_address.h",
"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/resolver_result.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h"
@ -6846,8 +6847,6 @@
"src/core/ext/client_channel/lb_policy_factory.h",
"src/core/ext/client_channel/lb_policy_registry.c",
"src/core/ext/client_channel/lb_policy_registry.h",
"src/core/ext/client_channel/method_config.c",
"src/core/ext/client_channel/method_config.h",
"src/core/ext/client_channel/parse_address.c",
"src/core/ext/client_channel/parse_address.h",
"src/core/ext/client_channel/resolver.c",
@ -6856,8 +6855,6 @@
"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/resolver_result.c",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.c",

@ -1306,6 +1306,7 @@
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
@ -1321,6 +1322,7 @@
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
@ -36676,6 +36678,27 @@
"shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure",
"timeout_seconds": 180
},
{
"args": [
"--scenarios_json",
"{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}]}"
],
"boringssl": true,
"ci_platforms": [
"linux"
],
"cpu_cost": 8,
"defaults": "boringssl",
"exclude_configs": [],
"flaky": false,
"language": "c++",
"name": "json_run_localhost",
"platforms": [
"linux"
],
"shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure",
"timeout_seconds": 180
},
{
"args": [
"--scenarios_json",
@ -36928,6 +36951,27 @@
"shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure",
"timeout_seconds": 180
},
{
"args": [
"--scenarios_json",
"{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}, \"num_clients\": 0}]}"
],
"boringssl": true,
"ci_platforms": [
"linux"
],
"cpu_cost": 8,
"defaults": "boringssl",
"exclude_configs": [],
"flaky": false,
"language": "c++",
"name": "json_run_localhost",
"platforms": [
"linux"
],
"shortname": "json_run_localhost:cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure",
"timeout_seconds": 180
},
{
"args": [
"--scenarios_json",

@ -382,6 +382,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
@ -439,12 +440,10 @@
<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" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\method_config.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.h" />
<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\resolver_result.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" />
@ -674,6 +673,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">
@ -806,8 +807,6 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_registry.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\method_config.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.c">
@ -816,8 +815,6 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.c">

@ -307,6 +307,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
@ -505,9 +508,6 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_registry.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\method_config.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
@ -520,9 +520,6 @@
<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\resolver_result.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>
@ -968,6 +965,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
@ -1139,9 +1139,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_registry.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\method_config.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
@ -1154,9 +1151,6 @@
<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\resolver_result.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>

@ -275,6 +275,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
@ -523,6 +524,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">

@ -364,6 +364,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
@ -758,6 +761,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>

@ -372,6 +372,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
@ -405,12 +406,10 @@
<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" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\method_config.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.h" />
<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\resolver_result.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" />
@ -642,6 +641,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">
@ -724,8 +725,6 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_registry.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\method_config.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.c">
@ -734,8 +733,6 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.c">

@ -310,6 +310,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
@ -433,9 +436,6 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_registry.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\method_config.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
@ -448,9 +448,6 @@
<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\resolver_result.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>
@ -881,6 +878,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
@ -980,9 +980,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\lb_policy_registry.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\method_config.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\parse_address.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
@ -995,9 +992,6 @@
<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\resolver_result.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>

Loading…
Cancel
Save