mirror of https://github.com/grpc/grpc.git
parent
6a7863ae37
commit
bbe2587c39
35 changed files with 832 additions and 79 deletions
@ -0,0 +1,177 @@ |
||||
//
|
||||
//
|
||||
// Copyright 2018 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
//
|
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/global_subchannel_pool.h" |
||||
|
||||
#include "src/core/ext/filters/client_channel/subchannel.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
GlobalSubchannelPool::GlobalSubchannelPool() { |
||||
subchannel_map_ = grpc_avl_create(&subchannel_avl_vtable_); |
||||
gpr_mu_init(&mu_); |
||||
} |
||||
|
||||
GlobalSubchannelPool::~GlobalSubchannelPool() { |
||||
gpr_mu_destroy(&mu_); |
||||
grpc_avl_unref(subchannel_map_, nullptr); |
||||
} |
||||
|
||||
void GlobalSubchannelPool::Init() { |
||||
instance_ = New<RefCountedPtr<GlobalSubchannelPool>>( |
||||
MakeRefCounted<GlobalSubchannelPool>()); |
||||
} |
||||
|
||||
void GlobalSubchannelPool::Shutdown() { |
||||
// To ensure Init() was called before.
|
||||
GPR_ASSERT(instance_ != nullptr); |
||||
// To ensure Shutdown() was not called before.
|
||||
GPR_ASSERT(*instance_ != nullptr); |
||||
instance_->reset(); |
||||
Delete(instance_); |
||||
} |
||||
|
||||
RefCountedPtr<GlobalSubchannelPool> GlobalSubchannelPool::instance() { |
||||
GPR_ASSERT(instance_ != nullptr); |
||||
GPR_ASSERT(*instance_ != nullptr); |
||||
return *instance_; |
||||
} |
||||
|
||||
grpc_subchannel* GlobalSubchannelPool::RegisterSubchannel( |
||||
SubchannelKey* key, grpc_subchannel* constructed) { |
||||
grpc_subchannel* c = nullptr; |
||||
// Compare and swap (CAS) loop:
|
||||
while (c == nullptr) { |
||||
// Ref the shared map to have a local copy.
|
||||
gpr_mu_lock(&mu_); |
||||
grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr); |
||||
gpr_mu_unlock(&mu_); |
||||
// Check to see if a subchannel already exists.
|
||||
c = static_cast<grpc_subchannel*>(grpc_avl_get(old_map, key, nullptr)); |
||||
if (c != nullptr) { |
||||
// The subchannel already exists. Reuse it.
|
||||
c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "subchannel_register+reuse"); |
||||
GRPC_SUBCHANNEL_UNREF(constructed, "subchannel_register+found_existing"); |
||||
// Exit the CAS loop without modifying the shared map.
|
||||
} else { |
||||
// There hasn't been such subchannel. Add one.
|
||||
// Note that we should ref the old map first because grpc_avl_add() will
|
||||
// unref it while we still need to access it later.
|
||||
grpc_avl new_map = grpc_avl_add( |
||||
grpc_avl_ref(old_map, nullptr), New<SubchannelKey>(*key), |
||||
GRPC_SUBCHANNEL_WEAK_REF(constructed, "subchannel_register+new"), |
||||
nullptr); |
||||
// Try to publish the change to the shared map. It may happen (but
|
||||
// unlikely) that some other thread has changed the shared map, so compare
|
||||
// to make sure it's unchanged before swapping. Retry if it's changed.
|
||||
gpr_mu_lock(&mu_); |
||||
if (old_map.root == subchannel_map_.root) { |
||||
GPR_SWAP(grpc_avl, new_map, subchannel_map_); |
||||
c = constructed; |
||||
} |
||||
gpr_mu_unlock(&mu_); |
||||
grpc_avl_unref(new_map, nullptr); |
||||
} |
||||
grpc_avl_unref(old_map, nullptr); |
||||
} |
||||
return c; |
||||
} |
||||
|
||||
void GlobalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) { |
||||
bool done = false; |
||||
// Compare and swap (CAS) loop:
|
||||
while (!done) { |
||||
// Ref the shared map to have a local copy.
|
||||
gpr_mu_lock(&mu_); |
||||
grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr); |
||||
gpr_mu_unlock(&mu_); |
||||
// Remove the subchannel.
|
||||
// Note that we should ref the old map first because grpc_avl_remove() will
|
||||
// unref it while we still need to access it later.
|
||||
grpc_avl new_map = |
||||
grpc_avl_remove(grpc_avl_ref(old_map, nullptr), key, nullptr); |
||||
// Try to publish the change to the shared map. It may happen (but
|
||||
// unlikely) that some other thread has changed the shared map, so compare
|
||||
// to make sure it's unchanged before swapping. Retry if it's changed.
|
||||
gpr_mu_lock(&mu_); |
||||
if (old_map.root == subchannel_map_.root) { |
||||
GPR_SWAP(grpc_avl, new_map, subchannel_map_); |
||||
done = true; |
||||
} |
||||
gpr_mu_unlock(&mu_); |
||||
grpc_avl_unref(new_map, nullptr); |
||||
grpc_avl_unref(old_map, nullptr); |
||||
} |
||||
} |
||||
|
||||
grpc_subchannel* GlobalSubchannelPool::FindSubchannel(SubchannelKey* key) { |
||||
// Lock, and take a reference to the subchannel map.
|
||||
// We don't need to do the search under a lock as AVL's are immutable.
|
||||
gpr_mu_lock(&mu_); |
||||
grpc_avl index = grpc_avl_ref(subchannel_map_, nullptr); |
||||
gpr_mu_unlock(&mu_); |
||||
grpc_subchannel* c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF( |
||||
static_cast<grpc_subchannel*>(grpc_avl_get(index, key, nullptr)), |
||||
"found_from_pool"); |
||||
grpc_avl_unref(index, nullptr); |
||||
return c; |
||||
} |
||||
|
||||
RefCountedPtr<GlobalSubchannelPool>* GlobalSubchannelPool::instance_ = nullptr; |
||||
|
||||
namespace { |
||||
|
||||
void sck_avl_destroy(void* p, void* user_data) { |
||||
SubchannelKey* key = static_cast<SubchannelKey*>(p); |
||||
Delete(key); |
||||
} |
||||
|
||||
void* sck_avl_copy(void* p, void* unused) { |
||||
const SubchannelKey* key = static_cast<const SubchannelKey*>(p); |
||||
auto* new_key = New<SubchannelKey>(*key); |
||||
return static_cast<void*>(new_key); |
||||
} |
||||
|
||||
long sck_avl_compare(void* a, void* b, void* unused) { |
||||
const SubchannelKey* key_a = static_cast<const SubchannelKey*>(a); |
||||
const SubchannelKey* key_b = static_cast<const SubchannelKey*>(b); |
||||
return key_a->Cmp(*key_b); |
||||
} |
||||
|
||||
void scv_avl_destroy(void* p, void* user_data) { |
||||
GRPC_SUBCHANNEL_WEAK_UNREF((grpc_subchannel*)p, "global_subchannel_pool"); |
||||
} |
||||
|
||||
void* scv_avl_copy(void* p, void* unused) { |
||||
GRPC_SUBCHANNEL_WEAK_REF((grpc_subchannel*)p, "global_subchannel_pool"); |
||||
return p; |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
const grpc_avl_vtable GlobalSubchannelPool::subchannel_avl_vtable_ = { |
||||
sck_avl_destroy, // destroy_key
|
||||
sck_avl_copy, // copy_key
|
||||
sck_avl_compare, // compare_keys
|
||||
scv_avl_destroy, // destroy_value
|
||||
scv_avl_copy // copy_value
|
||||
}; |
||||
|
||||
} // namespace grpc_core
|
@ -0,0 +1,68 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_GLOBAL_SUBCHANNEL_POOL_H |
||||
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_GLOBAL_SUBCHANNEL_POOL_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
// The global subchannel pool. It shares subchannels among channels. There
|
||||
// should be only one instance of this class. Init() should be called once at
|
||||
// the filter initialization time; Shutdown() should be called once at the
|
||||
// filter shutdown time.
|
||||
// TODO(juanlishen): Enable subchannel retention.
|
||||
class GlobalSubchannelPool final : public SubchannelPoolInterface { |
||||
public: |
||||
// The ctor and dtor are not intended to use directly.
|
||||
GlobalSubchannelPool(); |
||||
~GlobalSubchannelPool() override; |
||||
|
||||
// Should be called exactly once at filter initialization time.
|
||||
static void Init(); |
||||
// Should be called exactly once at filter shutdown time.
|
||||
static void Shutdown(); |
||||
|
||||
// Gets the singleton instance.
|
||||
static RefCountedPtr<GlobalSubchannelPool> instance(); |
||||
|
||||
// Implements interface methods.
|
||||
grpc_subchannel* RegisterSubchannel(SubchannelKey* key, |
||||
grpc_subchannel* constructed) override; |
||||
void UnregisterSubchannel(SubchannelKey* key) override; |
||||
grpc_subchannel* FindSubchannel(SubchannelKey* key) override; |
||||
|
||||
private: |
||||
// The singleton instance. (It's a pointer to RefCountedPtr so that this
|
||||
// non-local static object can be trivially destructible.)
|
||||
static RefCountedPtr<GlobalSubchannelPool>* instance_; |
||||
|
||||
// The vtable for subchannel operations in an AVL tree.
|
||||
static const grpc_avl_vtable subchannel_avl_vtable_; |
||||
// A map from subchannel key to subchannel.
|
||||
grpc_avl subchannel_map_; |
||||
// To protect subchannel_map_.
|
||||
gpr_mu mu_; |
||||
}; |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_GLOBAL_SUBCHANNEL_POOL_H */ |
@ -0,0 +1,96 @@ |
||||
//
|
||||
//
|
||||
// Copyright 2018 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
//
|
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/local_subchannel_pool.h" |
||||
|
||||
#include "src/core/ext/filters/client_channel/subchannel.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
LocalSubchannelPool::LocalSubchannelPool() { |
||||
subchannel_map_ = grpc_avl_create(&subchannel_avl_vtable_); |
||||
} |
||||
|
||||
LocalSubchannelPool::~LocalSubchannelPool() { |
||||
grpc_avl_unref(subchannel_map_, nullptr); |
||||
} |
||||
|
||||
grpc_subchannel* LocalSubchannelPool::RegisterSubchannel( |
||||
SubchannelKey* key, grpc_subchannel* constructed) { |
||||
// Check to see if a subchannel already exists.
|
||||
grpc_subchannel* c = static_cast<grpc_subchannel*>( |
||||
grpc_avl_get(subchannel_map_, key, nullptr)); |
||||
if (c != nullptr) { |
||||
// The subchannel already exists. Reuse it.
|
||||
c = GRPC_SUBCHANNEL_REF(c, "subchannel_register+reuse"); |
||||
GRPC_SUBCHANNEL_UNREF(constructed, "subchannel_register+found_existing"); |
||||
} else { |
||||
// There hasn't been such subchannel. Add one.
|
||||
subchannel_map_ = grpc_avl_add(subchannel_map_, New<SubchannelKey>(*key), |
||||
constructed, nullptr); |
||||
c = constructed; |
||||
} |
||||
return c; |
||||
} |
||||
|
||||
void LocalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) { |
||||
subchannel_map_ = grpc_avl_remove(subchannel_map_, key, nullptr); |
||||
} |
||||
|
||||
grpc_subchannel* LocalSubchannelPool::FindSubchannel(SubchannelKey* key) { |
||||
grpc_subchannel* c = static_cast<grpc_subchannel*>( |
||||
grpc_avl_get(subchannel_map_, key, nullptr)); |
||||
return c == nullptr ? c : GRPC_SUBCHANNEL_REF(c, "found_from_pool"); |
||||
} |
||||
|
||||
namespace { |
||||
|
||||
void sck_avl_destroy(void* p, void* user_data) { |
||||
SubchannelKey* key = static_cast<SubchannelKey*>(p); |
||||
Delete(key); |
||||
} |
||||
|
||||
void* sck_avl_copy(void* p, void* unused) { |
||||
const SubchannelKey* key = static_cast<const SubchannelKey*>(p); |
||||
auto new_key = New<SubchannelKey>(*key); |
||||
return static_cast<void*>(new_key); |
||||
} |
||||
|
||||
long sck_avl_compare(void* a, void* b, void* unused) { |
||||
const SubchannelKey* key_a = static_cast<const SubchannelKey*>(a); |
||||
const SubchannelKey* key_b = static_cast<const SubchannelKey*>(b); |
||||
return key_a->Cmp(*key_b); |
||||
} |
||||
|
||||
void scv_avl_destroy(void* p, void* user_data) {} |
||||
|
||||
void* scv_avl_copy(void* p, void* unused) { return p; } |
||||
|
||||
} // namespace
|
||||
|
||||
const grpc_avl_vtable LocalSubchannelPool::subchannel_avl_vtable_ = { |
||||
sck_avl_destroy, // destroy_key
|
||||
sck_avl_copy, // copy_key
|
||||
sck_avl_compare, // compare_keys
|
||||
scv_avl_destroy, // destroy_value
|
||||
scv_avl_copy // copy_value
|
||||
}; |
||||
|
||||
} // namespace grpc_core
|
@ -0,0 +1,56 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LOCAL_SUBCHANNEL_POOL_H |
||||
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LOCAL_SUBCHANNEL_POOL_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
// The local subchannel pool that is owned by a single channel. It doesn't
|
||||
// support subchannel sharing with other channels by nature. Nor does it support
|
||||
// subchannel retention when a subchannel is not used. The only real purpose of
|
||||
// using this subchannel pool is to allow subchannel reuse within the channel
|
||||
// when an incoming resolver update contains some addresses for which the
|
||||
// channel has already created subchannels.
|
||||
// Thread-unsafe.
|
||||
class LocalSubchannelPool final : public SubchannelPoolInterface { |
||||
public: |
||||
LocalSubchannelPool(); |
||||
~LocalSubchannelPool() override; |
||||
|
||||
// Implements interface methods.
|
||||
// Thread-unsafe. Intended to be invoked within the client_channel combiner.
|
||||
grpc_subchannel* RegisterSubchannel(SubchannelKey* key, |
||||
grpc_subchannel* constructed) override; |
||||
void UnregisterSubchannel(SubchannelKey* key) override; |
||||
grpc_subchannel* FindSubchannel(SubchannelKey* key) override; |
||||
|
||||
private: |
||||
// The vtable for subchannel operations in an AVL tree.
|
||||
static const grpc_avl_vtable subchannel_avl_vtable_; |
||||
// A map from subchannel key to subchannel.
|
||||
grpc_avl subchannel_map_; |
||||
}; |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LOCAL_SUBCHANNEL_POOL_H */ |
@ -0,0 +1,97 @@ |
||||
//
|
||||
//
|
||||
// Copyright 2018 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
//
|
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" |
||||
|
||||
#include "src/core/lib/gpr/useful.h" |
||||
|
||||
// The subchannel pool to reuse subchannels.
|
||||
#define GRPC_ARG_SUBCHANNEL_POOL "grpc.subchannel_pool" |
||||
// The subchannel key ID that is only used in test to make each key unique.
|
||||
#define GRPC_ARG_SUBCHANNEL_KEY_TEST_ONLY_ID "grpc.subchannel_key_test_only_id" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
TraceFlag grpc_subchannel_pool_trace(false, "subchannel_pool"); |
||||
|
||||
SubchannelKey::SubchannelKey(const grpc_channel_args* args) { |
||||
Init(args, grpc_channel_args_normalize); |
||||
} |
||||
|
||||
SubchannelKey::~SubchannelKey() { |
||||
grpc_channel_args_destroy(const_cast<grpc_channel_args*>(args_)); |
||||
} |
||||
|
||||
SubchannelKey::SubchannelKey(const SubchannelKey& other) { |
||||
Init(other.args_, grpc_channel_args_copy); |
||||
} |
||||
|
||||
SubchannelKey& SubchannelKey::operator=(const SubchannelKey& other) { |
||||
grpc_channel_args_destroy(const_cast<grpc_channel_args*>(args_)); |
||||
Init(other.args_, grpc_channel_args_copy); |
||||
return *this; |
||||
} |
||||
|
||||
int SubchannelKey::Cmp(const SubchannelKey& other) const { |
||||
return grpc_channel_args_compare(args_, other.args_); |
||||
} |
||||
|
||||
void SubchannelKey::Init( |
||||
const grpc_channel_args* args, |
||||
grpc_channel_args* (*copy_channel_args)(const grpc_channel_args* args)) { |
||||
args_ = copy_channel_args(args); |
||||
} |
||||
|
||||
namespace { |
||||
|
||||
void* arg_copy(void* p) { |
||||
auto* subchannel_pool = static_cast<SubchannelPoolInterface*>(p); |
||||
subchannel_pool->Ref().release(); |
||||
return p; |
||||
} |
||||
|
||||
void arg_destroy(void* p) { |
||||
auto* subchannel_pool = static_cast<SubchannelPoolInterface*>(p); |
||||
subchannel_pool->Unref(); |
||||
} |
||||
|
||||
int arg_cmp(void* a, void* b) { return GPR_ICMP(a, b); } |
||||
|
||||
const grpc_arg_pointer_vtable subchannel_pool_arg_vtable = { |
||||
arg_copy, arg_destroy, arg_cmp}; |
||||
|
||||
} // namespace
|
||||
|
||||
grpc_arg SubchannelPoolInterface::CreateChannelArg( |
||||
SubchannelPoolInterface* subchannel_pool) { |
||||
return grpc_channel_arg_pointer_create( |
||||
const_cast<char*>(GRPC_ARG_SUBCHANNEL_POOL), subchannel_pool, |
||||
&subchannel_pool_arg_vtable); |
||||
} |
||||
|
||||
SubchannelPoolInterface* |
||||
SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs( |
||||
const grpc_channel_args* args) { |
||||
const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_POOL); |
||||
if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr; |
||||
return static_cast<SubchannelPoolInterface*>(arg->value.pointer.p); |
||||
} |
||||
|
||||
} // namespace grpc_core
|
@ -0,0 +1,94 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_POOL_INTERFACE_H |
||||
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_POOL_INTERFACE_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/avl/avl.h" |
||||
#include "src/core/lib/channel/channel_args.h" |
||||
#include "src/core/lib/gprpp/abstract.h" |
||||
#include "src/core/lib/gprpp/ref_counted.h" |
||||
|
||||
struct grpc_subchannel; |
||||
|
||||
namespace grpc_core { |
||||
|
||||
extern TraceFlag grpc_subchannel_pool_trace; |
||||
|
||||
// A key that can uniquely identify a subchannel.
|
||||
class SubchannelKey { |
||||
public: |
||||
explicit SubchannelKey(const grpc_channel_args* args); |
||||
~SubchannelKey(); |
||||
|
||||
// Copyable.
|
||||
SubchannelKey(const SubchannelKey& other); |
||||
SubchannelKey& operator=(const SubchannelKey& other); |
||||
// Not movable.
|
||||
SubchannelKey(SubchannelKey&&) = delete; |
||||
SubchannelKey& operator=(SubchannelKey&&) = delete; |
||||
|
||||
int Cmp(const SubchannelKey& other) const; |
||||
|
||||
private: |
||||
// Initializes the subchannel key with the given \a args and the function to
|
||||
// copy channel args.
|
||||
void Init( |
||||
const grpc_channel_args* args, |
||||
grpc_channel_args* (*copy_channel_args)(const grpc_channel_args* args)); |
||||
|
||||
const grpc_channel_args* args_; |
||||
}; |
||||
|
||||
// Interface for subchannel pool.
|
||||
// TODO(juanlishen): This refcounting mechanism may lead to memory leak.
|
||||
// To solve that, we should force polling to flush any pending callbacks, then
|
||||
// shut down safely. See https://github.com/grpc/grpc/issues/12560.
|
||||
class SubchannelPoolInterface : public RefCounted<SubchannelPoolInterface> { |
||||
public: |
||||
SubchannelPoolInterface() : RefCounted(&grpc_subchannel_pool_trace) {} |
||||
virtual ~SubchannelPoolInterface() {} |
||||
|
||||
// Registers a subchannel against a key. Returns the subchannel registered
|
||||
// with \a key, which may be different from \a constructed because we reuse
|
||||
// (instead of update) any existing subchannel already registered with \a key.
|
||||
virtual grpc_subchannel* RegisterSubchannel( |
||||
SubchannelKey* key, grpc_subchannel* constructed) GRPC_ABSTRACT; |
||||
|
||||
// Removes the registered subchannel found by \a key.
|
||||
virtual void UnregisterSubchannel(SubchannelKey* key) GRPC_ABSTRACT; |
||||
|
||||
// Finds the subchannel registered for the given subchannel key. Returns NULL
|
||||
// if no such channel exists. Thread-safe.
|
||||
virtual grpc_subchannel* FindSubchannel(SubchannelKey* key) GRPC_ABSTRACT; |
||||
|
||||
// Creates a channel arg from \a subchannel pool.
|
||||
static grpc_arg CreateChannelArg(SubchannelPoolInterface* subchannel_pool); |
||||
|
||||
// Gets the subchannel pool from the channel args.
|
||||
static SubchannelPoolInterface* GetSubchannelPoolFromChannelArgs( |
||||
const grpc_channel_args* args); |
||||
|
||||
GRPC_ABSTRACT_BASE_CLASS |
||||
}; |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_POOL_INTERFACE_H */ |
Loading…
Reference in new issue