Merge github.com:grpc/grpc into slice_with_exec_ctx

reviewable/pr8705/r2
Craig Tiller 9 years ago
commit b28c7e8710
  1. 16
      BUILD
  2. 6
      CMakeLists.txt
  3. 8
      Makefile
  4. 2
      binding.gyp
  5. 4
      build.yaml
  6. 2
      config.m4
  7. 6
      gRPC-Core.podspec
  8. 4
      grpc.gemspec
  9. 7
      include/grpc++/channel.h
  10. 4
      include/grpc++/support/channel_arguments.h
  11. 3
      include/grpc/impl/codegen/grpc_types.h
  12. 4
      package.xml
  13. 122
      src/core/ext/client_channel/client_channel.c
  14. 6
      src/core/ext/client_channel/lb_policy_registry.c
  15. 24
      src/core/ext/lb_policy/grpclb/grpclb.c
  16. 60
      src/core/lib/channel/message_size_filter.c
  17. 9
      src/core/lib/support/string.c
  18. 3
      src/core/lib/support/string.h
  19. 42
      src/core/lib/transport/mdstr_hash_table.c
  20. 18
      src/core/lib/transport/mdstr_hash_table.h
  21. 251
      src/core/lib/transport/service_config.c
  22. 71
      src/core/lib/transport/service_config.h
  23. 30
      src/cpp/client/channel_cc.cc
  24. 5
      src/cpp/common/channel_arguments.cc
  25. 2
      src/python/grpcio/grpc_core_dependencies.py
  26. 8
      src/python/grpcio_tests/tests/interop/client.py
  27. 6
      test/core/channel/channel_args_test.c
  28. 49
      test/core/client_channel/lb_policies_test.c
  29. 27
      test/core/end2end/connection_refused_test.c
  30. 28
      test/core/end2end/tests/cancel_after_accept.c
  31. 55
      test/core/end2end/tests/max_message_length.c
  32. 6
      test/core/iomgr/ev_epoll_linux_test.c
  33. 6
      test/core/security/ssl_server_fuzzer.c
  34. 9
      test/cpp/end2end/round_robin_end2end_test.cc
  35. 43
      test/cpp/grpclb/grpclb_test.cc
  36. 4
      tools/doxygen/Doxyfile.core.internal
  37. 17
      tools/jenkins/run_full_performance.sh
  38. 8
      tools/run_tests/performance/build_performance.sh
  39. 17
      tools/run_tests/performance/remote_host_prepare.sh
  40. 4
      tools/run_tests/run_performance_tests.py
  41. 6
      tools/run_tests/sources_and_headers.json
  42. 6
      vsprojects/vcxproj/grpc/grpc.vcxproj
  43. 8
      vsprojects/vcxproj/grpc/grpc.vcxproj.filters
  44. 6
      vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
  45. 8
      vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
  46. 6
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
  47. 8
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters

16
BUILD

@ -248,8 +248,8 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.h", "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h", "src/core/lib/transport/transport.h",
@ -437,8 +437,8 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.c", "src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c", "src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c", "src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/pid_controller.c", "src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c", "src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c", "src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c", "src/core/lib/transport/transport.c",
@ -683,8 +683,8 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.h", "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h", "src/core/lib/transport/transport.h",
@ -857,8 +857,8 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.c", "src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c", "src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c", "src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/pid_controller.c", "src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c", "src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c", "src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c", "src/core/lib/transport/transport.c",
@ -1073,8 +1073,8 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.h", "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h", "src/core/lib/transport/transport.h",
@ -1239,8 +1239,8 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.c", "src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c", "src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c", "src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/pid_controller.c", "src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c", "src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c", "src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c", "src/core/lib/transport/transport.c",
@ -2105,8 +2105,8 @@ objc_library(
"src/core/lib/transport/mdstr_hash_table.c", "src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c", "src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c", "src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/pid_controller.c", "src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c", "src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c", "src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c", "src/core/lib/transport/transport.c",
@ -2330,8 +2330,8 @@ objc_library(
"src/core/lib/transport/mdstr_hash_table.h", "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h", "src/core/lib/transport/transport.h",

@ -392,8 +392,8 @@ add_library(grpc
src/core/lib/transport/mdstr_hash_table.c src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
src/core/lib/transport/pid_controller.c src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c src/core/lib/transport/transport.c
@ -672,8 +672,8 @@ add_library(grpc_cronet
src/core/lib/transport/mdstr_hash_table.c src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
src/core/lib/transport/pid_controller.c src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c src/core/lib/transport/transport.c
@ -924,8 +924,8 @@ add_library(grpc_unsecure
src/core/lib/transport/mdstr_hash_table.c src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
src/core/lib/transport/pid_controller.c src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c src/core/lib/transport/transport.c

@ -2731,8 +2731,8 @@ LIBGRPC_SRC = \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
@ -3029,8 +3029,8 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
@ -3318,8 +3318,8 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
@ -3536,8 +3536,8 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \

@ -671,8 +671,8 @@
'src/core/lib/transport/mdstr_hash_table.c', 'src/core/lib/transport/mdstr_hash_table.c',
'src/core/lib/transport/metadata.c', 'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c', 'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/method_config.c',
'src/core/lib/transport/pid_controller.c', 'src/core/lib/transport/pid_controller.c',
'src/core/lib/transport/service_config.c',
'src/core/lib/transport/static_metadata.c', 'src/core/lib/transport/static_metadata.c',
'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/timeout_encoding.c',
'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport.c',

@ -255,8 +255,8 @@ filegroups:
- src/core/lib/transport/mdstr_hash_table.h - src/core/lib/transport/mdstr_hash_table.h
- src/core/lib/transport/metadata.h - src/core/lib/transport/metadata.h
- src/core/lib/transport/metadata_batch.h - src/core/lib/transport/metadata_batch.h
- src/core/lib/transport/method_config.h
- src/core/lib/transport/pid_controller.h - src/core/lib/transport/pid_controller.h
- src/core/lib/transport/service_config.h
- src/core/lib/transport/static_metadata.h - src/core/lib/transport/static_metadata.h
- src/core/lib/transport/timeout_encoding.h - src/core/lib/transport/timeout_encoding.h
- src/core/lib/transport/transport.h - src/core/lib/transport/transport.h
@ -368,8 +368,8 @@ filegroups:
- src/core/lib/transport/mdstr_hash_table.c - src/core/lib/transport/mdstr_hash_table.c
- src/core/lib/transport/metadata.c - src/core/lib/transport/metadata.c
- src/core/lib/transport/metadata_batch.c - src/core/lib/transport/metadata_batch.c
- src/core/lib/transport/method_config.c
- src/core/lib/transport/pid_controller.c - src/core/lib/transport/pid_controller.c
- src/core/lib/transport/service_config.c
- src/core/lib/transport/static_metadata.c - src/core/lib/transport/static_metadata.c
- src/core/lib/transport/timeout_encoding.c - src/core/lib/transport/timeout_encoding.c
- src/core/lib/transport/transport.c - src/core/lib/transport/transport.c

@ -187,8 +187,8 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \

@ -338,8 +338,8 @@ Pod::Spec.new do |s|
'src/core/lib/transport/mdstr_hash_table.h', 'src/core/lib/transport/mdstr_hash_table.h',
'src/core/lib/transport/metadata.h', 'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h', 'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/method_config.h',
'src/core/lib/transport/pid_controller.h', 'src/core/lib/transport/pid_controller.h',
'src/core/lib/transport/service_config.h',
'src/core/lib/transport/static_metadata.h', 'src/core/lib/transport/static_metadata.h',
'src/core/lib/transport/timeout_encoding.h', 'src/core/lib/transport/timeout_encoding.h',
'src/core/lib/transport/transport.h', 'src/core/lib/transport/transport.h',
@ -531,8 +531,8 @@ Pod::Spec.new do |s|
'src/core/lib/transport/mdstr_hash_table.c', 'src/core/lib/transport/mdstr_hash_table.c',
'src/core/lib/transport/metadata.c', 'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c', 'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/method_config.c',
'src/core/lib/transport/pid_controller.c', 'src/core/lib/transport/pid_controller.c',
'src/core/lib/transport/service_config.c',
'src/core/lib/transport/static_metadata.c', 'src/core/lib/transport/static_metadata.c',
'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/timeout_encoding.c',
'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport.c',
@ -741,8 +741,8 @@ Pod::Spec.new do |s|
'src/core/lib/transport/mdstr_hash_table.h', 'src/core/lib/transport/mdstr_hash_table.h',
'src/core/lib/transport/metadata.h', 'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h', 'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/method_config.h',
'src/core/lib/transport/pid_controller.h', 'src/core/lib/transport/pid_controller.h',
'src/core/lib/transport/service_config.h',
'src/core/lib/transport/static_metadata.h', 'src/core/lib/transport/static_metadata.h',
'src/core/lib/transport/timeout_encoding.h', 'src/core/lib/transport/timeout_encoding.h',
'src/core/lib/transport/transport.h', 'src/core/lib/transport/transport.h',

@ -258,8 +258,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/mdstr_hash_table.h ) 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.h )
s.files += %w( src/core/lib/transport/metadata_batch.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/pid_controller.h ) s.files += %w( src/core/lib/transport/pid_controller.h )
s.files += %w( src/core/lib/transport/service_config.h )
s.files += %w( src/core/lib/transport/static_metadata.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/timeout_encoding.h )
s.files += %w( src/core/lib/transport/transport.h ) s.files += %w( src/core/lib/transport/transport.h )
@ -451,8 +451,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/mdstr_hash_table.c ) 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.c )
s.files += %w( src/core/lib/transport/metadata_batch.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/pid_controller.c ) s.files += %w( src/core/lib/transport/pid_controller.c )
s.files += %w( src/core/lib/transport/service_config.c )
s.files += %w( src/core/lib/transport/static_metadata.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/timeout_encoding.c )
s.files += %w( src/core/lib/transport/transport.c ) s.files += %w( src/core/lib/transport/transport.c )

@ -57,6 +57,13 @@ class Channel final : public ChannelInterface,
/// \a try_to_connect is set to true, try to connect. /// \a try_to_connect is set to true, try to connect.
grpc_connectivity_state GetState(bool try_to_connect) override; grpc_connectivity_state GetState(bool try_to_connect) override;
/// Returns the LB policy name, or the empty string if not yet available.
grpc::string GetLoadBalancingPolicyName() const;
/// Returns the service config in JSON form, or the empty string if
/// not available.
grpc::string GetServiceConfigJSON() const;
private: private:
template <class InputMessage, class OutputMessage> template <class InputMessage, class OutputMessage>
friend Status BlockingUnaryCall(ChannelInterface* channel, friend Status BlockingUnaryCall(ChannelInterface* channel,

@ -93,6 +93,10 @@ class ChannelArguments {
/// grpclb LB policy will be used, regardless of what is specified here. /// grpclb LB policy will be used, regardless of what is specified here.
void SetLoadBalancingPolicyName(const grpc::string& lb_policy_name); void SetLoadBalancingPolicyName(const grpc::string& lb_policy_name);
/// Set service config in JSON form.
/// Primarily meant for use in unit tests.
void SetServiceConfigJSON(const grpc::string& service_config_json);
// Generic channel argument setters. Only for advanced use cases. // Generic channel argument setters. Only for advanced use cases.
/// Set an integer argument \a value under \a key. /// Set an integer argument \a value under \a key.
void SetInt(const grpc::string& key, int value); void SetInt(const grpc::string& key, int value);

@ -478,6 +478,9 @@ typedef struct {
/* If non-NULL, will be set to point to a string indicating the LB /* If non-NULL, will be set to point to a string indicating the LB
* policy name. Caller takes ownership. */ * policy name. Caller takes ownership. */
char **lb_policy_name; char **lb_policy_name;
/* If non-NULL, will be set to point to a string containing the
* service config used by the channel in JSON form. */
char **service_config_json;
} grpc_channel_info; } grpc_channel_info;
typedef struct grpc_resource_quota grpc_resource_quota; typedef struct grpc_resource_quota grpc_resource_quota;

@ -265,8 +265,8 @@
<file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.h" role="src" /> <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.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.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/pid_controller.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/pid_controller.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/service_config.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/static_metadata.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/timeout_encoding.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/transport.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/transport.h" role="src" />
@ -458,8 +458,8 @@
<file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.c" role="src" /> <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.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.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/pid_controller.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/pid_controller.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/service_config.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/static_metadata.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/timeout_encoding.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/transport.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/transport.c" role="src" />

@ -56,7 +56,7 @@
#include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/method_config.h" #include "src/core/lib/transport/service_config.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
/* Client channel implementation */ /* Client channel implementation */
@ -82,34 +82,65 @@ static void *method_parameters_copy(void *value) {
return new_value; return new_value;
} }
static int method_parameters_cmp(void *value1, void *value2) { static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *p) {
const method_parameters *v1 = value1;
const method_parameters *v2 = value2;
const int retval = gpr_time_cmp(v1->timeout, v2->timeout);
if (retval != 0) return retval;
if (v1->wait_for_ready > v2->wait_for_ready) return 1;
if (v1->wait_for_ready < v2->wait_for_ready) return -1;
return 0;
}
static void method_parameters_del(grpc_exec_ctx *exec_ctx, void *p) {
gpr_free(p); gpr_free(p);
} }
static const grpc_mdstr_hash_table_vtable method_parameters_vtable = { static const grpc_mdstr_hash_table_vtable method_parameters_vtable = {
method_parameters_del, method_parameters_copy, method_parameters_cmp}; method_parameters_free, method_parameters_copy};
static void *method_config_convert_value( static void *method_parameters_create_from_json(const grpc_json *json) {
const grpc_method_config *method_config) { wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET;
gpr_timespec timeout = {0, 0, GPR_TIMESPAN};
for (grpc_json *field = json->child; field != NULL; field = field->next) {
if (field->key == NULL) continue;
if (strcmp(field->key, "waitForReady") == 0) {
if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate.
if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
return NULL;
}
wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
: WAIT_FOR_READY_FALSE;
} else if (strcmp(field->key, "timeout") == 0) {
if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate.
if (field->type != GRPC_JSON_STRING) return NULL;
size_t len = strlen(field->value);
if (field->value[len - 1] != 's') return NULL;
char *buf = gpr_strdup(field->value);
buf[len - 1] = '\0'; // Remove trailing 's'.
char *decimal_point = strchr(buf, '.');
if (decimal_point != NULL) {
*decimal_point = '\0';
timeout.tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
if (timeout.tv_nsec == -1) {
gpr_free(buf);
return NULL;
}
// There should always be exactly 3, 6, or 9 fractional digits.
int multiplier = 1;
switch (strlen(decimal_point + 1)) {
case 9:
break;
case 6:
multiplier *= 1000;
break;
case 3:
multiplier *= 1000000;
break;
default: // Unsupported number of digits.
gpr_free(buf);
return NULL;
}
timeout.tv_nsec *= multiplier;
}
timeout.tv_sec = gpr_parse_nonnegative_int(buf);
if (timeout.tv_sec == -1) return NULL;
gpr_free(buf);
}
}
method_parameters *value = gpr_malloc(sizeof(method_parameters)); method_parameters *value = gpr_malloc(sizeof(method_parameters));
const gpr_timespec *timeout = grpc_method_config_get_timeout(method_config); value->timeout = timeout;
value->timeout = timeout != NULL ? *timeout : gpr_time_0(GPR_TIMESPAN); value->wait_for_ready = wait_for_ready;
const bool *wait_for_ready =
grpc_method_config_get_wait_for_ready(method_config);
value->wait_for_ready =
wait_for_ready == NULL
? WAIT_FOR_READY_UNSET
: (wait_for_ready ? WAIT_FOR_READY_TRUE : WAIT_FOR_READY_FALSE);
return value; return value;
} }
@ -130,6 +161,8 @@ typedef struct client_channel_channel_data {
/** currently active load balancer */ /** currently active load balancer */
char *lb_policy_name; char *lb_policy_name;
grpc_lb_policy *lb_policy; grpc_lb_policy *lb_policy;
/** service config in JSON form */
char *service_config_json;
/** maps method names to method_parameters structs */ /** maps method names to method_parameters structs */
grpc_mdstr_hash_table *method_params_table; grpc_mdstr_hash_table *method_params_table;
/** incoming resolver result - set by resolver.next() */ /** incoming resolver result - set by resolver.next() */
@ -236,15 +269,12 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE; grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
bool exit_idle = false; bool exit_idle = false;
grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy"); grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
char *service_config_json = NULL;
if (chand->resolver_result != NULL) { if (chand->resolver_result != NULL) {
grpc_lb_policy_args lb_policy_args;
lb_policy_args.args = chand->resolver_result;
lb_policy_args.client_channel_factory = chand->client_channel_factory;
// Find LB policy name. // Find LB policy name.
const grpc_arg *channel_arg = const grpc_arg *channel_arg =
grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_LB_POLICY_NAME); grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
if (channel_arg != NULL) { if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING); GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
lb_policy_name = channel_arg->value.string; lb_policy_name = channel_arg->value.string;
@ -253,7 +283,7 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
// assume that we should use the grpclb policy, regardless of what the // assume that we should use the grpclb policy, regardless of what the
// resolver actually specified. // resolver actually specified.
channel_arg = channel_arg =
grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_LB_ADDRESSES); grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
if (channel_arg != NULL) { if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER); GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
grpc_lb_addresses *addresses = channel_arg->value.pointer.p; grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
@ -278,7 +308,10 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
// Use pick_first if nothing was specified and we didn't select grpclb // Use pick_first if nothing was specified and we didn't select grpclb
// above. // above.
if (lb_policy_name == NULL) lb_policy_name = "pick_first"; if (lb_policy_name == NULL) lb_policy_name = "pick_first";
// Instantiate LB policy.
grpc_lb_policy_args lb_policy_args;
lb_policy_args.args = chand->resolver_result;
lb_policy_args.client_channel_factory = chand->client_channel_factory;
lb_policy = lb_policy =
grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args); grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
if (lb_policy != NULL) { if (lb_policy != NULL) {
@ -287,13 +320,20 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
state = state =
grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error); grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
} }
// Find service config.
channel_arg = channel_arg =
grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_SERVICE_CONFIG); grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
if (channel_arg != NULL) { if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER); GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
method_params_table = grpc_method_config_table_convert( service_config_json = gpr_strdup(channel_arg->value.string);
exec_ctx, (grpc_method_config_table *)channel_arg->value.pointer.p, grpc_service_config *service_config =
method_config_convert_value, &method_parameters_vtable); grpc_service_config_create(service_config_json);
if (service_config != NULL) {
method_params_table = grpc_service_config_create_method_config_table(
exec_ctx, service_config, method_parameters_create_from_json,
&method_parameters_vtable);
grpc_service_config_destroy(service_config);
}
} }
// Before we clean up, save a copy of lb_policy_name, since it might // Before we clean up, save a copy of lb_policy_name, since it might
// be pointing to data inside chand->resolver_result. // be pointing to data inside chand->resolver_result.
@ -315,6 +355,10 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
} }
old_lb_policy = chand->lb_policy; old_lb_policy = chand->lb_policy;
chand->lb_policy = lb_policy; chand->lb_policy = lb_policy;
if (service_config_json != NULL) {
gpr_free(chand->service_config_json);
chand->service_config_json = service_config_json;
}
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table); grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table);
} }
@ -450,6 +494,11 @@ static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
? NULL ? NULL
: gpr_strdup(chand->lb_policy_name); : gpr_strdup(chand->lb_policy_name);
} }
if (info->service_config_json != NULL) {
*info->service_config_json = chand->service_config_json == NULL
? NULL
: gpr_strdup(chand->service_config_json);
}
gpr_mu_unlock(&chand->mu); gpr_mu_unlock(&chand->mu);
} }
@ -493,6 +542,7 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel"); GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
} }
gpr_free(chand->lb_policy_name); gpr_free(chand->lb_policy_name);
gpr_free(chand->service_config_json);
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table); grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table);
} }

@ -35,6 +35,8 @@
#include <string.h> #include <string.h>
#include "src/core/lib/support/string.h"
#define MAX_POLICIES 10 #define MAX_POLICIES 10
static grpc_lb_policy_factory *g_all_of_the_lb_policies[MAX_POLICIES]; static grpc_lb_policy_factory *g_all_of_the_lb_policies[MAX_POLICIES];
@ -52,7 +54,7 @@ void grpc_lb_policy_registry_shutdown(void) {
void grpc_register_lb_policy(grpc_lb_policy_factory *factory) { void grpc_register_lb_policy(grpc_lb_policy_factory *factory) {
int i; int i;
for (i = 0; i < g_number_of_lb_policies; i++) { for (i = 0; i < g_number_of_lb_policies; i++) {
GPR_ASSERT(0 != strcmp(factory->vtable->name, GPR_ASSERT(0 != gpr_stricmp(factory->vtable->name,
g_all_of_the_lb_policies[i]->vtable->name)); g_all_of_the_lb_policies[i]->vtable->name));
} }
GPR_ASSERT(g_number_of_lb_policies != MAX_POLICIES); GPR_ASSERT(g_number_of_lb_policies != MAX_POLICIES);
@ -66,7 +68,7 @@ static grpc_lb_policy_factory *lookup_factory(const char *name) {
if (name == NULL) return NULL; if (name == NULL) return NULL;
for (i = 0; i < g_number_of_lb_policies; i++) { for (i = 0; i < g_number_of_lb_policies; i++) {
if (0 == strcmp(name, g_all_of_the_lb_policies[i]->vtable->name)) { if (0 == gpr_stricmp(name, g_all_of_the_lb_policies[i]->vtable->name)) {
return g_all_of_the_lb_policies[i]; return g_all_of_the_lb_policies[i];
} }
} }

@ -187,14 +187,20 @@ static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg,
* addresses failed to connect). There won't be any user_data/token * addresses failed to connect). There won't be any user_data/token
* available */ * available */
if (wc_arg->target != NULL) { if (wc_arg->target != NULL) {
GPR_ASSERT(wc_arg->lb_token != NULL); if (wc_arg->lb_token != NULL) {
initial_metadata_add_lb_token(wc_arg->initial_metadata, initial_metadata_add_lb_token(wc_arg->initial_metadata,
wc_arg->lb_token_mdelem_storage, wc_arg->lb_token_mdelem_storage,
GRPC_MDELEM_REF(wc_arg->lb_token)); GRPC_MDELEM_REF(wc_arg->lb_token));
} else {
gpr_log(GPR_ERROR,
"No LB token for connected subchannel pick %p (from RR "
"instance %p).",
(void *)*wc_arg->target, (void *)wc_arg->rr_policy);
abort();
}
} }
if (grpc_lb_glb_trace) { if (grpc_lb_glb_trace) {
gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")", gpr_log(GPR_INFO, "Unreffing RR %p", (void *)wc_arg->rr_policy);
(intptr_t)wc_arg->rr_policy);
} }
GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure"); GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure");
} }
@ -412,7 +418,7 @@ static void parse_server(const grpc_grpclb_server *server,
} }
/* Returns addresses extracted from \a serverlist. */ /* Returns addresses extracted from \a serverlist. */
static grpc_lb_addresses *process_serverlist( static grpc_lb_addresses *process_serverlist_locked(
grpc_exec_ctx *exec_ctx, const grpc_grpclb_serverlist *serverlist) { grpc_exec_ctx *exec_ctx, const grpc_grpclb_serverlist *serverlist) {
size_t num_valid = 0; size_t num_valid = 0;
/* first pass: count how many are valid in order to allocate the necessary /* first pass: count how many are valid in order to allocate the necessary
@ -452,10 +458,12 @@ static grpc_lb_addresses *process_serverlist(
user_data = grpc_mdelem_from_metadata_strings( user_data = grpc_mdelem_from_metadata_strings(
exec_ctx, GRPC_MDSTR_LB_TOKEN, lb_token_mdstr); exec_ctx, GRPC_MDSTR_LB_TOKEN, lb_token_mdstr);
} else { } else {
gpr_log(GPR_ERROR, char *uri = grpc_sockaddr_to_uri(&addr);
gpr_log(GPR_INFO,
"Missing LB token for backend address '%s'. The empty token will " "Missing LB token for backend address '%s'. The empty token will "
"be used instead", "be used instead",
grpc_sockaddr_to_uri(&addr)); uri);
gpr_free(uri);
user_data = GRPC_MDELEM_LB_TOKEN_EMPTY; user_data = GRPC_MDELEM_LB_TOKEN_EMPTY;
} }
@ -509,7 +517,8 @@ static grpc_lb_policy *create_rr_locked(
grpc_lb_policy_args args; grpc_lb_policy_args args;
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.client_channel_factory = glb_policy->cc_factory; args.client_channel_factory = glb_policy->cc_factory;
grpc_lb_addresses *addresses = process_serverlist(exec_ctx, serverlist); grpc_lb_addresses *addresses =
process_serverlist_locked(exec_ctx, serverlist);
// Replace the LB addresses in the channel args that we pass down to // Replace the LB addresses in the channel args that we pass down to
// the subchannel. // the subchannel.
@ -769,7 +778,6 @@ static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
* while holding glb_policy->mu: lb_on_server_status_received, invoked due to * while holding glb_policy->mu: lb_on_server_status_received, invoked due to
* the cancel, needs to acquire that same lock */ * the cancel, needs to acquire that same lock */
grpc_call *lb_call = glb_policy->lb_call; grpc_call *lb_call = glb_policy->lb_call;
glb_policy->lb_call = NULL;
gpr_mu_unlock(&glb_policy->mu); gpr_mu_unlock(&glb_policy->mu);
/* glb_policy->lb_call and this local lb_call must be consistent at this point /* glb_policy->lb_call and this local lb_call must be consistent at this point

@ -39,7 +39,8 @@
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/transport/method_config.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/transport/service_config.h"
#define DEFAULT_MAX_SEND_MESSAGE_LENGTH -1 // Unlimited. #define DEFAULT_MAX_SEND_MESSAGE_LENGTH -1 // Unlimited.
// The protobuf library will (by default) start warning at 100 megs. // The protobuf library will (by default) start warning at 100 megs.
@ -56,32 +57,33 @@ static void* message_size_limits_copy(void* value) {
return new_value; return new_value;
} }
static int message_size_limits_cmp(void* value1, void* value2) { static void message_size_limits_free(grpc_exec_ctx* exec_ctx, void* value) {
const message_size_limits* v1 = value1; gpr_free(value);
const message_size_limits* v2 = value2;
if (v1->max_send_size > v2->max_send_size) return 1;
if (v1->max_send_size < v2->max_send_size) return -1;
if (v1->max_recv_size > v2->max_recv_size) return 1;
if (v1->max_recv_size < v2->max_recv_size) return -1;
return 0;
} }
static void free_mem(grpc_exec_ctx* exec_ctx, void* p) { gpr_free(p); }
static const grpc_mdstr_hash_table_vtable message_size_limits_vtable = { static const grpc_mdstr_hash_table_vtable message_size_limits_vtable = {
free_mem, message_size_limits_copy, message_size_limits_cmp}; message_size_limits_free, message_size_limits_copy};
static void* method_config_convert_value( static void* message_size_limits_create_from_json(const grpc_json* json) {
const grpc_method_config* method_config) { int max_request_message_bytes = -1;
int max_response_message_bytes = -1;
for (grpc_json* field = json->child; field != NULL; field = field->next) {
if (field->key == NULL) continue;
if (strcmp(field->key, "maxRequestMessageBytes") == 0) {
if (max_request_message_bytes >= 0) return NULL; // Duplicate.
if (field->type != GRPC_JSON_STRING) return NULL;
max_request_message_bytes = gpr_parse_nonnegative_int(field->value);
if (max_request_message_bytes == -1) return NULL;
} else if (strcmp(field->key, "maxResponseMessageBytes") == 0) {
if (max_response_message_bytes >= 0) return NULL; // Duplicate.
if (field->type != GRPC_JSON_STRING) return NULL;
max_response_message_bytes = gpr_parse_nonnegative_int(field->value);
if (max_response_message_bytes == -1) return NULL;
}
}
message_size_limits* value = gpr_malloc(sizeof(message_size_limits)); message_size_limits* value = gpr_malloc(sizeof(message_size_limits));
const int32_t* max_request_message_bytes = value->max_send_size = max_request_message_bytes;
grpc_method_config_get_max_request_message_bytes(method_config); value->max_recv_size = max_response_message_bytes;
value->max_send_size =
max_request_message_bytes != NULL ? *max_request_message_bytes : -1;
const int32_t* max_response_message_bytes =
grpc_method_config_get_max_response_message_bytes(method_config);
value->max_recv_size =
max_response_message_bytes != NULL ? *max_response_message_bytes : -1;
return value; return value;
} }
@ -225,10 +227,16 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx,
const grpc_arg* channel_arg = const grpc_arg* channel_arg =
grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVICE_CONFIG); grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVICE_CONFIG);
if (channel_arg != NULL) { if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER); GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
chand->method_limit_table = grpc_method_config_table_convert( grpc_service_config* service_config =
exec_ctx, (grpc_method_config_table*)channel_arg->value.pointer.p, grpc_service_config_create(channel_arg->value.string);
method_config_convert_value, &message_size_limits_vtable); if (service_config != NULL) {
chand->method_limit_table =
grpc_service_config_create_method_config_table(
exec_ctx, service_config, message_size_limits_create_from_json,
&message_size_limits_vtable);
grpc_service_config_destroy(service_config);
}
} }
} }

@ -34,7 +34,9 @@
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include <ctype.h> #include <ctype.h>
#include <limits.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
@ -189,6 +191,13 @@ int int64_ttoa(int64_t value, char *string) {
return i; return i;
} }
int gpr_parse_nonnegative_int(const char *value) {
char *end;
long result = strtol(value, &end, 0);
if (*end != '\0' || result < 0 || result > INT_MAX) return -1;
return (int)result;
}
char *gpr_leftpad(const char *str, char flag, size_t length) { char *gpr_leftpad(const char *str, char flag, size_t length) {
const size_t str_length = strlen(str); const size_t str_length = strlen(str);
const size_t out_length = str_length > length ? str_length : length; const size_t out_length = str_length > length ? str_length : length;

@ -77,6 +77,9 @@ NOTE: This function ensures sufficient bit width even on Win x64,
where long is 32bit is size.*/ where long is 32bit is size.*/
int int64_ttoa(int64_t value, char *output); int int64_ttoa(int64_t value, char *output);
// Parses a non-negative number from a value string. Returns -1 on error.
int gpr_parse_nonnegative_int(const char *value);
/* Reverse a run of bytes */ /* Reverse a run of bytes */
void gpr_reverse_bytes(char *str, int len); void gpr_reverse_bytes(char *str, int len);

@ -41,7 +41,6 @@
struct grpc_mdstr_hash_table { struct grpc_mdstr_hash_table {
gpr_refcount refs; gpr_refcount refs;
size_t num_entries;
size_t size; size_t size;
grpc_mdstr_hash_table_entry* entries; grpc_mdstr_hash_table_entry* entries;
}; };
@ -77,7 +76,6 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_create(
grpc_mdstr_hash_table* table = gpr_malloc(sizeof(*table)); grpc_mdstr_hash_table* table = gpr_malloc(sizeof(*table));
memset(table, 0, sizeof(*table)); memset(table, 0, sizeof(*table));
gpr_ref_init(&table->refs, 1); gpr_ref_init(&table->refs, 1);
table->num_entries = num_entries;
// Quadratic probing gets best performance when the table is no more // Quadratic probing gets best performance when the table is no more
// than half full. // than half full.
table->size = num_entries * 2; table->size = num_entries * 2;
@ -96,7 +94,7 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table) {
return table; return table;
} }
int grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx, void grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
grpc_mdstr_hash_table* table) { grpc_mdstr_hash_table* table) {
if (table != NULL && gpr_unref(&table->refs)) { if (table != NULL && gpr_unref(&table->refs)) {
for (size_t i = 0; i < table->size; ++i) { for (size_t i = 0; i < table->size; ++i) {
@ -108,13 +106,7 @@ int grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
} }
gpr_free(table->entries); gpr_free(table->entries);
gpr_free(table); gpr_free(table);
return 1;
} }
return 0;
}
size_t grpc_mdstr_hash_table_num_entries(const grpc_mdstr_hash_table* table) {
return table->num_entries;
} }
void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table, void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
@ -124,35 +116,3 @@ void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
if (idx == table->size) return NULL; // Not found. if (idx == table->size) return NULL; // Not found.
return table->entries[idx].value; return table->entries[idx].value;
} }
int grpc_mdstr_hash_table_cmp(const grpc_mdstr_hash_table* table1,
const grpc_mdstr_hash_table* table2) {
// Compare by num_entries.
if (table1->num_entries < table2->num_entries) return -1;
if (table1->num_entries > table2->num_entries) return 1;
for (size_t i = 0; i < table1->num_entries; ++i) {
grpc_mdstr_hash_table_entry* e1 = &table1->entries[i];
grpc_mdstr_hash_table_entry* e2 = &table2->entries[i];
// Compare keys by hash value.
if (e1->key->hash < e2->key->hash) return -1;
if (e1->key->hash > e2->key->hash) return 1;
// Compare by vtable (pointer equality).
if (e1->vtable < e2->vtable) return -1;
if (e1->vtable > e2->vtable) return 1;
// Compare values via vtable.
const int value_result = e1->vtable->compare_value(e1->value, e2->value);
if (value_result != 0) return value_result;
}
return 0;
}
void grpc_mdstr_hash_table_iterate(
const grpc_mdstr_hash_table* table,
void (*func)(const grpc_mdstr_hash_table_entry* entry, void* user_data),
void* user_data) {
for (size_t i = 0; i < table->size; ++i) {
if (table->entries[i].key != NULL) {
func(&table->entries[i], user_data);
}
}
}

@ -51,7 +51,6 @@ typedef struct grpc_mdstr_hash_table grpc_mdstr_hash_table;
typedef struct grpc_mdstr_hash_table_vtable { typedef struct grpc_mdstr_hash_table_vtable {
void (*destroy_value)(grpc_exec_ctx* exec_ctx, void* value); void (*destroy_value)(grpc_exec_ctx* exec_ctx, void* value);
void* (*copy_value)(void* value); void* (*copy_value)(void* value);
int (*compare_value)(void* value1, void* value2);
} grpc_mdstr_hash_table_vtable; } grpc_mdstr_hash_table_vtable;
typedef struct grpc_mdstr_hash_table_entry { typedef struct grpc_mdstr_hash_table_entry {
@ -67,27 +66,12 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_create(
size_t num_entries, grpc_mdstr_hash_table_entry* entries); size_t num_entries, grpc_mdstr_hash_table_entry* entries);
grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table); grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table);
/** Returns 1 when \a table is destroyed. */ void grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
int grpc_mdstr_hash_table_unref(grpc_exec_ctx* exec_ctx,
grpc_mdstr_hash_table* table); grpc_mdstr_hash_table* table);
/** Returns the number of entries in \a table. */
size_t grpc_mdstr_hash_table_num_entries(const grpc_mdstr_hash_table* table);
/** Returns the value from \a table associated with \a key. /** Returns the value from \a table associated with \a key.
Returns NULL if \a key is not found. */ Returns NULL if \a key is not found. */
void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table, void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
const grpc_mdstr* key); const grpc_mdstr* key);
/** Compares two hash tables.
The sort order is stable but undefined. */
int grpc_mdstr_hash_table_cmp(const grpc_mdstr_hash_table* table1,
const grpc_mdstr_hash_table* table2);
/** Iterates over the entries in \a table, calling \a func for each entry. */
void grpc_mdstr_hash_table_iterate(
const grpc_mdstr_hash_table* table,
void (*func)(const grpc_mdstr_hash_table_entry* entry, void* user_data),
void* user_data);
#endif /* GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H */ #endif /* GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H */

@ -0,0 +1,251 @@
//
// 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/lib/transport/service_config.h"
#include <string.h>
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/json/json.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/mdstr_hash_table.h"
// The main purpose of the code here is to parse the service config in
// JSON form, which will look like this:
//
// {
// "loadBalancingPolicy": "string", // optional
// "methodConfig": [ // array of one or more method_config objects
// {
// "name": [ // array of one or more name objects
// {
// "service": "string", // required
// "method": "string", // optional
// }
// ],
// // remaining fields are optional.
// // see https://developers.google.com/protocol-buffers/docs/proto3#json
// // for format details.
// "waitForReady": bool,
// "timeout": "duration_string",
// "maxRequestMessageBytes": "int64_string",
// "maxResponseMessageBytes": "int64_string",
// }
// ]
// }
struct grpc_service_config {
char* json_string; // Underlying storage for json_tree.
grpc_json* json_tree;
};
grpc_service_config* grpc_service_config_create(const char* json_string) {
grpc_service_config* service_config = gpr_malloc(sizeof(*service_config));
service_config->json_string = gpr_strdup(json_string);
service_config->json_tree =
grpc_json_parse_string(service_config->json_string);
if (service_config->json_tree == NULL) {
gpr_log(GPR_INFO, "failed to parse JSON for service config");
gpr_free(service_config->json_string);
gpr_free(service_config);
return NULL;
}
return service_config;
}
void grpc_service_config_destroy(grpc_service_config* service_config) {
grpc_json_destroy(service_config->json_tree);
gpr_free(service_config->json_string);
gpr_free(service_config);
}
const char* grpc_service_config_get_lb_policy_name(
const grpc_service_config* service_config) {
const grpc_json* json = service_config->json_tree;
if (json->type != GRPC_JSON_OBJECT || json->key != NULL) return NULL;
const char* lb_policy_name = NULL;
for (grpc_json* field = json->child; field != NULL; field = field->next) {
if (field->key == NULL) return NULL;
if (strcmp(field->key, "loadBalancingPolicy") == 0) {
if (lb_policy_name != NULL) return NULL; // Duplicate.
if (field->type != GRPC_JSON_STRING) return NULL;
lb_policy_name = field->value;
}
}
return lb_policy_name;
}
// Returns the number of names specified in the method config \a json.
static size_t count_names_in_method_config_json(grpc_json* json) {
size_t num_names = 0;
for (grpc_json* field = json->child; field != NULL; field = field->next) {
if (field->key != NULL && strcmp(field->key, "name") == 0) ++num_names;
}
return num_names;
}
// Returns a path string for the JSON name object specified by \a json.
// Returns NULL on error. Caller takes ownership of result.
static char* parse_json_method_name(grpc_json* json) {
if (json->type != GRPC_JSON_OBJECT) return NULL;
const char* service_name = NULL;
const char* method_name = NULL;
for (grpc_json* child = json->child; child != NULL; child = child->next) {
if (child->key == NULL) return NULL;
if (child->type != GRPC_JSON_STRING) return NULL;
if (strcmp(child->key, "service") == 0) {
if (service_name != NULL) return NULL; // Duplicate.
if (child->value == NULL) return NULL;
service_name = child->value;
} else if (strcmp(child->key, "method") == 0) {
if (method_name != NULL) return NULL; // Duplicate.
if (child->value == NULL) return NULL;
method_name = child->value;
}
}
if (service_name == NULL) return NULL; // Required field.
char* path;
gpr_asprintf(&path, "/%s/%s", service_name,
method_name == NULL ? "*" : method_name);
return path;
}
// Parses the method config from \a json. Adds an entry to \a entries for
// each name found, incrementing \a idx for each entry added.
// Returns false on error.
static bool parse_json_method_config(
grpc_exec_ctx* exec_ctx, grpc_json* json,
void* (*create_value)(const grpc_json* method_config_json),
const grpc_mdstr_hash_table_vtable* vtable,
grpc_mdstr_hash_table_entry* entries, size_t* idx) {
// Construct value.
void* method_config = create_value(json);
if (method_config == NULL) return false;
// Construct list of paths.
bool success = false;
gpr_strvec paths;
gpr_strvec_init(&paths);
for (grpc_json* child = json->child; child != NULL; child = child->next) {
if (child->key == NULL) continue;
if (strcmp(child->key, "name") == 0) {
if (child->type != GRPC_JSON_ARRAY) goto done;
for (grpc_json* name = child->child; name != NULL; name = name->next) {
char* path = parse_json_method_name(name);
gpr_strvec_add(&paths, path);
}
}
}
if (paths.count == 0) goto done; // No names specified.
// Add entry for each path.
for (size_t i = 0; i < paths.count; ++i) {
entries[*idx].key = grpc_mdstr_from_string(paths.strs[i]);
entries[*idx].value = vtable->copy_value(method_config);
entries[*idx].vtable = vtable;
++*idx;
}
success = true;
done:
vtable->destroy_value(exec_ctx, method_config);
gpr_strvec_destroy(&paths);
return success;
}
grpc_mdstr_hash_table* grpc_service_config_create_method_config_table(
grpc_exec_ctx* exec_ctx, const grpc_service_config* service_config,
void* (*create_value)(const grpc_json* method_config_json),
const grpc_mdstr_hash_table_vtable* vtable) {
const grpc_json* json = service_config->json_tree;
// Traverse parsed JSON tree.
if (json->type != GRPC_JSON_OBJECT || json->key != NULL) return NULL;
size_t num_entries = 0;
grpc_mdstr_hash_table_entry* entries = NULL;
for (grpc_json* field = json->child; field != NULL; field = field->next) {
if (field->key == NULL) return NULL;
if (strcmp(field->key, "methodConfig") == 0) {
if (entries != NULL) return NULL; // Duplicate.
if (field->type != GRPC_JSON_ARRAY) return NULL;
// Find number of entries.
for (grpc_json* method = field->child; method != NULL;
method = method->next) {
num_entries += count_names_in_method_config_json(method);
}
// Populate method config table entries.
entries = gpr_malloc(num_entries * sizeof(grpc_mdstr_hash_table_entry));
size_t idx = 0;
for (grpc_json* method = field->child; method != NULL;
method = method->next) {
if (!parse_json_method_config(exec_ctx, method, create_value, vtable,
entries, &idx)) {
return NULL;
}
}
GPR_ASSERT(idx == num_entries);
}
}
// Instantiate method config table.
grpc_mdstr_hash_table* method_config_table = NULL;
if (entries != NULL) {
method_config_table = grpc_mdstr_hash_table_create(num_entries, entries);
// Clean up.
for (size_t i = 0; i < num_entries; ++i) {
GRPC_MDSTR_UNREF(exec_ctx, entries[i].key);
vtable->destroy_value(exec_ctx, entries[i].value);
}
gpr_free(entries);
}
return method_config_table;
}
void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
const grpc_mdstr_hash_table* table,
const grpc_mdstr* path) {
void* value = grpc_mdstr_hash_table_get(table, path);
// If we didn't find a match for the path, try looking for a wildcard
// entry (i.e., change "/service/method" to "/service/*").
if (value == NULL) {
const char* path_str = grpc_mdstr_as_c_string(path);
const char* sep = strrchr(path_str, '/') + 1;
const size_t len = (size_t)(sep - path_str);
char* buf = gpr_malloc(len + 2); // '*' and NUL
memcpy(buf, path_str, len);
buf[len] = '*';
buf[len + 1] = '\0';
grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf);
gpr_free(buf);
value = grpc_mdstr_hash_table_get(table, wildcard_path);
GRPC_MDSTR_UNREF(exec_ctx, wildcard_path);
}
return value;
}

@ -0,0 +1,71 @@
//
// 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.
//
#ifndef GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H
#define GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H
#include <grpc/impl/codegen/grpc_types.h>
#include "src/core/lib/json/json.h"
#include "src/core/lib/transport/mdstr_hash_table.h"
typedef struct grpc_service_config grpc_service_config;
grpc_service_config* grpc_service_config_create(const char* json_string);
void grpc_service_config_destroy(grpc_service_config* service_config);
/// Gets the LB policy name from \a service_config.
/// Returns NULL if no LB policy name was specified.
/// Caller does NOT take ownership.
const char* grpc_service_config_get_lb_policy_name(
const grpc_service_config* service_config);
/// Creates a method config table based on the data in \a json.
/// The table's keys are request paths. The table's value type is
/// returned by \a create_value(), based on data parsed from the JSON tree.
/// \a vtable provides methods used to manage the values.
/// Returns NULL on error.
grpc_mdstr_hash_table* grpc_service_config_create_method_config_table(
grpc_exec_ctx* exec_ctx, const grpc_service_config* service_config,
void* (*create_value)(const grpc_json* method_config_json),
const grpc_mdstr_hash_table_vtable* vtable);
/// A helper function for looking up values in the table returned by
/// \a grpc_service_config_create_method_config_table().
/// Gets the method config for the specified \a path, which should be of
/// the form "/service/method".
/// Returns NULL if the method has no config.
/// Caller does NOT own a reference to the result.
void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx,
const grpc_mdstr_hash_table* table,
const grpc_mdstr* path);
#endif /* GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H */

@ -48,6 +48,7 @@
#include <grpc++/support/time.h> #include <grpc++/support/time.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/slice.h> #include <grpc/slice.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
@ -61,6 +62,35 @@ Channel::Channel(const grpc::string& host, grpc_channel* channel)
Channel::~Channel() { grpc_channel_destroy(c_channel_); } Channel::~Channel() { grpc_channel_destroy(c_channel_); }
namespace {
grpc::string GetChannelInfoField(grpc_channel* channel,
grpc_channel_info* channel_info,
char*** channel_info_field) {
char* value = NULL;
memset(channel_info, 0, sizeof(*channel_info));
*channel_info_field = &value;
grpc_channel_get_info(channel, channel_info);
if (value == NULL) return "";
grpc::string result = value;
gpr_free(value);
return result;
}
} // namespace
grpc::string Channel::GetLoadBalancingPolicyName() const {
grpc_channel_info channel_info;
return GetChannelInfoField(c_channel_, &channel_info,
&channel_info.lb_policy_name);
}
grpc::string Channel::GetServiceConfigJSON() const {
grpc_channel_info channel_info;
return GetChannelInfoField(c_channel_, &channel_info,
&channel_info.service_config_json);
}
Call Channel::CreateCall(const RpcMethod& method, ClientContext* context, Call Channel::CreateCall(const RpcMethod& method, ClientContext* context,
CompletionQueue* cq) { CompletionQueue* cq) {
const bool kRegistered = method.channel_tag() && context->authority().empty(); const bool kRegistered = method.channel_tag() && context->authority().empty();

@ -148,6 +148,11 @@ void ChannelArguments::SetLoadBalancingPolicyName(
SetString(GRPC_ARG_LB_POLICY_NAME, lb_policy_name); SetString(GRPC_ARG_LB_POLICY_NAME, lb_policy_name);
} }
void ChannelArguments::SetServiceConfigJSON(
const grpc::string& service_config_json) {
SetString(GRPC_ARG_SERVICE_CONFIG, service_config_json);
}
void ChannelArguments::SetInt(const grpc::string& key, int value) { void ChannelArguments::SetInt(const grpc::string& key, int value) {
grpc_arg arg; grpc_arg arg;
arg.type = GRPC_ARG_INTEGER; arg.type = GRPC_ARG_INTEGER;

@ -181,8 +181,8 @@ CORE_SOURCE_FILES = [
'src/core/lib/transport/mdstr_hash_table.c', 'src/core/lib/transport/mdstr_hash_table.c',
'src/core/lib/transport/metadata.c', 'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c', 'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/method_config.c',
'src/core/lib/transport/pid_controller.c', 'src/core/lib/transport/pid_controller.c',
'src/core/lib/transport/service_config.c',
'src/core/lib/transport/static_metadata.c', 'src/core/lib/transport/static_metadata.c',
'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/timeout_encoding.c',
'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport.c',

@ -43,11 +43,13 @@ from tests.interop import resources
def _args(): def _args():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument(
'--server_host', help='the host to which to connect', type=str) '--server_host', help='the host to which to connect', type=str,
default="127.0.0.1")
parser.add_argument( parser.add_argument(
'--server_port', help='the port to which to connect', type=int) '--server_port', help='the port to which to connect', type=int)
parser.add_argument( parser.add_argument(
'--test_case', help='the test case to execute', type=str) '--test_case', help='the test case to execute', type=str,
default="large_unary")
parser.add_argument( parser.add_argument(
'--use_tls', help='require a secure connection', default=False, '--use_tls', help='require a secure connection', default=False,
type=resources.parse_bool) type=resources.parse_bool)
@ -55,7 +57,7 @@ def _args():
'--use_test_ca', help='replace platform root CAs with ca.pem', '--use_test_ca', help='replace platform root CAs with ca.pem',
default=False, type=resources.parse_bool) default=False, type=resources.parse_bool)
parser.add_argument( parser.add_argument(
'--server_host_override', '--server_host_override', default="foo.test.google.fr",
help='the server host to which to claim to connect', type=str) help='the server host to which to claim to connect', type=str)
parser.add_argument('--oauth_scope', help='scope for OAuth tokens', type=str) parser.add_argument('--oauth_scope', help='scope for OAuth tokens', type=str)
parser.add_argument( parser.add_argument(

@ -151,7 +151,11 @@ static void test_set_socket_mutator(void) {
GPR_ASSERT(strcmp(ch_args->args[0].key, GRPC_ARG_SOCKET_MUTATOR) == 0); GPR_ASSERT(strcmp(ch_args->args[0].key, GRPC_ARG_SOCKET_MUTATOR) == 0);
GPR_ASSERT(ch_args->args[0].type == GRPC_ARG_POINTER); GPR_ASSERT(ch_args->args[0].type == GRPC_ARG_POINTER);
grpc_channel_args_destroy(ch_args); {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_channel_args_destroy(&exec_ctx, ch_args);
grpc_exec_ctx_finish(&exec_ctx);
}
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {

@ -43,6 +43,7 @@
#include "src/core/ext/client_channel/client_channel.h" #include "src/core/ext/client_channel/client_channel.h"
#include "src/core/ext/client_channel/lb_policy_registry.h" #include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel.h"
@ -522,7 +523,7 @@ static grpc_channel *create_client(const servers_fixture *f) {
arg_array[0].value.integer = RETRY_TIMEOUT; arg_array[0].value.integer = RETRY_TIMEOUT;
arg_array[1].type = GRPC_ARG_STRING; arg_array[1].type = GRPC_ARG_STRING;
arg_array[1].key = GRPC_ARG_LB_POLICY_NAME; arg_array[1].key = GRPC_ARG_LB_POLICY_NAME;
arg_array[1].value.string = "round_robin"; arg_array[1].value.string = "ROUND_ROBIN";
args.num_args = 2; args.num_args = 2;
args.args = arg_array; args.args = arg_array;
@ -611,29 +612,47 @@ static void test_pending_calls(size_t concurrent_calls) {
} }
static void test_get_channel_info() { static void test_get_channel_info() {
grpc_channel_args args;
grpc_arg arg_array[1];
arg_array[0].type = GRPC_ARG_STRING;
arg_array[0].key = GRPC_ARG_LB_POLICY_NAME;
arg_array[0].value.string = "round_robin";
args.num_args = 1;
args.args = arg_array;
grpc_channel *channel = grpc_channel *channel =
grpc_insecure_channel_create("ipv4:127.0.0.1:1234", &args, NULL); grpc_insecure_channel_create("ipv4:127.0.0.1:1234", NULL, NULL);
// Ensures that resolver returns. // Ensures that resolver returns.
grpc_channel_check_connectivity_state(channel, true /* try_to_connect */); grpc_channel_check_connectivity_state(channel, true /* try_to_connect */);
// Use grpc_channel_get_info() to get LB policy name. // First, request no fields. This is a no-op.
char *lb_policy_name = NULL;
grpc_channel_info channel_info; grpc_channel_info channel_info;
memset(&channel_info, 0, sizeof(channel_info));
grpc_channel_get_info(channel, &channel_info);
// Request LB policy name.
char *lb_policy_name = NULL;
channel_info.lb_policy_name = &lb_policy_name; channel_info.lb_policy_name = &lb_policy_name;
grpc_channel_get_info(channel, &channel_info); grpc_channel_get_info(channel, &channel_info);
GPR_ASSERT(lb_policy_name != NULL); GPR_ASSERT(lb_policy_name != NULL);
GPR_ASSERT(strcmp(lb_policy_name, "round_robin") == 0); GPR_ASSERT(strcmp(lb_policy_name, "pick_first") == 0);
gpr_free(lb_policy_name); gpr_free(lb_policy_name);
// Try again without requesting anything. This is a no-op. // Request service config, which does not exist, so we'll get nothing back.
channel_info.lb_policy_name = NULL; memset(&channel_info, 0, sizeof(channel_info));
char *service_config_json = "dummy_string";
channel_info.service_config_json = &service_config_json;
grpc_channel_get_info(channel, &channel_info);
GPR_ASSERT(service_config_json == NULL);
// Recreate the channel such that it has a service config.
grpc_channel_destroy(channel);
grpc_arg arg;
arg.type = GRPC_ARG_STRING;
arg.key = GRPC_ARG_SERVICE_CONFIG;
arg.value.string = "{\"loadBalancingPolicy\": \"ROUND_ROBIN\"}";
grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1);
channel = grpc_insecure_channel_create("ipv4:127.0.0.1:1234", args, NULL);
{
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_channel_args_destroy(&exec_ctx, args);
grpc_exec_ctx_finish(&exec_ctx);
}
// Ensures that resolver returns.
grpc_channel_check_connectivity_state(channel, true /* try_to_connect */);
// Now request the service config again.
grpc_channel_get_info(channel, &channel_info); grpc_channel_get_info(channel, &channel_info);
GPR_ASSERT(service_config_json != NULL);
GPR_ASSERT(strcmp(service_config_json, arg.value.string) == 0);
gpr_free(service_config_json);
// Clean up. // Clean up.
grpc_channel_destroy(channel); grpc_channel_destroy(channel);
} }

@ -41,7 +41,7 @@
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/method_config.h" #include "src/core/lib/transport/service_config.h"
#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/cq_verifier.h"
#include "test/core/util/port.h" #include "test/core/util/port.h"
@ -75,21 +75,20 @@ static void run_test(bool wait_for_ready, bool use_service_config) {
/* if using service config, create channel args */ /* if using service config, create channel args */
grpc_channel_args *args = NULL; grpc_channel_args *args = NULL;
if (use_service_config) { if (use_service_config) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GPR_ASSERT(wait_for_ready); GPR_ASSERT(wait_for_ready);
grpc_method_config_table_entry entry = { grpc_arg arg;
grpc_mdstr_from_string("/service/method"), arg.type = GRPC_ARG_STRING;
grpc_method_config_create(&wait_for_ready, NULL, NULL, NULL), arg.key = GRPC_ARG_SERVICE_CONFIG;
}; arg.value.string =
grpc_method_config_table *method_config_table = "{\n"
grpc_method_config_table_create(1, &entry); " \"methodConfig\": [ {\n"
GRPC_MDSTR_UNREF(&exec_ctx, entry.method_name); " \"name\": [\n"
grpc_method_config_unref(&exec_ctx, entry.method_config); " { \"service\": \"service\", \"method\": \"method\" }\n"
grpc_arg arg = " ],\n"
grpc_method_config_table_create_channel_arg(method_config_table); " \"waitForReady\": true\n"
" } ]\n"
"}";
args = grpc_channel_args_copy_and_add(args, &arg, 1); args = grpc_channel_args_copy_and_add(args, &arg, 1);
grpc_method_config_table_unref(&exec_ctx, method_config_table);
grpc_exec_ctx_finish(&exec_ctx);
} }
/* create a call, channel to a port which will refuse connection */ /* create a call, channel to a port which will refuse connection */

@ -44,7 +44,7 @@
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/method_config.h" #include "src/core/lib/transport/service_config.h"
#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/tests/cancel_test_helpers.h" #include "test/core/end2end/tests/cancel_test_helpers.h"
@ -134,21 +134,19 @@ static void test_cancel_after_accept(grpc_end2end_test_config config,
grpc_channel_args *args = NULL; grpc_channel_args *args = NULL;
if (use_service_config) { if (use_service_config) {
gpr_timespec timeout = {5, 0, GPR_TIMESPAN}; grpc_arg arg;
grpc_method_config_table_entry entry = { arg.type = GRPC_ARG_STRING;
grpc_mdstr_from_string("/service/method"), arg.key = GRPC_ARG_SERVICE_CONFIG;
grpc_method_config_create(NULL, &timeout, NULL, NULL), arg.value.string =
}; "{\n"
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; " \"methodConfig\": [ {\n"
grpc_method_config_table *method_config_table = " \"name\": [\n"
grpc_method_config_table_create(1, &entry); " { \"service\": \"service\", \"method\": \"method\" }\n"
GRPC_MDSTR_UNREF(&exec_ctx, entry.method_name); " ],\n"
grpc_method_config_unref(&exec_ctx, entry.method_config); " \"timeout\": \"5s\"\n"
grpc_arg arg = " } ]\n"
grpc_method_config_table_create_channel_arg(method_config_table); "}";
args = grpc_channel_args_copy_and_add(args, &arg, 1); args = grpc_channel_args_copy_and_add(args, &arg, 1);
grpc_method_config_table_unref(&exec_ctx, method_config_table);
grpc_exec_ctx_finish(&exec_ctx);
} }
grpc_end2end_test_fixture f = grpc_end2end_test_fixture f =

@ -44,7 +44,7 @@
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/method_config.h" #include "src/core/lib/transport/service_config.h"
#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/cq_verifier.h"
@ -137,22 +137,20 @@ static void test_max_message_length_on_request(grpc_end2end_test_config config,
grpc_channel_args *server_args = NULL; grpc_channel_args *server_args = NULL;
if (use_service_config) { if (use_service_config) {
// We don't currently support service configs on the server side. // We don't currently support service configs on the server side.
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GPR_ASSERT(send_limit); GPR_ASSERT(send_limit);
int32_t max_request_message_bytes = 5; grpc_arg arg;
grpc_method_config_table_entry entry = { arg.type = GRPC_ARG_STRING;
grpc_mdstr_from_string("/service/method"), arg.key = GRPC_ARG_SERVICE_CONFIG;
grpc_method_config_create(NULL, NULL, &max_request_message_bytes, NULL), arg.value.string =
}; "{\n"
grpc_method_config_table *method_config_table = " \"methodConfig\": [ {\n"
grpc_method_config_table_create(1, &entry); " \"name\": [\n"
GRPC_MDSTR_UNREF(&exec_ctx, entry.method_name); " { \"service\": \"service\", \"method\": \"method\" }\n"
grpc_method_config_unref(&exec_ctx, entry.method_config); " ],\n"
grpc_arg arg = " \"maxRequestMessageBytes\": \"5\"\n"
grpc_method_config_table_create_channel_arg(method_config_table); " } ]\n"
"}";
client_args = grpc_channel_args_copy_and_add(NULL, &arg, 1); client_args = grpc_channel_args_copy_and_add(NULL, &arg, 1);
grpc_method_config_table_unref(&exec_ctx, method_config_table);
grpc_exec_ctx_finish(&exec_ctx);
} else { } else {
// Set limit via channel args. // Set limit via channel args.
grpc_arg arg; grpc_arg arg;
@ -317,23 +315,20 @@ static void test_max_message_length_on_response(grpc_end2end_test_config config,
grpc_channel_args *server_args = NULL; grpc_channel_args *server_args = NULL;
if (use_service_config) { if (use_service_config) {
// We don't currently support service configs on the server side. // We don't currently support service configs on the server side.
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GPR_ASSERT(!send_limit); GPR_ASSERT(!send_limit);
int32_t max_response_message_bytes = 5; grpc_arg arg;
grpc_method_config_table_entry entry = { arg.type = GRPC_ARG_STRING;
grpc_mdstr_from_string("/service/method"), arg.key = GRPC_ARG_SERVICE_CONFIG;
grpc_method_config_create(NULL, NULL, NULL, arg.value.string =
&max_response_message_bytes), "{\n"
}; " \"methodConfig\": [ {\n"
grpc_method_config_table *method_config_table = " \"name\": [\n"
grpc_method_config_table_create(1, &entry); " { \"service\": \"service\", \"method\": \"method\" }\n"
GRPC_MDSTR_UNREF(&exec_ctx, entry.method_name); " ],\n"
grpc_method_config_unref(&exec_ctx, entry.method_config); " \"maxResponseMessageBytes\": \"5\"\n"
grpc_arg arg = " } ]\n"
grpc_method_config_table_create_channel_arg(method_config_table); "}";
client_args = grpc_channel_args_copy_and_add(NULL, &arg, 1); client_args = grpc_channel_args_copy_and_add(NULL, &arg, 1);
grpc_method_config_table_unref(&exec_ctx, method_config_table);
grpc_exec_ctx_finish(&exec_ctx);
} else { } else {
// Set limit via channel args. // Set limit via channel args.
grpc_arg arg; grpc_arg arg;

@ -236,7 +236,11 @@ int main(int argc, char **argv) {
"strategy. and the current strategy is: '%s'", "strategy. and the current strategy is: '%s'",
poll_strategy); poll_strategy);
} }
grpc_iomgr_shutdown(); {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_iomgr_shutdown(&exec_ctx);
grpc_exec_ctx_finish(&exec_ctx);
}
return 0; return 0;
} }
#else /* defined(GRPC_LINUX_EPOLL) */ #else /* defined(GRPC_LINUX_EPOLL) */

@ -82,7 +82,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
grpc_resource_quota_create("ssl_server_fuzzer"); grpc_resource_quota_create("ssl_server_fuzzer");
grpc_endpoint *mock_endpoint = grpc_endpoint *mock_endpoint =
grpc_mock_endpoint_create(discard_write, resource_quota); grpc_mock_endpoint_create(discard_write, resource_quota);
grpc_resource_quota_internal_unref(&exec_ctx, resource_quota); grpc_resource_quota_unref_internal(&exec_ctx, resource_quota);
grpc_mock_endpoint_put_read( grpc_mock_endpoint_put_read(
&exec_ctx, mock_endpoint, &exec_ctx, mock_endpoint,
@ -106,7 +106,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Create security connector // Create security connector
grpc_server_security_connector *sc = NULL; grpc_server_security_connector *sc = NULL;
grpc_security_status status = grpc_security_status status =
grpc_server_credentials_create_security_connector(creds, &sc); grpc_server_credentials_create_security_connector(&exec_ctx, creds, &sc);
GPR_ASSERT(status == GRPC_SECURITY_OK); GPR_ASSERT(status == GRPC_SECURITY_OK);
sc->channel_args = NULL; sc->channel_args = NULL;
gpr_timespec deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), gpr_timespec deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
@ -129,7 +129,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
GPR_ASSERT(state.done_callback_called); GPR_ASSERT(state.done_callback_called);
GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "test"); GRPC_SECURITY_CONNECTOR_UNREF(&exec_ctx, &sc->base, "test");
grpc_server_credentials_release(creds); grpc_server_credentials_release(creds);
grpc_slice_unref(cert_slice); grpc_slice_unref(cert_slice);
grpc_slice_unref(key_slice); grpc_slice_unref(key_slice);

@ -109,9 +109,9 @@ class RoundRobinEnd2endTest : public ::testing::Test {
uri << "127.0.0.1:" << servers_[i]->port_ << ","; uri << "127.0.0.1:" << servers_[i]->port_ << ",";
} }
uri << "127.0.0.1:" << servers_[servers_.size() - 1]->port_; uri << "127.0.0.1:" << servers_[servers_.size() - 1]->port_;
std::shared_ptr<Channel> channel = channel_ =
CreateCustomChannel(uri.str(), InsecureChannelCredentials(), args); CreateCustomChannel(uri.str(), InsecureChannelCredentials(), args);
stub_ = grpc::testing::EchoTestService::NewStub(channel); stub_ = grpc::testing::EchoTestService::NewStub(channel_);
} }
void SendRpc(int num_rpcs) { void SendRpc(int num_rpcs) {
@ -165,6 +165,7 @@ class RoundRobinEnd2endTest : public ::testing::Test {
const grpc::string server_host_; const grpc::string server_host_;
CompletionQueue cli_cq_; CompletionQueue cli_cq_;
std::shared_ptr<Channel> channel_;
std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_; std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
std::vector<std::unique_ptr<ServerData>> servers_; std::vector<std::unique_ptr<ServerData>> servers_;
}; };
@ -186,6 +187,8 @@ TEST_F(RoundRobinEnd2endTest, PickFirst) {
} }
} }
EXPECT_TRUE(found); EXPECT_TRUE(found);
// Check LB policy name for the channel.
EXPECT_EQ("pick_first", channel_->GetLoadBalancingPolicyName());
} }
TEST_F(RoundRobinEnd2endTest, RoundRobin) { TEST_F(RoundRobinEnd2endTest, RoundRobin) {
@ -198,6 +201,8 @@ TEST_F(RoundRobinEnd2endTest, RoundRobin) {
for (size_t i = 0; i < servers_.size(); ++i) { for (size_t i = 0; i < servers_.size(); ++i) {
EXPECT_EQ(1, servers_[i]->service_.request_count()); EXPECT_EQ(1, servers_[i]->service_.request_count());
} }
// Check LB policy name for the channel.
EXPECT_EQ("round_robin", channel_->GetLoadBalancingPolicyName());
} }
} // namespace } // namespace

@ -108,6 +108,7 @@ typedef struct server_fixture {
grpc_completion_queue *cq; grpc_completion_queue *cq;
char *servers_hostport; char *servers_hostport;
int port; int port;
const char *lb_token_prefix;
gpr_thd_id tid; gpr_thd_id tid;
int num_calls_serviced; int num_calls_serviced;
} server_fixture; } server_fixture;
@ -123,7 +124,8 @@ static void *tag(intptr_t t) { return (void *)t; }
static grpc_slice build_response_payload_slice( static grpc_slice build_response_payload_slice(
const char *host, int *ports, size_t nports, const char *host, int *ports, size_t nports,
int64_t expiration_interval_secs, int32_t expiration_interval_nanos) { int64_t expiration_interval_secs, int32_t expiration_interval_nanos,
const char *token_prefix) {
// server_list { // server_list {
// servers { // servers {
// ip_address: <in_addr/6 bytes of an IP> // ip_address: <in_addr/6 bytes of an IP>
@ -150,15 +152,15 @@ static grpc_slice build_response_payload_slice(
struct in_addr ip4; struct in_addr ip4;
GPR_ASSERT(inet_pton(AF_INET, host, &ip4) == 1); GPR_ASSERT(inet_pton(AF_INET, host, &ip4) == 1);
server->set_ip_address( server->set_ip_address(
grpc::string(reinterpret_cast<const char *>(&ip4), sizeof(ip4))); string(reinterpret_cast<const char *>(&ip4), sizeof(ip4)));
server->set_port(ports[i]); server->set_port(ports[i]);
// The following long long int cast is meant to work around the // Missing tokens are acceptable. Test that path.
// disfunctional implementation of std::to_string in gcc 4.4, which doesn't if (strlen(token_prefix) > 0) {
// have a version for int but does have one for long long int. string token_data = token_prefix + std::to_string(ports[i]);
string token_data = "token" + std::to_string((long long int)ports[i]);
server->set_load_balance_token(token_data); server->set_load_balance_token(token_data);
} }
const grpc::string &enc_resp = response.SerializeAsString(); }
const string &enc_resp = response.SerializeAsString();
return grpc_slice_from_copied_buffer(enc_resp.data(), enc_resp.size()); return grpc_slice_from_copied_buffer(enc_resp.data(), enc_resp.size());
} }
@ -250,14 +252,14 @@ static void start_lb_server(server_fixture *sf, int *ports, size_t nports,
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
if (i == 0) { if (i == 0) {
// First half of the ports. // First half of the ports.
response_payload_slice = response_payload_slice = build_response_payload_slice(
build_response_payload_slice("127.0.0.1", ports, nports / 2, -1, -1); "127.0.0.1", ports, nports / 2, -1, -1, sf->lb_token_prefix);
} else { } else {
// Second half of the ports. // Second half of the ports.
sleep_ms(update_delay_ms); sleep_ms(update_delay_ms);
response_payload_slice = response_payload_slice = build_response_payload_slice(
build_response_payload_slice("127.0.0.1", ports + (nports / 2), "127.0.0.1", ports + (nports / 2), (nports + 1) / 2 /* ceil */, -1,
(nports + 1) / 2 /* ceil */, -1, -1); -1, "" /* this half doesn't get to receive an LB token */);
} }
response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1);
@ -339,11 +341,10 @@ static void start_backend_server(server_fixture *sf) {
return; return;
} }
GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
const string expected_token =
// The following long long int cast is meant to work around the strlen(sf->lb_token_prefix) == 0
// disfunctional implementation of std::to_string in gcc 4.4, which doesn't ? ""
// have a version for int but does have one for long long int. : sf->lb_token_prefix + std::to_string(sf->port);
string expected_token = "token" + std::to_string((long long int)sf->port);
GPR_ASSERT(contains_metadata(&request_metadata_recv, "lb-token", GPR_ASSERT(contains_metadata(&request_metadata_recv, "lb-token",
expected_token.c_str())); expected_token.c_str()));
@ -626,6 +627,7 @@ static void fork_lb_server(void *arg) {
tf->lb_server_update_delay_ms); tf->lb_server_update_delay_ms);
} }
#define LB_TOKEN_PREFIX "token"
static test_fixture setup_test_fixture(int lb_server_update_delay_ms) { static test_fixture setup_test_fixture(int lb_server_update_delay_ms) {
test_fixture tf; test_fixture tf;
memset(&tf, 0, sizeof(tf)); memset(&tf, 0, sizeof(tf));
@ -635,11 +637,18 @@ static test_fixture setup_test_fixture(int lb_server_update_delay_ms) {
gpr_thd_options_set_joinable(&options); gpr_thd_options_set_joinable(&options);
for (int i = 0; i < NUM_BACKENDS; ++i) { for (int i = 0; i < NUM_BACKENDS; ++i) {
// Only the first half of the servers expect an LB token.
if (i < NUM_BACKENDS / 2) {
tf.lb_backends[i].lb_token_prefix = LB_TOKEN_PREFIX;
} else {
tf.lb_backends[i].lb_token_prefix = "";
}
setup_server("127.0.0.1", &tf.lb_backends[i]); setup_server("127.0.0.1", &tf.lb_backends[i]);
gpr_thd_new(&tf.lb_backends[i].tid, fork_backend_server, &tf.lb_backends[i], gpr_thd_new(&tf.lb_backends[i].tid, fork_backend_server, &tf.lb_backends[i],
&options); &options);
} }
tf.lb_server.lb_token_prefix = LB_TOKEN_PREFIX;
setup_server("127.0.0.1", &tf.lb_server); setup_server("127.0.0.1", &tf.lb_server);
gpr_thd_new(&tf.lb_server.tid, fork_lb_server, &tf.lb_server, &options); gpr_thd_new(&tf.lb_server.tid, fork_lb_server, &tf.lb_server, &options);

@ -880,8 +880,8 @@ src/core/lib/transport/connectivity_state.h \
src/core/lib/transport/mdstr_hash_table.h \ src/core/lib/transport/mdstr_hash_table.h \
src/core/lib/transport/metadata.h \ src/core/lib/transport/metadata.h \
src/core/lib/transport/metadata_batch.h \ src/core/lib/transport/metadata_batch.h \
src/core/lib/transport/method_config.h \
src/core/lib/transport/pid_controller.h \ src/core/lib/transport/pid_controller.h \
src/core/lib/transport/service_config.h \
src/core/lib/transport/static_metadata.h \ src/core/lib/transport/static_metadata.h \
src/core/lib/transport/timeout_encoding.h \ src/core/lib/transport/timeout_encoding.h \
src/core/lib/transport/transport.h \ src/core/lib/transport/transport.h \
@ -1073,8 +1073,8 @@ src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \

@ -41,8 +41,12 @@ tools/run_tests/run_performance_tests.py \
--category scalable \ --category scalable \
--bq_result_table performance_test.performance_experiment \ --bq_result_table performance_test.performance_experiment \
--remote_worker_host grpc-performance-server-8core grpc-performance-client-8core grpc-performance-client2-8core \ --remote_worker_host grpc-performance-server-8core grpc-performance-client-8core grpc-performance-client2-8core \
--xml_report report_8core.xml \
|| EXIT_CODE=1 || EXIT_CODE=1
# prevent pushing leftover build files to remote hosts in the next step.
git clean -fdxq --exclude='report*.xml'
# scalability with 32cores (and upload to a different BQ table) # scalability with 32cores (and upload to a different BQ table)
tools/run_tests/run_performance_tests.py \ tools/run_tests/run_performance_tests.py \
-l c++ java csharp go \ -l c++ java csharp go \
@ -50,6 +54,19 @@ tools/run_tests/run_performance_tests.py \
--category scalable \ --category scalable \
--bq_result_table performance_test.performance_experiment_32core \ --bq_result_table performance_test.performance_experiment_32core \
--remote_worker_host grpc-performance-server-32core grpc-performance-client-32core grpc-performance-client2-32core \ --remote_worker_host grpc-performance-server-32core grpc-performance-client-32core grpc-performance-client2-32core \
--xml_report report_32core.xml \
|| EXIT_CODE=1
# prevent pushing leftover build files to remote hosts in the next step.
git clean -fdxq --exclude='report*.xml'
# selected scenarios on Windows
tools/run_tests/run_performance_tests.py \
-l csharp \
--category scalable \
--bq_result_table performance_test.performance_experiment_windows \
--remote_worker_host grpc-performance-windows1 grpc-performance-windows2 \
--xml_report report_windows.xml \
|| EXIT_CODE=1 || EXIT_CODE=1
exit $EXIT_CODE exit $EXIT_CODE

@ -37,10 +37,14 @@ CONFIG=${CONFIG:-opt}
# build C++ qps worker & driver always - we need at least the driver to # build C++ qps worker & driver always - we need at least the driver to
# run any of the scenarios. # run any of the scenarios.
# TODO(jtattermusch): C++ worker and driver are not buildable on Windows yet
if [ "$OSTYPE" != "msys" ]
then
# TODO(jtattermusch): not embedding OpenSSL breaks the C# build because # TODO(jtattermusch): not embedding OpenSSL breaks the C# build because
# grpc_csharp_ext needs OpenSSL embedded and some intermediate files from # grpc_csharp_ext needs OpenSSL embedded and some intermediate files from
# this build will be reused. # this build will be reused.
make CONFIG=${CONFIG} EMBED_OPENSSL=true EMBED_ZLIB=true qps_worker qps_json_driver -j8 make CONFIG=${CONFIG} EMBED_OPENSSL=true EMBED_ZLIB=true qps_worker qps_json_driver -j8
fi
for language in $@ for language in $@
do do
@ -55,10 +59,10 @@ do
tools/run_tests/performance/build_performance_go.sh tools/run_tests/performance/build_performance_go.sh
;; ;;
"csharp") "csharp")
tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8 --compiler coreclr python tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8 --compiler coreclr
;; ;;
*) *)
tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8 python tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8
;; ;;
esac esac
done done

@ -32,18 +32,23 @@ set -ex
cd $(dirname $0)/../../.. cd $(dirname $0)/../../..
# cleanup after previous builds
ssh "${USER_AT_HOST}" "rm -rf ~/performance_workspace && mkdir -p ~/performance_workspace"
# TODO(jtattermusch): To be sure there are no running processes that would # TODO(jtattermusch): To be sure there are no running processes that would
# mess with the results, be rough and reboot the slave here # mess with the results, be rough and reboot the slave here
# and wait for it to come back online. # and wait for it to come back online.
# could also kill jenkins. ssh "${USER_AT_HOST}" "killall -9 qps_worker dotnet mono node ruby worker || true"
ssh "${USER_AT_HOST}" "killall -9 qps_worker mono node ruby worker || true"
# On Windows, killall is not supported & we need to kill all pending workers
# before attempting to delete the workspace
ssh "${USER_AT_HOST}" "ps -e | egrep 'qps_worker|dotnet' | awk '{print $1}' | xargs kill -9 || true"
# cleanup after previous builds
ssh "${USER_AT_HOST}" "rm -rf ~/performance_workspace && mkdir -p ~/performance_workspace"
# push the current sources to the slave and unpack it. # push the current sources to the slave and unpack it.
scp ../grpc.tar "${USER_AT_HOST}:~/performance_workspace" scp ../grpc.tar "${USER_AT_HOST}:~/performance_workspace"
ssh "${USER_AT_HOST}" "tar -xf ~/performance_workspace/grpc.tar -C ~/performance_workspace" # Windows workaround: attempt to untar twice, first run is going to fail
# with symlink creation error(s).
ssh "${USER_AT_HOST}" "tar -xf ~/performance_workspace/grpc.tar -C ~/performance_workspace || tar -xf ~/performance_workspace/grpc.tar -C ~/performance_workspace"
# For consistency with local run, invoke the kill_workers script remotely. # For consistency with local run, invoke the kill_workers script remotely.
ssh "${USER_AT_HOST}" "~/performance_workspace/grpc/tools/run_tests/performance/kill_workers.sh" ssh "${USER_AT_HOST}" "~/performance_workspace/grpc/tools/run_tests/performance/kill_workers.sh"

@ -403,6 +403,8 @@ argp.add_argument('--netperf',
action='store_const', action='store_const',
const=True, const=True,
help='Run netperf benchmark as one of the scenarios.') help='Run netperf benchmark as one of the scenarios.')
argp.add_argument('-x', '--xml_report', default='report.xml', type=str,
help='Name of XML report file to generate.')
args = argp.parse_args() args = argp.parse_args()
@ -473,7 +475,7 @@ for scenario in scenarios:
qps_workers_killed += finish_qps_workers(scenario.workers) qps_workers_killed += finish_qps_workers(scenario.workers)
report_utils.render_junit_xml_report(merged_resultset, 'report.xml', report_utils.render_junit_xml_report(merged_resultset, args.xml_report,
suite_name='benchmarks') suite_name='benchmarks')
if total_scenario_failures > 0 or qps_workers_killed > 0: if total_scenario_failures > 0 or qps_workers_killed > 0:

@ -6763,8 +6763,8 @@
"src/core/lib/transport/mdstr_hash_table.h", "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h", "src/core/lib/transport/transport.h",
@ -6980,10 +6980,10 @@
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.c", "src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/metadata_batch.h", "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/pid_controller.c", "src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.c", "src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.c", "src/core/lib/transport/timeout_encoding.c",

@ -389,8 +389,8 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" /> <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.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.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\pid_controller.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.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\timeout_encoding.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
@ -691,10 +691,10 @@
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\service_config.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">

@ -322,10 +322,10 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\service_config.c">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
@ -1004,10 +1004,10 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">

@ -282,8 +282,8 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" /> <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.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.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\pid_controller.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.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\timeout_encoding.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
@ -542,10 +542,10 @@
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\service_config.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">

@ -379,10 +379,10 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\service_config.c">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
@ -800,10 +800,10 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">

@ -379,8 +379,8 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\mdstr_hash_table.h" /> <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.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.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\pid_controller.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.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\timeout_encoding.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" />
@ -659,10 +659,10 @@
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\service_config.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.c">

@ -325,10 +325,10 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\service_config.c">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c"> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
@ -917,10 +917,10 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\service_config.h">
<Filter>src\core\lib\transport</Filter> <Filter>src\core\lib\transport</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h"> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">

Loading…
Cancel
Save