Merge pull request #8462 from markdroth/resolver_channel_args

Plumb channel_args through resolvers.
pull/8517/head^2
Mark D. Roth 8 years ago committed by GitHub
commit d4a5971ae8
  1. 8
      BUILD
  2. 3
      CMakeLists.txt
  3. 3
      Makefile
  4. 1
      binding.gyp
  5. 2
      build.yaml
  6. 1
      config.m4
  7. 3
      gRPC-Core.podspec
  8. 2
      grpc.gemspec
  9. 7
      include/grpc/impl/codegen/grpc_types.h
  10. 2
      package.xml
  11. 21
      src/core/ext/client_channel/README.md
  12. 59
      src/core/ext/client_channel/client_channel.c
  13. 4
      src/core/ext/client_channel/client_channel_factory.c
  14. 9
      src/core/ext/client_channel/client_channel_factory.h
  15. 78
      src/core/ext/client_channel/lb_policy_factory.c
  16. 40
      src/core/ext/client_channel/lb_policy_factory.h
  17. 3
      src/core/ext/client_channel/resolver.c
  18. 18
      src/core/ext/client_channel/resolver.h
  19. 7
      src/core/ext/client_channel/resolver_factory.h
  20. 12
      src/core/ext/client_channel/resolver_registry.c
  21. 7
      src/core/ext/client_channel/resolver_registry.h
  22. 94
      src/core/ext/client_channel/resolver_result.c
  23. 68
      src/core/ext/client_channel/resolver_result.h
  24. 2
      src/core/ext/client_channel/subchannel.c
  25. 2
      src/core/ext/client_channel/subchannel.h
  26. 6
      src/core/ext/client_channel/subchannel_index.c
  27. 4
      src/core/ext/client_channel/subchannel_index.h
  28. 106
      src/core/ext/lb_policy/grpclb/grpclb.c
  29. 30
      src/core/ext/lb_policy/pick_first/pick_first.c
  30. 29
      src/core/ext/lb_policy/round_robin/round_robin.c
  31. 50
      src/core/ext/resolver/dns/native/dns_resolver.c
  32. 35
      src/core/ext/resolver/sockaddr/sockaddr_resolver.c
  33. 63
      src/core/ext/transport/chttp2/client/insecure/channel_create.c
  34. 73
      src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
  35. 55
      src/core/lib/channel/channel_args.c
  36. 11
      src/core/lib/channel/channel_args.h
  37. 1
      src/python/grpcio/grpc_core_dependencies.py
  38. 5
      test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
  39. 14
      test/core/client_channel/resolvers/sockaddr_resolver_test.c
  40. 42
      test/core/end2end/fake_resolver.c
  41. 2
      test/cpp/end2end/end2end_test.cc
  42. 2
      tools/doxygen/Doxyfile.core.internal
  43. 3
      tools/run_tests/sources_and_headers.json
  44. 2
      tools/run_tests/tests.json
  45. 3
      vsprojects/vcxproj/grpc/grpc.vcxproj
  46. 6
      vsprojects/vcxproj/grpc/grpc.vcxproj.filters
  47. 3
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
  48. 6
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters

@ -311,7 +311,6 @@ cc_library(
"src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h",
@ -504,7 +503,6 @@ cc_library(
"src/core/ext/client_channel/resolver.c",
"src/core/ext/client_channel/resolver_factory.c",
"src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/resolver_result.c",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c",
@ -711,7 +709,6 @@ cc_library(
"src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h",
@ -887,7 +884,6 @@ cc_library(
"src/core/ext/client_channel/resolver.c",
"src/core/ext/client_channel/resolver_factory.c",
"src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/resolver_result.c",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c",
@ -1088,7 +1084,6 @@ cc_library(
"src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h",
@ -1257,7 +1252,6 @@ cc_library(
"src/core/ext/client_channel/resolver.c",
"src/core/ext/client_channel/resolver_factory.c",
"src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/resolver_result.c",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c",
@ -2207,7 +2201,6 @@ objc_library(
"src/core/ext/client_channel/resolver.c",
"src/core/ext/client_channel/resolver_factory.c",
"src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/resolver_result.c",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c",
@ -2416,7 +2409,6 @@ objc_library(
"src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h",

@ -462,7 +462,6 @@ add_library(grpc
src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c
src/core/ext/client_channel/resolver_result.c
src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c
@ -709,7 +708,6 @@ add_library(grpc_cronet
src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c
src/core/ext/client_channel/resolver_result.c
src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c
@ -953,7 +951,6 @@ add_library(grpc_unsecure
src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c
src/core/ext/client_channel/resolver_result.c
src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c

@ -2747,7 +2747,6 @@ LIBGRPC_SRC = \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/resolver_result.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \
@ -3012,7 +3011,6 @@ LIBGRPC_CRONET_SRC = \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/resolver_result.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \
@ -3501,7 +3499,6 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/resolver_result.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \

@ -740,7 +740,6 @@
'src/core/ext/client_channel/resolver.c',
'src/core/ext/client_channel/resolver_factory.c',
'src/core/ext/client_channel/resolver_registry.c',
'src/core/ext/client_channel/resolver_result.c',
'src/core/ext/client_channel/subchannel.c',
'src/core/ext/client_channel/subchannel_index.c',
'src/core/ext/client_channel/uri_parser.c',

@ -382,7 +382,6 @@ filegroups:
- src/core/ext/client_channel/resolver.h
- src/core/ext/client_channel/resolver_factory.h
- src/core/ext/client_channel/resolver_registry.h
- src/core/ext/client_channel/resolver_result.h
- src/core/ext/client_channel/subchannel.h
- src/core/ext/client_channel/subchannel_index.h
- src/core/ext/client_channel/uri_parser.h
@ -403,7 +402,6 @@ filegroups:
- src/core/ext/client_channel/resolver.c
- src/core/ext/client_channel/resolver_factory.c
- src/core/ext/client_channel/resolver_registry.c
- src/core/ext/client_channel/resolver_result.c
- src/core/ext/client_channel/subchannel.c
- src/core/ext/client_channel/subchannel_index.c
- src/core/ext/client_channel/uri_parser.c

@ -256,7 +256,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/resolver_result.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \

@ -398,7 +398,6 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/resolver.h',
'src/core/ext/client_channel/resolver_factory.h',
'src/core/ext/client_channel/resolver_registry.h',
'src/core/ext/client_channel/resolver_result.h',
'src/core/ext/client_channel/subchannel.h',
'src/core/ext/client_channel/subchannel_index.h',
'src/core/ext/client_channel/uri_parser.h',
@ -595,7 +594,6 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/resolver.c',
'src/core/ext/client_channel/resolver_factory.c',
'src/core/ext/client_channel/resolver_registry.c',
'src/core/ext/client_channel/resolver_result.c',
'src/core/ext/client_channel/subchannel.c',
'src/core/ext/client_channel/subchannel_index.c',
'src/core/ext/client_channel/uri_parser.c',
@ -793,7 +791,6 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/resolver.h',
'src/core/ext/client_channel/resolver_factory.h',
'src/core/ext/client_channel/resolver_registry.h',
'src/core/ext/client_channel/resolver_result.h',
'src/core/ext/client_channel/subchannel.h',
'src/core/ext/client_channel/subchannel_index.h',
'src/core/ext/client_channel/uri_parser.h',

@ -318,7 +318,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_channel/resolver.h )
s.files += %w( src/core/ext/client_channel/resolver_factory.h )
s.files += %w( src/core/ext/client_channel/resolver_registry.h )
s.files += %w( src/core/ext/client_channel/resolver_result.h )
s.files += %w( src/core/ext/client_channel/subchannel.h )
s.files += %w( src/core/ext/client_channel/subchannel_index.h )
s.files += %w( src/core/ext/client_channel/uri_parser.h )
@ -515,7 +514,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_channel/resolver.c )
s.files += %w( src/core/ext/client_channel/resolver_factory.c )
s.files += %w( src/core/ext/client_channel/resolver_registry.c )
s.files += %w( src/core/ext/client_channel/resolver_result.c )
s.files += %w( src/core/ext/client_channel/subchannel.c )
s.files += %w( src/core/ext/client_channel/subchannel_index.c )
s.files += %w( src/core/ext/client_channel/uri_parser.c )

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

@ -325,7 +325,6 @@
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_result.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/subchannel.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/subchannel_index.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.h" role="src" />
@ -522,7 +521,6 @@
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_result.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/subchannel.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/subchannel_index.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.c" role="src" />

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

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

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

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

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

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

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

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

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

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

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

@ -1,94 +0,0 @@
//
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#include "src/core/ext/client_channel/resolver_result.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h"
struct grpc_resolver_result {
gpr_refcount refs;
char* server_name;
grpc_lb_addresses* addresses;
char* lb_policy_name;
grpc_channel_args* lb_policy_args;
};
grpc_resolver_result* grpc_resolver_result_create(
const char* server_name, grpc_lb_addresses* addresses,
const char* lb_policy_name, grpc_channel_args* lb_policy_args) {
grpc_resolver_result* result = gpr_malloc(sizeof(*result));
memset(result, 0, sizeof(*result));
gpr_ref_init(&result->refs, 1);
result->server_name = gpr_strdup(server_name);
result->addresses = addresses;
result->lb_policy_name = gpr_strdup(lb_policy_name);
result->lb_policy_args = lb_policy_args;
return result;
}
void grpc_resolver_result_ref(grpc_resolver_result* result) {
gpr_ref(&result->refs);
}
void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx,
grpc_resolver_result* result) {
if (gpr_unref(&result->refs)) {
gpr_free(result->server_name);
grpc_lb_addresses_destroy(result->addresses, NULL /* user_data_destroy */);
gpr_free(result->lb_policy_name);
grpc_channel_args_destroy(result->lb_policy_args);
gpr_free(result);
}
}
const char* grpc_resolver_result_get_server_name(grpc_resolver_result* result) {
return result->server_name;
}
grpc_lb_addresses* grpc_resolver_result_get_addresses(
grpc_resolver_result* result) {
return result->addresses;
}
const char* grpc_resolver_result_get_lb_policy_name(
grpc_resolver_result* result) {
return result->lb_policy_name;
}
grpc_channel_args* grpc_resolver_result_get_lb_policy_args(
grpc_resolver_result* result) {
return result->lb_policy_args;
}

@ -1,68 +0,0 @@
//
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H
#define GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H
#include "src/core/ext/client_channel/lb_policy_factory.h"
// TODO(roth, ctiller): In the long term, we are considering replacing
// the resolver_result data structure with grpc_channel_args. The idea is
// that the resolver will return a set of channel args that contains the
// information that is currently in the resolver_result struct. For
// example, there will be specific args indicating the set of addresses
// and the name of the LB policy to instantiate. Note that if we did
// this, we would probably want to change the data structure of
// grpc_channel_args such to a hash table or AVL or some other data
// structure that does not require linear search to find keys.
/// Results reported from a grpc_resolver.
typedef struct grpc_resolver_result grpc_resolver_result;
/// Takes ownership of \a addresses and \a lb_policy_args.
grpc_resolver_result* grpc_resolver_result_create(
const char* server_name, grpc_lb_addresses* addresses,
const char* lb_policy_name, grpc_channel_args* lb_policy_args);
void grpc_resolver_result_ref(grpc_resolver_result* result);
void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx,
grpc_resolver_result* result);
/// Accessors. Caller does NOT take ownership of results.
const char* grpc_resolver_result_get_server_name(grpc_resolver_result* result);
grpc_lb_addresses* grpc_resolver_result_get_addresses(
grpc_resolver_result* result);
const char* grpc_resolver_result_get_lb_policy_name(
grpc_resolver_result* result);
grpc_channel_args* grpc_resolver_result_get_lb_policy_args(
grpc_resolver_result* result);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H */

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -250,7 +250,6 @@ CORE_SOURCE_FILES = [
'src/core/ext/client_channel/resolver.c',
'src/core/ext/client_channel/resolver_factory.c',
'src/core/ext/client_channel/resolver_registry.c',
'src/core/ext/client_channel/resolver_result.c',
'src/core/ext/client_channel/subchannel.c',
'src/core/ext/client_channel/subchannel_index.c',
'src/core/ext/client_channel/uri_parser.c',

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

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

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

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

@ -935,7 +935,6 @@ src/core/ext/client_channel/parse_address.h \
src/core/ext/client_channel/resolver.h \
src/core/ext/client_channel/resolver_factory.h \
src/core/ext/client_channel/resolver_registry.h \
src/core/ext/client_channel/resolver_result.h \
src/core/ext/client_channel/subchannel.h \
src/core/ext/client_channel/subchannel_index.h \
src/core/ext/client_channel/uri_parser.h \
@ -1132,7 +1131,6 @@ src/core/ext/client_channel/parse_address.c \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/resolver_result.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \

@ -6818,7 +6818,6 @@
"src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h"
@ -6856,8 +6855,6 @@
"src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/resolver_result.c",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.c",

@ -1306,6 +1306,7 @@
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
@ -1321,6 +1322,7 @@
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",

@ -444,7 +444,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h" />
@ -816,8 +815,6 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.c">

@ -520,9 +520,6 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
@ -1154,9 +1151,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>

@ -410,7 +410,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h" />
@ -734,8 +733,6 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.c">

@ -448,9 +448,6 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
@ -995,9 +992,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>

Loading…
Cancel
Save