|
|
@ -27,7 +27,10 @@ |
|
|
|
|
|
|
|
|
|
|
|
#include "src/core/ext/filters/client_channel/lb_policy_registry.h" |
|
|
|
#include "src/core/ext/filters/client_channel/lb_policy_registry.h" |
|
|
|
#include "src/core/ext/filters/client_channel/server_address.h" |
|
|
|
#include "src/core/ext/filters/client_channel/server_address.h" |
|
|
|
|
|
|
|
// TODO(roth): Should not need the include of subchannel.h here, since
|
|
|
|
|
|
|
|
// that implementation should be hidden from the LB policy API.
|
|
|
|
#include "src/core/ext/filters/client_channel/subchannel.h" |
|
|
|
#include "src/core/ext/filters/client_channel/subchannel.h" |
|
|
|
|
|
|
|
#include "src/core/ext/filters/client_channel/subchannel_interface.h" |
|
|
|
#include "src/core/lib/channel/channel_args.h" |
|
|
|
#include "src/core/lib/channel/channel_args.h" |
|
|
|
#include "src/core/lib/debug/trace.h" |
|
|
|
#include "src/core/lib/debug/trace.h" |
|
|
|
#include "src/core/lib/gprpp/abstract.h" |
|
|
|
#include "src/core/lib/gprpp/abstract.h" |
|
|
@ -88,11 +91,11 @@ class SubchannelData { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Returns a pointer to the subchannel.
|
|
|
|
// Returns a pointer to the subchannel.
|
|
|
|
Subchannel* subchannel() const { return subchannel_; } |
|
|
|
SubchannelInterface* subchannel() const { return subchannel_.get(); } |
|
|
|
|
|
|
|
|
|
|
|
// Returns the connected subchannel. Will be null if the subchannel
|
|
|
|
// Returns the connected subchannel. Will be null if the subchannel
|
|
|
|
// is not connected.
|
|
|
|
// is not connected.
|
|
|
|
ConnectedSubchannel* connected_subchannel() const { |
|
|
|
ConnectedSubchannelInterface* connected_subchannel() const { |
|
|
|
return connected_subchannel_.get(); |
|
|
|
return connected_subchannel_.get(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -102,8 +105,8 @@ class SubchannelData { |
|
|
|
// calling CancelConnectivityWatchLocked()).
|
|
|
|
// calling CancelConnectivityWatchLocked()).
|
|
|
|
grpc_connectivity_state CheckConnectivityStateLocked() { |
|
|
|
grpc_connectivity_state CheckConnectivityStateLocked() { |
|
|
|
GPR_ASSERT(pending_watcher_ == nullptr); |
|
|
|
GPR_ASSERT(pending_watcher_ == nullptr); |
|
|
|
connectivity_state_ = subchannel()->CheckConnectivityState( |
|
|
|
connectivity_state_ = |
|
|
|
subchannel_list_->health_check_service_name(), &connected_subchannel_); |
|
|
|
subchannel()->CheckConnectivityState(&connected_subchannel_); |
|
|
|
return connectivity_state_; |
|
|
|
return connectivity_state_; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -128,7 +131,8 @@ class SubchannelData { |
|
|
|
protected: |
|
|
|
protected: |
|
|
|
SubchannelData( |
|
|
|
SubchannelData( |
|
|
|
SubchannelList<SubchannelListType, SubchannelDataType>* subchannel_list, |
|
|
|
SubchannelList<SubchannelListType, SubchannelDataType>* subchannel_list, |
|
|
|
const ServerAddress& address, Subchannel* subchannel); |
|
|
|
const ServerAddress& address, |
|
|
|
|
|
|
|
RefCountedPtr<SubchannelInterface> subchannel); |
|
|
|
|
|
|
|
|
|
|
|
virtual ~SubchannelData(); |
|
|
|
virtual ~SubchannelData(); |
|
|
|
|
|
|
|
|
|
|
@ -140,7 +144,7 @@ class SubchannelData { |
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
private: |
|
|
|
// Watcher for subchannel connectivity state.
|
|
|
|
// Watcher for subchannel connectivity state.
|
|
|
|
class Watcher : public Subchannel::ConnectivityStateWatcher { |
|
|
|
class Watcher : public SubchannelInterface::ConnectivityStateWatcher { |
|
|
|
public: |
|
|
|
public: |
|
|
|
Watcher( |
|
|
|
Watcher( |
|
|
|
SubchannelData<SubchannelListType, SubchannelDataType>* subchannel_data, |
|
|
|
SubchannelData<SubchannelListType, SubchannelDataType>* subchannel_data, |
|
|
@ -150,9 +154,9 @@ class SubchannelData { |
|
|
|
|
|
|
|
|
|
|
|
~Watcher() { subchannel_list_.reset(DEBUG_LOCATION, "Watcher dtor"); } |
|
|
|
~Watcher() { subchannel_list_.reset(DEBUG_LOCATION, "Watcher dtor"); } |
|
|
|
|
|
|
|
|
|
|
|
void OnConnectivityStateChange( |
|
|
|
void OnConnectivityStateChange(grpc_connectivity_state new_state, |
|
|
|
grpc_connectivity_state new_state, |
|
|
|
RefCountedPtr<ConnectedSubchannelInterface> |
|
|
|
RefCountedPtr<ConnectedSubchannel> connected_subchannel) override; |
|
|
|
connected_subchannel) override; |
|
|
|
|
|
|
|
|
|
|
|
grpc_pollset_set* interested_parties() override { |
|
|
|
grpc_pollset_set* interested_parties() override { |
|
|
|
return subchannel_list_->policy()->interested_parties(); |
|
|
|
return subchannel_list_->policy()->interested_parties(); |
|
|
@ -169,7 +173,7 @@ class SubchannelData { |
|
|
|
RefCountedPtr<SubchannelList<SubchannelListType, SubchannelDataType>> |
|
|
|
RefCountedPtr<SubchannelList<SubchannelListType, SubchannelDataType>> |
|
|
|
subchannel_list, |
|
|
|
subchannel_list, |
|
|
|
grpc_connectivity_state state, |
|
|
|
grpc_connectivity_state state, |
|
|
|
RefCountedPtr<ConnectedSubchannel> connected_subchannel); |
|
|
|
RefCountedPtr<ConnectedSubchannelInterface> connected_subchannel); |
|
|
|
|
|
|
|
|
|
|
|
~Updater() { |
|
|
|
~Updater() { |
|
|
|
subchannel_list_.reset(DEBUG_LOCATION, "Watcher::Updater dtor"); |
|
|
|
subchannel_list_.reset(DEBUG_LOCATION, "Watcher::Updater dtor"); |
|
|
@ -182,7 +186,7 @@ class SubchannelData { |
|
|
|
RefCountedPtr<SubchannelList<SubchannelListType, SubchannelDataType>> |
|
|
|
RefCountedPtr<SubchannelList<SubchannelListType, SubchannelDataType>> |
|
|
|
subchannel_list_; |
|
|
|
subchannel_list_; |
|
|
|
const grpc_connectivity_state state_; |
|
|
|
const grpc_connectivity_state state_; |
|
|
|
RefCountedPtr<ConnectedSubchannel> connected_subchannel_; |
|
|
|
RefCountedPtr<ConnectedSubchannelInterface> connected_subchannel_; |
|
|
|
grpc_closure closure_; |
|
|
|
grpc_closure closure_; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -196,12 +200,12 @@ class SubchannelData { |
|
|
|
// Backpointer to owning subchannel list. Not owned.
|
|
|
|
// Backpointer to owning subchannel list. Not owned.
|
|
|
|
SubchannelList<SubchannelListType, SubchannelDataType>* subchannel_list_; |
|
|
|
SubchannelList<SubchannelListType, SubchannelDataType>* subchannel_list_; |
|
|
|
// The subchannel.
|
|
|
|
// The subchannel.
|
|
|
|
Subchannel* subchannel_; |
|
|
|
RefCountedPtr<SubchannelInterface> subchannel_; |
|
|
|
// Will be non-null when the subchannel's state is being watched.
|
|
|
|
// Will be non-null when the subchannel's state is being watched.
|
|
|
|
Subchannel::ConnectivityStateWatcher* pending_watcher_ = nullptr; |
|
|
|
SubchannelInterface::ConnectivityStateWatcher* pending_watcher_ = nullptr; |
|
|
|
// Data updated by the watcher.
|
|
|
|
// Data updated by the watcher.
|
|
|
|
grpc_connectivity_state connectivity_state_; |
|
|
|
grpc_connectivity_state connectivity_state_; |
|
|
|
RefCountedPtr<ConnectedSubchannel> connected_subchannel_; |
|
|
|
RefCountedPtr<ConnectedSubchannelInterface> connected_subchannel_; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// A list of subchannels.
|
|
|
|
// A list of subchannels.
|
|
|
@ -235,9 +239,6 @@ class SubchannelList : public InternallyRefCounted<SubchannelListType> { |
|
|
|
// Accessors.
|
|
|
|
// Accessors.
|
|
|
|
LoadBalancingPolicy* policy() const { return policy_; } |
|
|
|
LoadBalancingPolicy* policy() const { return policy_; } |
|
|
|
TraceFlag* tracer() const { return tracer_; } |
|
|
|
TraceFlag* tracer() const { return tracer_; } |
|
|
|
const char* health_check_service_name() const { |
|
|
|
|
|
|
|
return health_check_service_name_.get(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Resets connection backoff of all subchannels.
|
|
|
|
// Resets connection backoff of all subchannels.
|
|
|
|
// TODO(roth): We will probably need to rethink this as part of moving
|
|
|
|
// TODO(roth): We will probably need to rethink this as part of moving
|
|
|
@ -275,8 +276,6 @@ class SubchannelList : public InternallyRefCounted<SubchannelListType> { |
|
|
|
|
|
|
|
|
|
|
|
TraceFlag* tracer_; |
|
|
|
TraceFlag* tracer_; |
|
|
|
|
|
|
|
|
|
|
|
UniquePtr<char> health_check_service_name_; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
grpc_combiner* combiner_; |
|
|
|
grpc_combiner* combiner_; |
|
|
|
|
|
|
|
|
|
|
|
// The list of subchannels.
|
|
|
|
// The list of subchannels.
|
|
|
@ -300,7 +299,7 @@ template <typename SubchannelListType, typename SubchannelDataType> |
|
|
|
void SubchannelData<SubchannelListType, SubchannelDataType>::Watcher:: |
|
|
|
void SubchannelData<SubchannelListType, SubchannelDataType>::Watcher:: |
|
|
|
OnConnectivityStateChange( |
|
|
|
OnConnectivityStateChange( |
|
|
|
grpc_connectivity_state new_state, |
|
|
|
grpc_connectivity_state new_state, |
|
|
|
RefCountedPtr<ConnectedSubchannel> connected_subchannel) { |
|
|
|
RefCountedPtr<ConnectedSubchannelInterface> connected_subchannel) { |
|
|
|
// Will delete itself.
|
|
|
|
// Will delete itself.
|
|
|
|
New<Updater>(subchannel_data_, |
|
|
|
New<Updater>(subchannel_data_, |
|
|
|
subchannel_list_->Ref(DEBUG_LOCATION, "Watcher::Updater"), |
|
|
|
subchannel_list_->Ref(DEBUG_LOCATION, "Watcher::Updater"), |
|
|
@ -314,7 +313,7 @@ SubchannelData<SubchannelListType, SubchannelDataType>::Watcher::Updater:: |
|
|
|
RefCountedPtr<SubchannelList<SubchannelListType, SubchannelDataType>> |
|
|
|
RefCountedPtr<SubchannelList<SubchannelListType, SubchannelDataType>> |
|
|
|
subchannel_list, |
|
|
|
subchannel_list, |
|
|
|
grpc_connectivity_state state, |
|
|
|
grpc_connectivity_state state, |
|
|
|
RefCountedPtr<ConnectedSubchannel> connected_subchannel) |
|
|
|
RefCountedPtr<ConnectedSubchannelInterface> connected_subchannel) |
|
|
|
: subchannel_data_(subchannel_data), |
|
|
|
: subchannel_data_(subchannel_data), |
|
|
|
subchannel_list_(std::move(subchannel_list)), |
|
|
|
subchannel_list_(std::move(subchannel_list)), |
|
|
|
state_(state), |
|
|
|
state_(state), |
|
|
@ -336,7 +335,7 @@ void SubchannelData<SubchannelListType, SubchannelDataType>::Watcher::Updater:: |
|
|
|
"connected_subchannel=%p, shutting_down=%d, pending_watcher=%p", |
|
|
|
"connected_subchannel=%p, shutting_down=%d, pending_watcher=%p", |
|
|
|
sd->subchannel_list_->tracer()->name(), |
|
|
|
sd->subchannel_list_->tracer()->name(), |
|
|
|
sd->subchannel_list_->policy(), sd->subchannel_list_, sd->Index(), |
|
|
|
sd->subchannel_list_->policy(), sd->subchannel_list_, sd->Index(), |
|
|
|
sd->subchannel_list_->num_subchannels(), sd->subchannel_, |
|
|
|
sd->subchannel_list_->num_subchannels(), sd->subchannel_.get(), |
|
|
|
grpc_connectivity_state_name(self->state_), |
|
|
|
grpc_connectivity_state_name(self->state_), |
|
|
|
self->connected_subchannel_.get(), |
|
|
|
self->connected_subchannel_.get(), |
|
|
|
sd->subchannel_list_->shutting_down(), sd->pending_watcher_); |
|
|
|
sd->subchannel_list_->shutting_down(), sd->pending_watcher_); |
|
|
@ -360,9 +359,9 @@ void SubchannelData<SubchannelListType, SubchannelDataType>::Watcher::Updater:: |
|
|
|
template <typename SubchannelListType, typename SubchannelDataType> |
|
|
|
template <typename SubchannelListType, typename SubchannelDataType> |
|
|
|
SubchannelData<SubchannelListType, SubchannelDataType>::SubchannelData( |
|
|
|
SubchannelData<SubchannelListType, SubchannelDataType>::SubchannelData( |
|
|
|
SubchannelList<SubchannelListType, SubchannelDataType>* subchannel_list, |
|
|
|
SubchannelList<SubchannelListType, SubchannelDataType>* subchannel_list, |
|
|
|
const ServerAddress& address, Subchannel* subchannel) |
|
|
|
const ServerAddress& address, RefCountedPtr<SubchannelInterface> subchannel) |
|
|
|
: subchannel_list_(subchannel_list), |
|
|
|
: subchannel_list_(subchannel_list), |
|
|
|
subchannel_(subchannel), |
|
|
|
subchannel_(std::move(subchannel)), |
|
|
|
// We assume that the current state is IDLE. If not, we'll get a
|
|
|
|
// We assume that the current state is IDLE. If not, we'll get a
|
|
|
|
// callback telling us that.
|
|
|
|
// callback telling us that.
|
|
|
|
connectivity_state_(GRPC_CHANNEL_IDLE) {} |
|
|
|
connectivity_state_(GRPC_CHANNEL_IDLE) {} |
|
|
@ -382,10 +381,9 @@ void SubchannelData<SubchannelListType, SubchannelDataType>:: |
|
|
|
" (subchannel %p): unreffing subchannel", |
|
|
|
" (subchannel %p): unreffing subchannel", |
|
|
|
subchannel_list_->tracer()->name(), subchannel_list_->policy(), |
|
|
|
subchannel_list_->tracer()->name(), subchannel_list_->policy(), |
|
|
|
subchannel_list_, Index(), subchannel_list_->num_subchannels(), |
|
|
|
subchannel_list_, Index(), subchannel_list_->num_subchannels(), |
|
|
|
subchannel_); |
|
|
|
subchannel_.get()); |
|
|
|
} |
|
|
|
} |
|
|
|
GRPC_SUBCHANNEL_UNREF(subchannel_, reason); |
|
|
|
subchannel_.reset(); |
|
|
|
subchannel_ = nullptr; |
|
|
|
|
|
|
|
connected_subchannel_.reset(); |
|
|
|
connected_subchannel_.reset(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -407,16 +405,16 @@ void SubchannelData<SubchannelListType, |
|
|
|
" (subchannel %p): starting watch (from %s)", |
|
|
|
" (subchannel %p): starting watch (from %s)", |
|
|
|
subchannel_list_->tracer()->name(), subchannel_list_->policy(), |
|
|
|
subchannel_list_->tracer()->name(), subchannel_list_->policy(), |
|
|
|
subchannel_list_, Index(), subchannel_list_->num_subchannels(), |
|
|
|
subchannel_list_, Index(), subchannel_list_->num_subchannels(), |
|
|
|
subchannel_, grpc_connectivity_state_name(connectivity_state_)); |
|
|
|
subchannel_.get(), |
|
|
|
|
|
|
|
grpc_connectivity_state_name(connectivity_state_)); |
|
|
|
} |
|
|
|
} |
|
|
|
GPR_ASSERT(pending_watcher_ == nullptr); |
|
|
|
GPR_ASSERT(pending_watcher_ == nullptr); |
|
|
|
pending_watcher_ = |
|
|
|
pending_watcher_ = |
|
|
|
New<Watcher>(this, subchannel_list()->Ref(DEBUG_LOCATION, "Watcher")); |
|
|
|
New<Watcher>(this, subchannel_list()->Ref(DEBUG_LOCATION, "Watcher")); |
|
|
|
subchannel_->WatchConnectivityState( |
|
|
|
subchannel_->WatchConnectivityState( |
|
|
|
connectivity_state_, |
|
|
|
connectivity_state_, |
|
|
|
UniquePtr<char>( |
|
|
|
UniquePtr<SubchannelInterface::ConnectivityStateWatcher>( |
|
|
|
gpr_strdup(subchannel_list_->health_check_service_name())), |
|
|
|
pending_watcher_)); |
|
|
|
UniquePtr<Subchannel::ConnectivityStateWatcher>(pending_watcher_)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template <typename SubchannelListType, typename SubchannelDataType> |
|
|
|
template <typename SubchannelListType, typename SubchannelDataType> |
|
|
@ -428,11 +426,10 @@ void SubchannelData<SubchannelListType, SubchannelDataType>:: |
|
|
|
" (subchannel %p): canceling connectivity watch (%s)", |
|
|
|
" (subchannel %p): canceling connectivity watch (%s)", |
|
|
|
subchannel_list_->tracer()->name(), subchannel_list_->policy(), |
|
|
|
subchannel_list_->tracer()->name(), subchannel_list_->policy(), |
|
|
|
subchannel_list_, Index(), subchannel_list_->num_subchannels(), |
|
|
|
subchannel_list_, Index(), subchannel_list_->num_subchannels(), |
|
|
|
subchannel_, reason); |
|
|
|
subchannel_.get(), reason); |
|
|
|
} |
|
|
|
} |
|
|
|
if (pending_watcher_ != nullptr) { |
|
|
|
if (pending_watcher_ != nullptr) { |
|
|
|
subchannel_->CancelConnectivityStateWatch( |
|
|
|
subchannel_->CancelConnectivityStateWatch(pending_watcher_); |
|
|
|
subchannel_list_->health_check_service_name(), pending_watcher_); |
|
|
|
|
|
|
|
pending_watcher_ = nullptr; |
|
|
|
pending_watcher_ = nullptr; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -463,25 +460,12 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList( |
|
|
|
tracer_->name(), policy, this, addresses.size()); |
|
|
|
tracer_->name(), policy, this, addresses.size()); |
|
|
|
} |
|
|
|
} |
|
|
|
subchannels_.reserve(addresses.size()); |
|
|
|
subchannels_.reserve(addresses.size()); |
|
|
|
// Find health check service name.
|
|
|
|
|
|
|
|
const bool inhibit_health_checking = grpc_channel_arg_get_bool( |
|
|
|
|
|
|
|
grpc_channel_args_find(&args, GRPC_ARG_INHIBIT_HEALTH_CHECKING), false); |
|
|
|
|
|
|
|
if (!inhibit_health_checking) { |
|
|
|
|
|
|
|
const char* health_check_service_name = grpc_channel_arg_get_string( |
|
|
|
|
|
|
|
grpc_channel_args_find(&args, "grpc.temp.health_check")); |
|
|
|
|
|
|
|
if (health_check_service_name != nullptr) { |
|
|
|
|
|
|
|
health_check_service_name_.reset(gpr_strdup(health_check_service_name)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// We need to remove the LB addresses in order to be able to compare the
|
|
|
|
// We need to remove the LB addresses in order to be able to compare the
|
|
|
|
// subchannel keys of subchannels from a different batch of addresses.
|
|
|
|
// subchannel keys of subchannels from a different batch of addresses.
|
|
|
|
// We also remove the health-checking-related args, since we are
|
|
|
|
|
|
|
|
// handling that here.
|
|
|
|
|
|
|
|
// We remove the service config, since it will be passed into the
|
|
|
|
// We remove the service config, since it will be passed into the
|
|
|
|
// subchannel via call context.
|
|
|
|
// subchannel via call context.
|
|
|
|
static const char* keys_to_remove[] = { |
|
|
|
static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS, |
|
|
|
GRPC_ARG_SUBCHANNEL_ADDRESS, "grpc.temp.health_check", |
|
|
|
GRPC_ARG_SERVICE_CONFIG}; |
|
|
|
GRPC_ARG_INHIBIT_HEALTH_CHECKING, GRPC_ARG_SERVICE_CONFIG}; |
|
|
|
|
|
|
|
// Create a subchannel for each address.
|
|
|
|
// Create a subchannel for each address.
|
|
|
|
for (size_t i = 0; i < addresses.size(); i++) { |
|
|
|
for (size_t i = 0; i < addresses.size(); i++) { |
|
|
|
// TODO(roth): we should ideally hide this from the LB policy code. In
|
|
|
|
// TODO(roth): we should ideally hide this from the LB policy code. In
|
|
|
@ -504,7 +488,8 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList( |
|
|
|
&args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), |
|
|
|
&args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), |
|
|
|
args_to_add.data(), args_to_add.size()); |
|
|
|
args_to_add.data(), args_to_add.size()); |
|
|
|
gpr_free(args_to_add[subchannel_address_arg_index].value.string); |
|
|
|
gpr_free(args_to_add[subchannel_address_arg_index].value.string); |
|
|
|
Subchannel* subchannel = helper->CreateSubchannel(*new_args); |
|
|
|
RefCountedPtr<SubchannelInterface> subchannel = |
|
|
|
|
|
|
|
helper->CreateSubchannel(*new_args); |
|
|
|
grpc_channel_args_destroy(new_args); |
|
|
|
grpc_channel_args_destroy(new_args); |
|
|
|
if (subchannel == nullptr) { |
|
|
|
if (subchannel == nullptr) { |
|
|
|
// Subchannel could not be created.
|
|
|
|
// Subchannel could not be created.
|
|
|
@ -523,11 +508,11 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList( |
|
|
|
gpr_log(GPR_INFO, |
|
|
|
gpr_log(GPR_INFO, |
|
|
|
"[%s %p] subchannel list %p index %" PRIuPTR |
|
|
|
"[%s %p] subchannel list %p index %" PRIuPTR |
|
|
|
": Created subchannel %p for address uri %s", |
|
|
|
": Created subchannel %p for address uri %s", |
|
|
|
tracer_->name(), policy_, this, subchannels_.size(), subchannel, |
|
|
|
tracer_->name(), policy_, this, subchannels_.size(), |
|
|
|
address_uri); |
|
|
|
subchannel.get(), address_uri); |
|
|
|
gpr_free(address_uri); |
|
|
|
gpr_free(address_uri); |
|
|
|
} |
|
|
|
} |
|
|
|
subchannels_.emplace_back(this, addresses[i], subchannel); |
|
|
|
subchannels_.emplace_back(this, addresses[i], std::move(subchannel)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|