Merge branch 'slice_with_exec_ctx' into eliminate_mdstr

reviewable/pr8842/r1
Craig Tiller 8 years ago
commit ac5f518016
  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. 8
      src/core/ext/client_channel/lb_policy_registry.c
  15. 43
      src/core/ext/lb_policy/grpclb/grpclb.c
  16. 16
      src/core/ext/load_reporting/load_reporting_filter.c
  17. 4
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  18. 65
      src/core/ext/transport/chttp2/transport/hpack_encoder.c
  19. 42
      src/core/ext/transport/chttp2/transport/hpack_parser.c
  20. 20
      src/core/ext/transport/chttp2/transport/hpack_table.c
  21. 26
      src/core/ext/transport/chttp2/transport/parsing.c
  22. 60
      src/core/lib/channel/message_size_filter.c
  23. 6
      src/core/lib/json/json.c
  24. 22
      src/core/lib/json/json.h
  25. 8
      src/core/lib/security/transport/client_auth_filter.c
  26. 10
      src/core/lib/security/transport/server_auth_filter.c
  27. 44
      src/core/lib/slice/slice_hash_table.c
  28. 19
      src/core/lib/slice/slice_hash_table.h
  29. 9
      src/core/lib/support/string.c
  30. 3
      src/core/lib/support/string.h
  31. 254
      src/core/lib/transport/service_config.c
  32. 71
      src/core/lib/transport/service_config.h
  33. 6
      src/core/lib/transport/transport_op_string.c
  34. 30
      src/cpp/client/channel_cc.cc
  35. 5
      src/cpp/common/channel_arguments.cc
  36. 2
      src/python/grpcio/grpc_core_dependencies.py
  37. 8
      src/python/grpcio_tests/tests/interop/client.py
  38. 49
      test/core/client_channel/lb_policies_test.c
  39. 27
      test/core/end2end/connection_refused_test.c
  40. 28
      test/core/end2end/tests/cancel_after_accept.c
  41. 55
      test/core/end2end/tests/max_message_length.c
  42. 9
      test/cpp/end2end/round_robin_end2end_test.cc
  43. 45
      test/cpp/grpclb/grpclb_test.cc
  44. 4
      tools/doxygen/Doxyfile.core.internal
  45. 17
      tools/jenkins/run_full_performance.sh
  46. 16
      tools/run_tests/performance/build_performance.sh
  47. 17
      tools/run_tests/performance/remote_host_prepare.sh
  48. 4
      tools/run_tests/run_performance_tests.py
  49. 6
      tools/run_tests/sources_and_headers.json
  50. 6
      vsprojects/vcxproj/grpc/grpc.vcxproj
  51. 8
      vsprojects/vcxproj/grpc/grpc.vcxproj.filters
  52. 6
      vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
  53. 8
      vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
  54. 6
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
  55. 8
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters

16
BUILD

@ -248,8 +248,8 @@ cc_library(
"src/core/lib/transport/connectivity_state.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h",
@ -438,8 +438,8 @@ cc_library(
"src/core/lib/transport/connectivity_state.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c",
@ -684,8 +684,8 @@ cc_library(
"src/core/lib/transport/connectivity_state.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h",
@ -859,8 +859,8 @@ cc_library(
"src/core/lib/transport/connectivity_state.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c",
@ -1075,8 +1075,8 @@ cc_library(
"src/core/lib/transport/connectivity_state.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h",
@ -1242,8 +1242,8 @@ cc_library(
"src/core/lib/transport/connectivity_state.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c",
@ -2109,8 +2109,8 @@ objc_library(
"src/core/lib/transport/connectivity_state.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c",
@ -2334,8 +2334,8 @@ objc_library(
"src/core/lib/transport/connectivity_state.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h",

@ -393,8 +393,8 @@ add_library(grpc
src/core/lib/transport/connectivity_state.c
src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c
@ -674,8 +674,8 @@ add_library(grpc_cronet
src/core/lib/transport/connectivity_state.c
src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c
@ -927,8 +927,8 @@ add_library(grpc_unsecure
src/core/lib/transport/connectivity_state.c
src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c

@ -2732,8 +2732,8 @@ LIBGRPC_SRC = \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \
@ -3031,8 +3031,8 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \
@ -3321,8 +3321,8 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \
@ -3540,8 +3540,8 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \

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

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

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

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

@ -258,8 +258,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/connectivity_state.h )
s.files += %w( src/core/lib/transport/metadata.h )
s.files += %w( src/core/lib/transport/metadata_batch.h )
s.files += %w( src/core/lib/transport/method_config.h )
s.files += %w( src/core/lib/transport/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/timeout_encoding.h )
s.files += %w( src/core/lib/transport/transport.h )
@ -452,8 +452,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/connectivity_state.c )
s.files += %w( src/core/lib/transport/metadata.c )
s.files += %w( src/core/lib/transport/metadata_batch.c )
s.files += %w( src/core/lib/transport/method_config.c )
s.files += %w( src/core/lib/transport/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/timeout_encoding.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.
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:
template <class InputMessage, class OutputMessage>
friend Status BlockingUnaryCall(ChannelInterface* channel,

@ -93,6 +93,10 @@ class ChannelArguments {
/// grpclb LB policy will be used, regardless of what is specified here.
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.
/// Set an integer argument \a value under \a key.
void SetInt(const grpc::string& key, int value);

@ -457,6 +457,9 @@ typedef struct {
/* If non-NULL, will be set to point to a string indicating the LB
* policy name. Caller takes ownership. */
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;
typedef struct grpc_resource_quota grpc_resource_quota;

@ -265,8 +265,8 @@
<file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/method_config.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/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/timeout_encoding.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/transport.h" role="src" />
@ -459,8 +459,8 @@
<file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/method_config.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/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/timeout_encoding.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/transport.c" role="src" />

@ -57,7 +57,7 @@
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/method_config.h"
#include "src/core/lib/transport/service_config.h"
#include "src/core/lib/transport/static_metadata.h"
/* Client channel implementation */
@ -83,34 +83,65 @@ static void *method_parameters_copy(void *value) {
return new_value;
}
static int method_parameters_cmp(void *value1, void *value2) {
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) {
static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *p) {
gpr_free(p);
}
static const grpc_slice_hash_table_vtable method_parameters_vtable = {
method_parameters_del, method_parameters_copy, method_parameters_cmp};
static void *method_config_convert_value(
const grpc_method_config *method_config) {
method_parameters_free, method_parameters_copy};
static void *method_parameters_create_from_json(const grpc_json *json) {
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));
const gpr_timespec *timeout = grpc_method_config_get_timeout(method_config);
value->timeout = timeout != NULL ? *timeout : gpr_time_0(GPR_TIMESPAN);
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);
value->timeout = timeout;
value->wait_for_ready = wait_for_ready;
return value;
}
@ -131,6 +162,8 @@ typedef struct client_channel_channel_data {
/** currently active load balancer */
char *lb_policy_name;
grpc_lb_policy *lb_policy;
/** service config in JSON form */
char *service_config_json;
/** maps method names to method_parameters structs */
grpc_slice_hash_table *method_params_table;
/** incoming resolver result - set by resolver.next() */
@ -237,15 +270,12 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
bool exit_idle = false;
grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
char *service_config_json = 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.
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) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
lb_policy_name = channel_arg->value.string;
@ -254,7 +284,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
// resolver actually specified.
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) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
@ -279,7 +309,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
// above.
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 =
grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
if (lb_policy != NULL) {
@ -288,13 +321,20 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
state =
grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
}
// Find service config.
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) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
method_params_table = grpc_method_config_table_convert(
exec_ctx, (grpc_method_config_table *)channel_arg->value.pointer.p,
method_config_convert_value, &method_parameters_vtable);
GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
service_config_json = gpr_strdup(channel_arg->value.string);
grpc_service_config *service_config =
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
// be pointing to data inside chand->resolver_result.
@ -316,6 +356,10 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
}
old_lb_policy = chand->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) {
grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
}
@ -451,6 +495,11 @@ static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
? NULL
: 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);
}
@ -494,6 +543,7 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
}
gpr_free(chand->lb_policy_name);
gpr_free(chand->service_config_json);
if (chand->method_params_table != NULL) {
grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
}

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

@ -137,7 +137,7 @@ static void initial_metadata_add_lb_token(
grpc_metadata_batch *initial_metadata,
grpc_linked_mdelem *lb_token_mdelem_storage, grpc_mdelem lb_token) {
GPR_ASSERT(lb_token_mdelem_storage != NULL);
GPR_ASSERT(lb_token != NULL);
GPR_ASSERT(!GRPC_MDISNULL(lb_token));
grpc_metadata_batch_add_tail(initial_metadata, lb_token_mdelem_storage,
lb_token);
}
@ -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
* available */
if (wc_arg->target != NULL) {
GPR_ASSERT(wc_arg->lb_token != NULL);
initial_metadata_add_lb_token(wc_arg->initial_metadata,
wc_arg->lb_token_mdelem_storage,
GRPC_MDELEM_REF(wc_arg->lb_token));
if (!GRPC_MDISNULL(wc_arg->lb_token)) {
initial_metadata_add_lb_token(wc_arg->initial_metadata,
wc_arg->lb_token_mdelem_storage,
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) {
gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")",
(intptr_t)wc_arg->rr_policy);
gpr_log(GPR_INFO, "Unreffing RR %p", (void *)wc_arg->rr_policy);
}
GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure");
}
@ -375,10 +381,10 @@ static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
/* vtable for LB tokens in grpc_lb_addresses. */
static void *lb_token_copy(void *token) {
return token == NULL ? NULL : GRPC_MDELEM_REF(token);
return token == NULL ? NULL : GRPC_MDELEM_REF((grpc_mdelem){token}).payload;
}
static void lb_token_destroy(grpc_exec_ctx *exec_ctx, void *token) {
if (token != NULL) GRPC_MDELEM_UNREF(exec_ctx, token);
if (token != NULL) GRPC_MDELEM_UNREF(exec_ctx, (grpc_mdelem){token});
}
static int lb_token_cmp(void *token1, void *token2) {
if (token1 > token2) return 1;
@ -411,7 +417,7 @@ static void parse_server(const grpc_grpclb_server *server,
}
/* 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) {
size_t num_valid = 0;
/* first pass: count how many are valid in order to allocate the necessary
@ -448,14 +454,17 @@ static grpc_lb_addresses *process_serverlist(
strnlen(server->load_balance_token, lb_token_max_length);
grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer(
server->load_balance_token, lb_token_length);
user_data = grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_LB_TOKEN,
lb_token_mdstr);
user_data =
grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_LB_TOKEN, lb_token_mdstr)
.payload;
} 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 "
"be used instead",
grpc_sockaddr_to_uri(&addr));
user_data = GRPC_MDELEM_LB_TOKEN_EMPTY;
uri);
gpr_free(uri);
user_data = GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
}
grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
@ -508,7 +517,8 @@ static grpc_lb_policy *create_rr_locked(
grpc_lb_policy_args args;
memset(&args, 0, sizeof(args));
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
// the subchannel.
@ -768,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
* the cancel, needs to acquire that same lock */
grpc_call *lb_call = glb_policy->lb_call;
glb_policy->lb_call = NULL;
gpr_mu_unlock(&glb_policy->mu);
/* glb_policy->lb_call and this local lb_call must be consistent at this point

@ -78,13 +78,13 @@ static grpc_mdelem recv_md_filter(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_call_element *elem = a->elem;
call_data *calld = elem->call_data;
if (grpc_slice_cmp(md->key, GRPC_MDSTR_PATH) == 0) {
calld->service_method = grpc_slice_ref_internal(md->value);
if (grpc_slice_cmp(GRPC_MDKEY(md), GRPC_MDSTR_PATH) == 0) {
calld->service_method = grpc_slice_ref_internal(GRPC_MDVALUE(md));
calld->have_service_method = true;
} else if (grpc_slice_cmp(md->key, GRPC_MDSTR_LB_TOKEN) == 0) {
calld->initial_md_string = grpc_slice_ref_internal(md->value);
} else if (grpc_slice_cmp(GRPC_MDKEY(md), GRPC_MDSTR_LB_TOKEN) == 0) {
calld->initial_md_string = grpc_slice_ref_internal(GRPC_MDVALUE(md));
calld->have_initial_md_string = true;
return NULL;
return GRPC_MDNULL;
}
return md;
@ -201,10 +201,10 @@ static grpc_mdelem lr_trailing_md_filter(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
if (grpc_slice_cmp(md->key, GRPC_MDSTR_LB_COST_BIN) == 0) {
calld->trailing_md_string = grpc_slice_ref_internal(md->value);
if (grpc_slice_cmp(GRPC_MDKEY(md), GRPC_MDSTR_LB_COST_BIN) == 0) {
calld->trailing_md_string = grpc_slice_ref_internal(GRPC_MDVALUE(md));
calld->have_trailing_md_string = true;
return NULL;
return GRPC_MDNULL;
}
return md;

@ -876,8 +876,8 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
static bool contains_non_ok_status(grpc_metadata_batch *batch) {
grpc_linked_mdelem *l;
for (l = batch->list.head; l; l = l->next) {
if (grpc_slice_cmp(l->md->key, GRPC_MDSTR_GRPC_STATUS) == 0 &&
l->md != GRPC_MDELEM_GRPC_STATUS_0) {
if (grpc_slice_cmp(GRPC_MDKEY(l->md), GRPC_MDSTR_GRPC_STATUS) == 0 &&
!grpc_mdelem_eq(l->md, GRPC_MDELEM_GRPC_STATUS_0)) {
return true;
}
}

@ -190,8 +190,8 @@ static void evict_entry(grpc_chttp2_hpack_compressor *c) {
/* add an element to the decoder table */
static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
grpc_mdelem elem) {
uint32_t key_hash = grpc_slice_hash(elem->key);
uint32_t value_hash = grpc_slice_hash(elem->value);
uint32_t key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
uint32_t value_hash = grpc_slice_hash(GRPC_MDVALUE(elem));
uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash);
uint32_t new_index = c->tail_remote_index + c->table_elems + 1;
size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
@ -217,17 +217,18 @@ static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
c->table_elems++;
/* Store this element into {entries,indices}_elem */
if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == elem) {
if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem)) {
/* already there: update with new index */
c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
} else if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == elem) {
} else if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)],
elem)) {
/* already there (cuckoo): update with new index */
c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
} else if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == NULL) {
} else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_2(elem_hash)])) {
/* not there, but a free element: add */
c->entries_elems[HASH_FRAGMENT_2(elem_hash)] = GRPC_MDELEM_REF(elem);
c->indices_elems[HASH_FRAGMENT_2(elem_hash)] = new_index;
} else if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == NULL) {
} else if (GRPC_MDISNULL(c->entries_elems[HASH_FRAGMENT_3(elem_hash)])) {
/* not there (cuckoo), but a free element: add */
c->entries_elems[HASH_FRAGMENT_3(elem_hash)] = GRPC_MDELEM_REF(elem);
c->indices_elems[HASH_FRAGMENT_3(elem_hash)] = new_index;
@ -246,34 +247,34 @@ static void add_elem(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
/* do exactly the same for the key (so we can find by that again too) */
if (grpc_slice_cmp(c->entries_keys[HASH_FRAGMENT_2(key_hash)], elem->key) ==
0) {
if (grpc_slice_cmp(c->entries_keys[HASH_FRAGMENT_2(key_hash)],
GRPC_MDKEY(elem)) == 0) {
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
} else if (grpc_slice_cmp(c->entries_keys[HASH_FRAGMENT_3(key_hash)],
elem->key) == 0) {
GRPC_MDKEY(elem)) == 0) {
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
} else if (c->entries_keys[HASH_FRAGMENT_2(key_hash)].refcount ==
&terminal_slice_refcount) {
c->entries_keys[HASH_FRAGMENT_2(key_hash)] =
grpc_slice_ref_internal(elem->key);
grpc_slice_ref_internal(GRPC_MDKEY(elem));
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
} else if (c->entries_keys[HASH_FRAGMENT_3(key_hash)].refcount ==
&terminal_slice_refcount) {
c->entries_keys[HASH_FRAGMENT_3(key_hash)] =
grpc_slice_ref_internal(elem->key);
grpc_slice_ref_internal(GRPC_MDKEY(elem));
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
} else if (c->indices_keys[HASH_FRAGMENT_2(key_hash)] <
c->indices_keys[HASH_FRAGMENT_3(key_hash)]) {
grpc_slice_unref_internal(exec_ctx,
c->entries_keys[HASH_FRAGMENT_2(key_hash)]);
c->entries_keys[HASH_FRAGMENT_2(key_hash)] =
grpc_slice_ref_internal(elem->key);
grpc_slice_ref_internal(GRPC_MDKEY(elem));
c->indices_keys[HASH_FRAGMENT_2(key_hash)] = new_index;
} else {
grpc_slice_unref_internal(exec_ctx,
c->entries_keys[HASH_FRAGMENT_3(key_hash)]);
c->entries_keys[HASH_FRAGMENT_3(key_hash)] =
grpc_slice_ref_internal(elem->key);
grpc_slice_ref_internal(GRPC_MDKEY(elem));
c->indices_keys[HASH_FRAGMENT_3(key_hash)] = new_index;
}
}
@ -286,13 +287,13 @@ static void emit_indexed(grpc_chttp2_hpack_compressor *c, uint32_t elem_index,
}
static grpc_slice get_wire_value(grpc_mdelem elem, uint8_t *huffman_prefix) {
if (grpc_is_binary_header(elem->key)) {
if (grpc_is_binary_header(GRPC_MDKEY(elem))) {
*huffman_prefix = 0x80;
return grpc_chttp2_base64_encode_and_huffman_compress(elem->value);
return grpc_chttp2_base64_encode_and_huffman_compress(GRPC_MDVALUE(elem));
}
/* TODO(ctiller): opportunistically compress non-binary headers */
*huffman_prefix = 0x00;
return grpc_slice_ref(elem->value);
return grpc_slice_ref(GRPC_MDVALUE(elem));
}
static void emit_lithdr_incidx(grpc_chttp2_hpack_compressor *c,
@ -331,7 +332,7 @@ static void emit_lithdr_noidx(grpc_chttp2_hpack_compressor *c,
static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
grpc_mdelem elem, framer_state *st) {
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(elem->key);
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
uint8_t huffman_prefix;
grpc_slice value_slice = get_wire_value(elem, &huffman_prefix);
uint32_t len_val = (uint32_t)GRPC_SLICE_LENGTH(value_slice);
@ -342,7 +343,7 @@ static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
*add_tiny_header_data(st, 1) = 0x40;
GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
add_tiny_header_data(st, len_key_len), len_key_len);
add_header_data(st, grpc_slice_ref_internal(elem->key));
add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem)));
GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len);
add_header_data(st, value_slice);
@ -350,7 +351,7 @@ static void emit_lithdr_incidx_v(grpc_chttp2_hpack_compressor *c,
static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
grpc_mdelem elem, framer_state *st) {
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(elem->key);
uint32_t len_key = (uint32_t)GRPC_SLICE_LENGTH(GRPC_MDKEY(elem));
uint8_t huffman_prefix;
grpc_slice value_slice = get_wire_value(elem, &huffman_prefix);
uint32_t len_val = (uint32_t)GRPC_SLICE_LENGTH(value_slice);
@ -361,7 +362,7 @@ static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
*add_tiny_header_data(st, 1) = 0x00;
GRPC_CHTTP2_WRITE_VARINT(len_key, 1, 0x00,
add_tiny_header_data(st, len_key_len), len_key_len);
add_header_data(st, grpc_slice_ref_internal(elem->key));
add_header_data(st, grpc_slice_ref_internal(GRPC_MDKEY(elem)));
GRPC_CHTTP2_WRITE_VARINT(len_val, 1, huffman_prefix,
add_tiny_header_data(st, len_val_len), len_val_len);
add_header_data(st, value_slice);
@ -383,15 +384,15 @@ static uint32_t dynidx(grpc_chttp2_hpack_compressor *c, uint32_t elem_index) {
/* encode an mdelem */
static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
grpc_mdelem elem, framer_state *st) {
uint32_t key_hash = grpc_slice_hash(elem->key);
uint32_t value_hash = grpc_slice_hash(elem->value);
uint32_t key_hash = grpc_slice_hash(GRPC_MDKEY(elem));
uint32_t value_hash = grpc_slice_hash(GRPC_MDVALUE(elem));
uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, value_hash);
size_t decoder_space_usage;
uint32_t indices_key;
int should_add_elem;
GPR_ASSERT(GRPC_SLICE_LENGTH(elem->key) > 0);
if (GRPC_SLICE_START_PTR(elem->key)[0] != ':') { /* regular header */
GPR_ASSERT(GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)) > 0);
if (GRPC_SLICE_START_PTR(GRPC_MDKEY(elem))[0] != ':') { /* regular header */
st->seen_regular_header = 1;
} else {
GPR_ASSERT(
@ -403,7 +404,7 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
/* is this elem currently in the decoders table? */
if (c->entries_elems[HASH_FRAGMENT_2(elem_hash)] == elem &&
if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_2(elem_hash)], elem) &&
c->indices_elems[HASH_FRAGMENT_2(elem_hash)] > c->tail_remote_index) {
/* HIT: complete element (first cuckoo hash) */
emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_2(elem_hash)]),
@ -411,7 +412,7 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
return;
}
if (c->entries_elems[HASH_FRAGMENT_3(elem_hash)] == elem &&
if (grpc_mdelem_eq(c->entries_elems[HASH_FRAGMENT_3(elem_hash)], elem) &&
c->indices_elems[HASH_FRAGMENT_3(elem_hash)] > c->tail_remote_index) {
/* HIT: complete element (second cuckoo hash) */
emit_indexed(c, dynidx(c, c->indices_elems[HASH_FRAGMENT_3(elem_hash)]),
@ -428,8 +429,8 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
/* no hits for the elem... maybe there's a key? */
indices_key = c->indices_keys[HASH_FRAGMENT_2(key_hash)];
if (grpc_slice_cmp(c->entries_keys[HASH_FRAGMENT_2(key_hash)], elem->key) ==
0 &&
if (grpc_slice_cmp(c->entries_keys[HASH_FRAGMENT_2(key_hash)],
GRPC_MDKEY(elem)) == 0 &&
indices_key > c->tail_remote_index) {
/* HIT: key (first cuckoo hash) */
if (should_add_elem) {
@ -444,8 +445,8 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c,
}
indices_key = c->indices_keys[HASH_FRAGMENT_3(key_hash)];
if (grpc_slice_cmp(c->entries_keys[HASH_FRAGMENT_3(key_hash)], elem->key) ==
0 &&
if (grpc_slice_cmp(c->entries_keys[HASH_FRAGMENT_3(key_hash)],
GRPC_MDKEY(elem)) == 0 &&
indices_key > c->tail_remote_index) {
/* HIT: key (first cuckoo hash) */
if (should_add_elem) {
@ -512,9 +513,7 @@ void grpc_chttp2_hpack_compressor_destroy(grpc_exec_ctx *exec_ctx,
if (c->entries_keys[i].refcount != &terminal_slice_refcount) {
grpc_slice_unref_internal(exec_ctx, c->entries_keys[i]);
}
if (c->entries_elems[i]) {
GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[i]);
}
GRPC_MDELEM_UNREF(exec_ctx, c->entries_elems[i]);
}
gpr_free(c->table_elem_size);
}

@ -773,7 +773,7 @@ static grpc_error *finish_indexed_field(grpc_exec_ctx *exec_ctx,
const uint8_t *cur,
const uint8_t *end) {
grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
if (md == NULL) {
if (GRPC_MDISNULL(md)) {
return grpc_error_set_int(
grpc_error_set_int(GRPC_ERROR_CREATE("Invalid HPACK index received"),
GRPC_ERROR_INT_INDEX, (intptr_t)p->index),
@ -815,12 +815,12 @@ static grpc_error *finish_lithdr_incidx(grpc_exec_ctx *exec_ctx,
const uint8_t *cur,
const uint8_t *end) {
grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(md != NULL); /* handled in string parsing */
grpc_error *err =
on_hdr(exec_ctx, p,
grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(md->key),
take_string(p, &p->value)),
1);
GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
grpc_error *err = on_hdr(
exec_ctx, p,
grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)),
take_string(p, &p->value)),
1);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end);
}
@ -884,12 +884,12 @@ static grpc_error *finish_lithdr_notidx(grpc_exec_ctx *exec_ctx,
const uint8_t *cur,
const uint8_t *end) {
grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(md != NULL); /* handled in string parsing */
grpc_error *err =
on_hdr(exec_ctx, p,
grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(md->key),
take_string(p, &p->value)),
0);
GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
grpc_error *err = on_hdr(
exec_ctx, p,
grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)),
take_string(p, &p->value)),
0);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end);
}
@ -953,12 +953,12 @@ static grpc_error *finish_lithdr_nvridx(grpc_exec_ctx *exec_ctx,
const uint8_t *cur,
const uint8_t *end) {
grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
GPR_ASSERT(md != NULL); /* handled in string parsing */
grpc_error *err =
on_hdr(exec_ctx, p,
grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(md->key),
take_string(p, &p->value)),
0);
GPR_ASSERT(!GRPC_MDISNULL(md)); /* handled in string parsing */
grpc_error *err = on_hdr(
exec_ctx, p,
grpc_mdelem_from_slices(exec_ctx, grpc_slice_ref_internal(GRPC_MDKEY(md)),
take_string(p, &p->value)),
0);
if (err != GRPC_ERROR_NONE) return parse_error(exec_ctx, p, cur, end, err);
return parse_begin(exec_ctx, p, cur, end);
}
@ -1501,13 +1501,13 @@ static bool is_binary_literal_header(grpc_chttp2_hpack_parser *p) {
static grpc_error *is_binary_indexed_header(grpc_chttp2_hpack_parser *p,
bool *is) {
grpc_mdelem elem = grpc_chttp2_hptbl_lookup(&p->table, p->index);
if (!elem) {
if (GRPC_MDISNULL(elem)) {
return grpc_error_set_int(
grpc_error_set_int(GRPC_ERROR_CREATE("Invalid HPACK index received"),
GRPC_ERROR_INT_INDEX, (intptr_t)p->index),
GRPC_ERROR_INT_SIZE, (intptr_t)p->table.num_ents);
}
*is = grpc_is_binary_header(elem->key);
*is = grpc_is_binary_header(GRPC_MDKEY(elem));
return GRPC_ERROR_NONE;
}

@ -212,7 +212,7 @@ void grpc_chttp2_hptbl_destroy(grpc_exec_ctx *exec_ctx,
}
grpc_mdelem grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
uint32_t tbl_index) {
uint32_t tbl_index) {
/* Static table comes first, just return an entry from it */
if (tbl_index <= GRPC_CHTTP2_LAST_STATIC_ENTRY) {
return tbl->static_ents[tbl_index - 1];
@ -225,14 +225,14 @@ grpc_mdelem grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
return tbl->ents[offset];
}
/* Invalid entry: return error */
return NULL;
return GRPC_MDNULL;
}
/* Evict one element from the table */
static void evict1(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) {
grpc_mdelem first_ent = tbl->ents[tbl->first_ent];
size_t elem_bytes = GRPC_SLICE_LENGTH(first_ent->key) +
GRPC_SLICE_LENGTH(first_ent->value) +
size_t elem_bytes = GRPC_SLICE_LENGTH(GRPC_MDKEY(first_ent)) +
GRPC_SLICE_LENGTH(GRPC_MDVALUE(first_ent)) +
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
GPR_ASSERT(elem_bytes <= tbl->mem_used);
tbl->mem_used -= (uint32_t)elem_bytes;
@ -306,8 +306,8 @@ grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_exec_ctx *exec_ctx,
grpc_error *grpc_chttp2_hptbl_add(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hptbl *tbl, grpc_mdelem md) {
/* determine how many bytes of buffer this entry represents */
size_t elem_bytes = GRPC_SLICE_LENGTH(md->key) +
GRPC_SLICE_LENGTH(md->value) +
size_t elem_bytes = GRPC_SLICE_LENGTH(GRPC_MDKEY(md)) +
GRPC_SLICE_LENGTH(GRPC_MDVALUE(md)) +
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
if (tbl->current_table_bytes > tbl->max_bytes) {
@ -362,9 +362,9 @@ grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
/* See if the string is in the static table */
for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
grpc_mdelem ent = tbl->static_ents[i];
if (grpc_slice_cmp(md->key, ent->key) != 0) continue;
if (grpc_slice_cmp(GRPC_MDKEY(md), GRPC_MDKEY(ent)) != 0) continue;
r.index = i + 1u;
r.has_value = grpc_slice_cmp(md->value, ent->value) == 0;
r.has_value = grpc_slice_cmp(GRPC_MDVALUE(md), GRPC_MDVALUE(ent)) == 0;
if (r.has_value) return r;
}
@ -373,9 +373,9 @@ grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
uint32_t idx =
(uint32_t)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY);
grpc_mdelem ent = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
if (grpc_slice_cmp(md->key, ent->key) != 0) continue;
if (grpc_slice_cmp(GRPC_MDKEY(md), GRPC_MDKEY(ent)) != 0) continue;
r.index = idx;
r.has_value = grpc_slice_cmp(md->value, ent->value) == 0;
r.has_value = grpc_slice_cmp(GRPC_MDVALUE(md), GRPC_MDVALUE(ent)) == 0;
if (r.has_value) return r;
}

@ -453,29 +453,30 @@ static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
GPR_ASSERT(s != NULL);
if (grpc_http_trace) {
char *key = grpc_dump_slice(md->key, GPR_DUMP_ASCII);
char *value = grpc_dump_slice(md->value, GPR_DUMP_HEX | GPR_DUMP_ASCII);
char *key = grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_ASCII);
char *value =
grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id,
t->is_client ? "CLI" : "SVR", key, value);
gpr_free(key);
gpr_free(value);
}
if (grpc_slice_cmp(md->key, GRPC_MDSTR_GRPC_STATUS) == 0 &&
md != GRPC_MDELEM_GRPC_STATUS_0) {
if (grpc_slice_cmp(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) == 0 &&
!grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
/* TODO(ctiller): check for a status like " 0" */
s->seen_error = true;
}
if (grpc_slice_cmp(md->key, GRPC_MDSTR_GRPC_TIMEOUT) == 0) {
if (grpc_slice_cmp(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT) == 0) {
gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
if (!cached_timeout) {
/* not already parsed: parse it now, and store the result away */
cached_timeout = gpr_malloc(sizeof(gpr_timespec));
if (!grpc_http2_decode_timeout(GRPC_SLICE_START_PTR(md->value),
GRPC_SLICE_LENGTH(md->value),
if (!grpc_http2_decode_timeout(GRPC_SLICE_START_PTR(GRPC_MDVALUE(md)),
GRPC_SLICE_LENGTH(GRPC_MDVALUE(md)),
cached_timeout)) {
char *val = grpc_dump_slice(md->value, GPR_DUMP_ASCII);
char *val = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_ASCII);
gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
gpr_free(val);
*cached_timeout = gpr_inf_future(GPR_TIMESPAN);
@ -523,16 +524,17 @@ static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp,
GPR_ASSERT(s != NULL);
if (grpc_http_trace) {
char *key = grpc_dump_slice(md->key, GPR_DUMP_ASCII);
char *value = grpc_dump_slice(md->value, GPR_DUMP_HEX | GPR_DUMP_ASCII);
char *key = grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_ASCII);
char *value =
grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_INFO, "HTTP:%d:TRL:%s: %s: %s", s->id,
t->is_client ? "CLI" : "SVR", key, value);
gpr_free(key);
gpr_free(value);
}
if (grpc_slice_cmp(md->key, GRPC_MDSTR_GRPC_STATUS) == 0 &&
md != GRPC_MDELEM_GRPC_STATUS_0) {
if (grpc_slice_cmp(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) == 0 &&
!grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
/* TODO(ctiller): check for a status like " 0" */
s->seen_error = true;
}

@ -39,7 +39,8 @@
#include <grpc/support/string_util.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.
// 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;
}
static int message_size_limits_cmp(void* value1, void* value2) {
const message_size_limits* v1 = value1;
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 message_size_limits_free(grpc_exec_ctx* exec_ctx, void* value) {
gpr_free(value);
}
static void free_mem(grpc_exec_ctx* exec_ctx, void* p) { gpr_free(p); }
static const grpc_slice_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(
const grpc_method_config* method_config) {
static void* message_size_limits_create_from_json(const grpc_json* json) {
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));
const int32_t* max_request_message_bytes =
grpc_method_config_get_max_request_message_bytes(method_config);
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;
value->max_send_size = max_request_message_bytes;
value->max_recv_size = max_response_message_bytes;
return value;
}
@ -225,10 +227,16 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx,
const grpc_arg* channel_arg =
grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVICE_CONFIG);
if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
chand->method_limit_table = grpc_method_config_table_convert(
exec_ctx, (grpc_method_config_table*)channel_arg->value.pointer.p,
method_config_convert_value, &message_size_limits_vtable);
GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
grpc_service_config* service_config =
grpc_service_config_create(channel_arg->value.string);
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);
}
}
}

@ -37,15 +37,15 @@
#include "src/core/lib/json/json.h"
grpc_json *grpc_json_create(grpc_json_type type) {
grpc_json *json = gpr_malloc(sizeof(*json));
grpc_json* grpc_json_create(grpc_json_type type) {
grpc_json* json = gpr_malloc(sizeof(*json));
memset(json, 0, sizeof(*json));
json->type = type;
return json;
}
void grpc_json_destroy(grpc_json *json) {
void grpc_json_destroy(grpc_json* json) {
while (json->child) {
grpc_json_destroy(json->child);
}

@ -42,14 +42,14 @@
* are not owned by it.
*/
typedef struct grpc_json {
struct grpc_json *next;
struct grpc_json *prev;
struct grpc_json *child;
struct grpc_json *parent;
struct grpc_json* next;
struct grpc_json* prev;
struct grpc_json* child;
struct grpc_json* parent;
grpc_json_type type;
const char *key;
const char *value;
const char* key;
const char* value;
} grpc_json;
/* The next two functions are going to parse the input string, and
@ -65,8 +65,8 @@ typedef struct grpc_json {
*
* Delete the allocated tree afterward using grpc_json_destroy().
*/
grpc_json *grpc_json_parse_string_with_len(char *input, size_t size);
grpc_json *grpc_json_parse_string(char *input);
grpc_json* grpc_json_parse_string_with_len(char* input, size_t size);
grpc_json* grpc_json_parse_string(char* input);
/* This function will create a new string using gpr_realloc, and will
* deserialize the grpc_json tree into it. It'll be zero-terminated,
@ -76,13 +76,13 @@ grpc_json *grpc_json_parse_string(char *input);
* If indent is 0, then newlines will be suppressed as well, and the
* output will be condensed at its maximum.
*/
char *grpc_json_dump_to_string(grpc_json *json, int indent);
char* grpc_json_dump_to_string(grpc_json* json, int indent);
/* Use these to create or delete a grpc_json object.
* Deletion is recursive. We will not attempt to free any of the strings
* in any of the objects of that tree.
*/
grpc_json *grpc_json_create(grpc_json_type type);
void grpc_json_destroy(grpc_json *json);
grpc_json* grpc_json_create(grpc_json_type type);
void grpc_json_destroy(grpc_json* json);
#endif /* GRPC_CORE_LIB_JSON_JSON_H */

@ -256,17 +256,17 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_mdelem md = l->md;
/* Pointer comparison is OK for md_elems created from the same context.
*/
if (grpc_slice_cmp(md->key, GRPC_MDSTR_AUTHORITY) == 0) {
if (grpc_slice_cmp(GRPC_MDKEY(md), GRPC_MDSTR_AUTHORITY) == 0) {
if (calld->have_host) {
grpc_slice_unref_internal(exec_ctx, calld->host);
}
calld->host = grpc_slice_ref_internal(md->value);
calld->host = grpc_slice_ref_internal(GRPC_MDVALUE(md));
calld->have_host = true;
} else if (grpc_slice_cmp(md->key, GRPC_MDSTR_PATH) == 0) {
} else if (grpc_slice_cmp(GRPC_MDKEY(md), GRPC_MDSTR_PATH) == 0) {
if (calld->have_method) {
grpc_slice_unref_internal(exec_ctx, calld->method);
}
calld->method = grpc_slice_ref_internal(md->value);
calld->method = grpc_slice_ref_internal(GRPC_MDVALUE(md));
calld->have_method = true;
}
}

@ -69,8 +69,8 @@ static grpc_metadata_array metadata_batch_to_md_array(
for (l = batch->list.head; l != NULL; l = l->next) {
grpc_metadata *usr_md = NULL;
grpc_mdelem md = l->md;
grpc_slice key = md->key;
grpc_slice value = md->value;
grpc_slice key = GRPC_MDKEY(md);
grpc_slice value = GRPC_MDVALUE(md);
if (result.count == result.capacity) {
result.capacity = GPR_MAX(result.capacity + 8, result.capacity * 2);
result.metadata =
@ -90,9 +90,9 @@ static grpc_mdelem remove_consumed_md(grpc_exec_ctx *exec_ctx, void *user_data,
size_t i;
for (i = 0; i < calld->num_consumed_md; i++) {
const grpc_metadata *consumed_md = &calld->consumed_md[i];
if (grpc_slice_cmp(md->key, consumed_md->key) == 0 &&
grpc_slice_cmp(md->value, consumed_md->value) == 0)
return NULL;
if (grpc_slice_cmp(GRPC_MDKEY(md), consumed_md->key) == 0 &&
grpc_slice_cmp(GRPC_MDKEY(md), consumed_md->value) == 0)
return GRPC_MDNULL;
}
return md;
}

@ -46,7 +46,6 @@ static const grpc_slice terminal_slice = {&terminal_slice_refcount,
struct grpc_slice_hash_table {
gpr_refcount refs;
size_t num_entries;
size_t size;
grpc_slice_hash_table_entry* entries;
};
@ -90,7 +89,6 @@ grpc_slice_hash_table* grpc_slice_hash_table_create(
grpc_slice_hash_table* table = gpr_malloc(sizeof(*table));
memset(table, 0, sizeof(*table));
gpr_ref_init(&table->refs, 1);
table->num_entries = num_entries;
// Quadratic probing gets best performance when the table is no more
// than half full.
table->size = num_entries * 2;
@ -112,8 +110,8 @@ grpc_slice_hash_table* grpc_slice_hash_table_ref(grpc_slice_hash_table* table) {
return table;
}
int grpc_slice_hash_table_unref(grpc_exec_ctx* exec_ctx,
grpc_slice_hash_table* table) {
void grpc_slice_hash_table_unref(grpc_exec_ctx* exec_ctx,
grpc_slice_hash_table* table) {
if (table != NULL && gpr_unref(&table->refs)) {
for (size_t i = 0; i < table->size; ++i) {
grpc_slice_hash_table_entry* entry = &table->entries[i];
@ -124,13 +122,7 @@ int grpc_slice_hash_table_unref(grpc_exec_ctx* exec_ctx,
}
gpr_free(table->entries);
gpr_free(table);
return 1;
}
return 0;
}
size_t grpc_slice_hash_table_num_entries(const grpc_slice_hash_table* table) {
return table->num_entries;
}
void* grpc_slice_hash_table_get(const grpc_slice_hash_table* table,
@ -140,35 +132,3 @@ void* grpc_slice_hash_table_get(const grpc_slice_hash_table* table,
if (idx == table->size) return NULL; // Not found.
return table->entries[idx].value;
}
int grpc_slice_hash_table_cmp(const grpc_slice_hash_table* table1,
const grpc_slice_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_slice_hash_table_entry* e1 = &table1->entries[i];
grpc_slice_hash_table_entry* e2 = &table2->entries[i];
// Compare keys by hash value.
int cmp = grpc_slice_cmp(e1->key, e2->key);
if (cmp != 0) return cmp;
// 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_slice_hash_table_iterate(
const grpc_slice_hash_table* table,
void (*func)(const grpc_slice_hash_table_entry* entry, void* user_data),
void* user_data) {
for (size_t i = 0; i < table->size; ++i) {
if (!is_terminal(table->entries[i].key)) {
func(&table->entries[i], user_data);
}
}
}

@ -51,7 +51,6 @@ typedef struct grpc_slice_hash_table grpc_slice_hash_table;
typedef struct grpc_slice_hash_table_vtable {
void (*destroy_value)(grpc_exec_ctx *exec_ctx, void *value);
void *(*copy_value)(void *value);
int (*compare_value)(void *value1, void *value2);
} grpc_slice_hash_table_vtable;
typedef struct grpc_slice_hash_table_entry {
@ -68,26 +67,12 @@ grpc_slice_hash_table *grpc_slice_hash_table_create(
grpc_slice_hash_table *grpc_slice_hash_table_ref(grpc_slice_hash_table *table);
/** Returns 1 when \a table is destroyed. */
int grpc_slice_hash_table_unref(grpc_exec_ctx *exec_ctx,
grpc_slice_hash_table *table);
/** Returns the number of entries in \a table. */
size_t grpc_slice_hash_table_num_entries(const grpc_slice_hash_table *table);
void grpc_slice_hash_table_unref(grpc_exec_ctx *exec_ctx,
grpc_slice_hash_table *table);
/** Returns the value from \a table associated with \a key.
Returns NULL if \a key is not found. */
void *grpc_slice_hash_table_get(const grpc_slice_hash_table *table,
const grpc_slice key);
/** Compares two hash tables.
The sort order is stable but undefined. */
int grpc_slice_hash_table_cmp(const grpc_slice_hash_table *table1,
const grpc_slice_hash_table *table2);
/** Iterates over the entries in \a table, calling \a func for each entry. */
void grpc_slice_hash_table_iterate(
const grpc_slice_hash_table *table,
void (*func)(const grpc_slice_hash_table_entry *entry, void *user_data),
void *user_data);
#endif /* GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H */

@ -34,7 +34,9 @@
#include "src/core/lib/support/string.h"
#include <ctype.h>
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <grpc/support/alloc.h>
@ -189,6 +191,13 @@ int int64_ttoa(int64_t value, char *string) {
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) {
const size_t str_length = strlen(str);
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.*/
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 */
void gpr_reverse_bytes(char *str, int len);

@ -0,0 +1,254 @@
//
// 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/slice/slice_hash_table.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.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_slice_hash_table_vtable* vtable,
grpc_slice_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_slice_from_copied_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_slice_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_slice_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_slice_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_slice_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_slice_hash_table* method_config_table = NULL;
if (entries != NULL) {
method_config_table = grpc_slice_hash_table_create(num_entries, entries);
// Clean up.
for (size_t i = 0; i < num_entries; ++i) {
grpc_slice_unref_internal(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_slice_hash_table* table,
grpc_slice path) {
void* value = grpc_slice_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) {
char* path_str = grpc_dump_slice(path, GPR_DUMP_ASCII);
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_slice wildcard_path = grpc_slice_from_copied_string(buf);
gpr_free(buf);
value = grpc_slice_hash_table_get(table, wildcard_path);
grpc_slice_unref_internal(exec_ctx, wildcard_path);
gpr_free(path_str);
}
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/slice/slice_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_slice_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_slice_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_slice_hash_table* table,
const grpc_slice path);
#endif /* GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H */

@ -49,10 +49,12 @@
static void put_metadata(gpr_strvec *b, grpc_mdelem md) {
gpr_strvec_add(b, gpr_strdup("key="));
gpr_strvec_add(b, grpc_dump_slice(md->key, GPR_DUMP_HEX | GPR_DUMP_ASCII));
gpr_strvec_add(
b, grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII));
gpr_strvec_add(b, gpr_strdup(" value="));
gpr_strvec_add(b, grpc_dump_slice(md->value, GPR_DUMP_HEX | GPR_DUMP_ASCII));
gpr_strvec_add(
b, grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII));
}
static void put_metadata_list(gpr_strvec *b, grpc_metadata_batch md) {

@ -48,6 +48,7 @@
#include <grpc++/support/time.h>
#include <grpc/grpc.h>
#include <grpc/slice.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.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_); }
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,
CompletionQueue* cq) {
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);
}
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) {
grpc_arg arg;
arg.type = GRPC_ARG_INTEGER;

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

@ -43,11 +43,13 @@ from tests.interop import resources
def _args():
parser = argparse.ArgumentParser()
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(
'--server_port', help='the port to which to connect', type=int)
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(
'--use_tls', help='require a secure connection', default=False,
type=resources.parse_bool)
@ -55,7 +57,7 @@ def _args():
'--use_test_ca', help='replace platform root CAs with ca.pem',
default=False, type=resources.parse_bool)
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)
parser.add_argument('--oauth_scope', help='scope for OAuth tokens', type=str)
parser.add_argument(

@ -43,6 +43,7 @@
#include "src/core/ext/client_channel/client_channel.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/support/string.h"
#include "src/core/lib/surface/channel.h"
@ -521,7 +522,7 @@ static grpc_channel *create_client(const servers_fixture *f) {
arg_array[0].value.integer = RETRY_TIMEOUT;
arg_array[1].type = GRPC_ARG_STRING;
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.args = arg_array;
@ -610,29 +611,47 @@ static void test_pending_calls(size_t concurrent_calls) {
}
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_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.
grpc_channel_check_connectivity_state(channel, true /* try_to_connect */);
// Use grpc_channel_get_info() to get LB policy name.
char *lb_policy_name = NULL;
// First, request no fields. This is a no-op.
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;
grpc_channel_get_info(channel, &channel_info);
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);
// Try again without requesting anything. This is a no-op.
channel_info.lb_policy_name = NULL;
// Request service config, which does not exist, so we'll get nothing back.
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);
GPR_ASSERT(service_config_json != NULL);
GPR_ASSERT(strcmp(service_config_json, arg.value.string) == 0);
gpr_free(service_config_json);
// Clean up.
grpc_channel_destroy(channel);
}

@ -42,7 +42,7 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/slice/slice_internal.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/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 */
grpc_channel_args *args = NULL;
if (use_service_config) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GPR_ASSERT(wait_for_ready);
grpc_method_config_table_entry entry = {
grpc_slice_from_static_string("/service/method"),
grpc_method_config_create(&wait_for_ready, NULL, NULL, NULL),
};
grpc_method_config_table *method_config_table =
grpc_method_config_table_create(1, &entry);
grpc_slice_unref_internal(&exec_ctx, entry.method_name);
grpc_method_config_unref(&exec_ctx, entry.method_config);
grpc_arg arg =
grpc_method_config_table_create_channel_arg(method_config_table);
grpc_arg arg;
arg.type = GRPC_ARG_STRING;
arg.key = GRPC_ARG_SERVICE_CONFIG;
arg.value.string =
"{\n"
" \"methodConfig\": [ {\n"
" \"name\": [\n"
" { \"service\": \"service\", \"method\": \"method\" }\n"
" ],\n"
" \"waitForReady\": true\n"
" } ]\n"
"}";
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 */

@ -45,7 +45,7 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/slice/slice_internal.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/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;
if (use_service_config) {
gpr_timespec timeout = {5, 0, GPR_TIMESPAN};
grpc_method_config_table_entry entry = {
grpc_slice_from_static_string("/service/method"),
grpc_method_config_create(NULL, &timeout, NULL, NULL),
};
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_method_config_table *method_config_table =
grpc_method_config_table_create(1, &entry);
grpc_slice_unref_internal(&exec_ctx, entry.method_name);
grpc_method_config_unref(&exec_ctx, entry.method_config);
grpc_arg arg =
grpc_method_config_table_create_channel_arg(method_config_table);
grpc_arg arg;
arg.type = GRPC_ARG_STRING;
arg.key = GRPC_ARG_SERVICE_CONFIG;
arg.value.string =
"{\n"
" \"methodConfig\": [ {\n"
" \"name\": [\n"
" { \"service\": \"service\", \"method\": \"method\" }\n"
" ],\n"
" \"timeout\": \"5s\"\n"
" } ]\n"
"}";
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 =

@ -45,7 +45,7 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/slice/slice_internal.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"
@ -137,22 +137,20 @@ static void test_max_message_length_on_request(grpc_end2end_test_config config,
grpc_channel_args *server_args = NULL;
if (use_service_config) {
// We don't currently support service configs on the server side.
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GPR_ASSERT(send_limit);
int32_t max_request_message_bytes = 5;
grpc_method_config_table_entry entry = {
grpc_slice_from_static_string("/service/method"),
grpc_method_config_create(NULL, NULL, &max_request_message_bytes, NULL),
};
grpc_method_config_table *method_config_table =
grpc_method_config_table_create(1, &entry);
grpc_slice_unref_internal(&exec_ctx, entry.method_name);
grpc_method_config_unref(&exec_ctx, entry.method_config);
grpc_arg arg =
grpc_method_config_table_create_channel_arg(method_config_table);
grpc_arg arg;
arg.type = GRPC_ARG_STRING;
arg.key = GRPC_ARG_SERVICE_CONFIG;
arg.value.string =
"{\n"
" \"methodConfig\": [ {\n"
" \"name\": [\n"
" { \"service\": \"service\", \"method\": \"method\" }\n"
" ],\n"
" \"maxRequestMessageBytes\": \"5\"\n"
" } ]\n"
"}";
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 {
// Set limit via channel args.
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;
if (use_service_config) {
// We don't currently support service configs on the server side.
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GPR_ASSERT(!send_limit);
int32_t max_response_message_bytes = 5;
grpc_method_config_table_entry entry = {
grpc_slice_from_static_string("/service/method"),
grpc_method_config_create(NULL, NULL, NULL,
&max_response_message_bytes),
};
grpc_method_config_table *method_config_table =
grpc_method_config_table_create(1, &entry);
grpc_slice_unref_internal(&exec_ctx, entry.method_name);
grpc_method_config_unref(&exec_ctx, entry.method_config);
grpc_arg arg =
grpc_method_config_table_create_channel_arg(method_config_table);
grpc_arg arg;
arg.type = GRPC_ARG_STRING;
arg.key = GRPC_ARG_SERVICE_CONFIG;
arg.value.string =
"{\n"
" \"methodConfig\": [ {\n"
" \"name\": [\n"
" { \"service\": \"service\", \"method\": \"method\" }\n"
" ],\n"
" \"maxResponseMessageBytes\": \"5\"\n"
" } ]\n"
"}";
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 {
// Set limit via channel args.
grpc_arg arg;

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

@ -108,6 +108,7 @@ typedef struct server_fixture {
grpc_completion_queue *cq;
char *servers_hostport;
int port;
const char *lb_token_prefix;
gpr_thd_id tid;
int num_calls_serviced;
} server_fixture;
@ -123,7 +124,8 @@ static void *tag(intptr_t t) { return (void *)t; }
static grpc_slice build_response_payload_slice(
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 {
// servers {
// ip_address: <in_addr/6 bytes of an IP>
@ -150,15 +152,15 @@ static grpc_slice build_response_payload_slice(
struct in_addr ip4;
GPR_ASSERT(inet_pton(AF_INET, host, &ip4) == 1);
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]);
// The following long long int cast is meant to work around the
// 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.
string token_data = "token" + std::to_string((long long int)ports[i]);
server->set_load_balance_token(token_data);
// Missing tokens are acceptable. Test that path.
if (strlen(token_prefix) > 0) {
string token_data = token_prefix + std::to_string(ports[i]);
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());
}
@ -250,14 +252,14 @@ static void start_lb_server(server_fixture *sf, int *ports, size_t nports,
for (int i = 0; i < 2; i++) {
if (i == 0) {
// First half of the ports.
response_payload_slice =
build_response_payload_slice("127.0.0.1", ports, nports / 2, -1, -1);
response_payload_slice = build_response_payload_slice(
"127.0.0.1", ports, nports / 2, -1, -1, sf->lb_token_prefix);
} else {
// Second half of the ports.
sleep_ms(update_delay_ms);
response_payload_slice =
build_response_payload_slice("127.0.0.1", ports + (nports / 2),
(nports + 1) / 2 /* ceil */, -1, -1);
response_payload_slice = build_response_payload_slice(
"127.0.0.1", ports + (nports / 2), (nports + 1) / 2 /* ceil */, -1,
-1, "" /* this half doesn't get to receive an LB token */);
}
response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1);
@ -339,11 +341,10 @@ static void start_backend_server(server_fixture *sf) {
return;
}
GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
// The following long long int cast is meant to work around the
// 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.
string expected_token = "token" + std::to_string((long long int)sf->port);
const string expected_token =
strlen(sf->lb_token_prefix) == 0
? ""
: sf->lb_token_prefix + std::to_string(sf->port);
GPR_ASSERT(contains_metadata(&request_metadata_recv, "lb-token",
expected_token.c_str()));
@ -626,6 +627,7 @@ static void fork_lb_server(void *arg) {
tf->lb_server_update_delay_ms);
}
#define LB_TOKEN_PREFIX "token"
static test_fixture setup_test_fixture(int lb_server_update_delay_ms) {
test_fixture 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);
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]);
gpr_thd_new(&tf.lb_backends[i].tid, fork_backend_server, &tf.lb_backends[i],
&options);
}
tf.lb_server.lb_token_prefix = LB_TOKEN_PREFIX;
setup_server("127.0.0.1", &tf.lb_server);
gpr_thd_new(&tf.lb_server.tid, fork_lb_server, &tf.lb_server, &options);

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

@ -41,8 +41,12 @@ tools/run_tests/run_performance_tests.py \
--category scalable \
--bq_result_table performance_test.performance_experiment \
--remote_worker_host grpc-performance-server-8core grpc-performance-client-8core grpc-performance-client2-8core \
--xml_report report_8core.xml \
|| 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)
tools/run_tests/run_performance_tests.py \
-l c++ java csharp go \
@ -50,6 +54,19 @@ tools/run_tests/run_performance_tests.py \
--category scalable \
--bq_result_table performance_test.performance_experiment_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 $EXIT_CODE

@ -37,10 +37,14 @@ CONFIG=${CONFIG:-opt}
# build C++ qps worker & driver always - we need at least the driver to
# run any of the scenarios.
# TODO(jtattermusch): not embedding OpenSSL breaks the C# build because
# grpc_csharp_ext needs OpenSSL embedded and some intermediate files from
# this build will be reused.
make CONFIG=${CONFIG} EMBED_OPENSSL=true EMBED_ZLIB=true qps_worker qps_json_driver -j8
# 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
# grpc_csharp_ext needs OpenSSL embedded and some intermediate files from
# this build will be reused.
make CONFIG=${CONFIG} EMBED_OPENSSL=true EMBED_ZLIB=true qps_worker qps_json_driver -j8
fi
for language in $@
do
@ -55,10 +59,10 @@ do
tools/run_tests/performance/build_performance_go.sh
;;
"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
done

@ -32,18 +32,23 @@ set -ex
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
# mess with the results, be rough and reboot the slave here
# and wait for it to come back online.
# could also kill jenkins.
ssh "${USER_AT_HOST}" "killall -9 qps_worker mono node ruby worker || true"
ssh "${USER_AT_HOST}" "killall -9 qps_worker dotnet 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.
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.
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',
const=True,
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()
@ -473,7 +475,7 @@ for scenario in scenarios:
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')
if total_scenario_failures > 0 or qps_workers_killed > 0:

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

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

@ -325,10 +325,10 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c">
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c">
<Filter>src\core\lib\transport</Filter>
</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>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
@ -1007,10 +1007,10 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h">
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h">
<Filter>src\core\lib\transport</Filter>
</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>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">

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

@ -382,10 +382,10 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c">
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c">
<Filter>src\core\lib\transport</Filter>
</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>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
@ -803,10 +803,10 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h">
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h">
<Filter>src\core\lib\transport</Filter>
</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>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">

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

@ -328,10 +328,10 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.c">
<Filter>src\core\lib\transport</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\method_config.c">
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.c">
<Filter>src\core\lib\transport</Filter>
</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>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.c">
@ -920,10 +920,10 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\metadata_batch.h">
<Filter>src\core\lib\transport</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\method_config.h">
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\pid_controller.h">
<Filter>src\core\lib\transport</Filter>
</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>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\static_metadata.h">

Loading…
Cancel
Save