Merge pull request #15341 from ncteisen/registry++
C++-ify the ChannelzRegistry, Adds Generic Object Supportpull/15124/merge
commit
654ecedd03
25 changed files with 505 additions and 170 deletions
@ -1,80 +0,0 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2017 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/impl/codegen/port_platform.h> |
||||
|
||||
#include "src/core/lib/avl/avl.h" |
||||
#include "src/core/lib/channel/channel_trace.h" |
||||
#include "src/core/lib/channel/channel_trace_registry.h" |
||||
#include "src/core/lib/gpr/useful.h" |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
// file global lock and avl.
|
||||
static gpr_mu g_mu; |
||||
static grpc_avl g_avl; |
||||
static gpr_atm g_uuid = 0; |
||||
|
||||
// avl vtable for uuid (intptr_t) -> ChannelTrace
|
||||
// this table is only looking, it does not own anything.
|
||||
static void destroy_intptr(void* not_used, void* user_data) {} |
||||
static void* copy_intptr(void* key, void* user_data) { return key; } |
||||
static long compare_intptr(void* key1, void* key2, void* user_data) { |
||||
return GPR_ICMP(key1, key2); |
||||
} |
||||
|
||||
static void destroy_channel_trace(void* trace, void* user_data) {} |
||||
static void* copy_channel_trace(void* trace, void* user_data) { return trace; } |
||||
static const grpc_avl_vtable avl_vtable = { |
||||
destroy_intptr, copy_intptr, compare_intptr, destroy_channel_trace, |
||||
copy_channel_trace}; |
||||
|
||||
void grpc_channel_trace_registry_init() { |
||||
gpr_mu_init(&g_mu); |
||||
g_avl = grpc_avl_create(&avl_vtable); |
||||
} |
||||
|
||||
void grpc_channel_trace_registry_shutdown() { |
||||
grpc_avl_unref(g_avl, nullptr); |
||||
gpr_mu_destroy(&g_mu); |
||||
} |
||||
|
||||
intptr_t grpc_channel_trace_registry_register_channel_trace( |
||||
grpc_core::ChannelTrace* channel_trace) { |
||||
intptr_t prior = gpr_atm_no_barrier_fetch_add(&g_uuid, 1); |
||||
gpr_mu_lock(&g_mu); |
||||
g_avl = grpc_avl_add(g_avl, (void*)prior, channel_trace, nullptr); |
||||
gpr_mu_unlock(&g_mu); |
||||
return prior; |
||||
} |
||||
|
||||
void grpc_channel_trace_registry_unregister_channel_trace(intptr_t uuid) { |
||||
gpr_mu_lock(&g_mu); |
||||
g_avl = grpc_avl_remove(g_avl, (void*)uuid, nullptr); |
||||
gpr_mu_unlock(&g_mu); |
||||
} |
||||
|
||||
grpc_core::ChannelTrace* grpc_channel_trace_registry_get_channel_trace( |
||||
intptr_t uuid) { |
||||
gpr_mu_lock(&g_mu); |
||||
grpc_core::ChannelTrace* ret = static_cast<grpc_core::ChannelTrace*>( |
||||
grpc_avl_get(g_avl, (void*)uuid, nullptr)); |
||||
gpr_mu_unlock(&g_mu); |
||||
return ret; |
||||
} |
@ -1,43 +0,0 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2017 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_LIB_CHANNEL_CHANNEL_TRACE_REGISTRY_H |
||||
#define GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_REGISTRY_H |
||||
|
||||
#include <grpc/impl/codegen/port_platform.h> |
||||
|
||||
#include "src/core/lib/channel/channel_trace.h" |
||||
|
||||
#include <stdint.h> |
||||
|
||||
// TODO(ncteisen): convert this file to C++
|
||||
|
||||
void grpc_channel_trace_registry_init(); |
||||
void grpc_channel_trace_registry_shutdown(); |
||||
|
||||
// globally registers a ChannelTrace. Returns its unique uuid
|
||||
intptr_t grpc_channel_trace_registry_register_channel_trace( |
||||
grpc_core::ChannelTrace* channel_trace); |
||||
// globally unregisters the ChannelTrace that is associated to uuid.
|
||||
void grpc_channel_trace_registry_unregister_channel_trace(intptr_t uuid); |
||||
// if object with uuid has previously been registered, returns the ChannelTrace
|
||||
// associated with that uuid. Else returns nullptr.
|
||||
grpc_core::ChannelTrace* grpc_channel_trace_registry_get_channel_trace( |
||||
intptr_t uuid); |
||||
|
||||
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_REGISTRY_H */ |
@ -0,0 +1,77 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2017 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/impl/codegen/port_platform.h> |
||||
|
||||
#include "src/core/lib/channel/channel_trace.h" |
||||
#include "src/core/lib/channel/channelz_registry.h" |
||||
#include "src/core/lib/gpr/useful.h" |
||||
#include "src/core/lib/gprpp/memory.h" |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
namespace grpc_core { |
||||
namespace { |
||||
|
||||
// singleton instance of the registry.
|
||||
ChannelzRegistry* g_channelz_registry = nullptr; |
||||
|
||||
// avl vtable for uuid (intptr_t) -> channelz_obj (void*)
|
||||
// this table is only looking, it does not own anything.
|
||||
void destroy_intptr(void* not_used, void* user_data) {} |
||||
void* copy_intptr(void* key, void* user_data) { return key; } |
||||
long compare_intptr(void* key1, void* key2, void* user_data) { |
||||
return GPR_ICMP(key1, key2); |
||||
} |
||||
|
||||
void destroy_channelz_obj(void* channelz_obj, void* user_data) {} |
||||
void* copy_channelz_obj(void* channelz_obj, void* user_data) { |
||||
return channelz_obj; |
||||
} |
||||
const grpc_avl_vtable avl_vtable = {destroy_intptr, copy_intptr, compare_intptr, |
||||
destroy_channelz_obj, copy_channelz_obj}; |
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void ChannelzRegistry::Init() { g_channelz_registry = New<ChannelzRegistry>(); } |
||||
|
||||
void ChannelzRegistry::Shutdown() { Delete(g_channelz_registry); } |
||||
|
||||
ChannelzRegistry* ChannelzRegistry::Default() { |
||||
GPR_DEBUG_ASSERT(g_channelz_registry != nullptr); |
||||
return g_channelz_registry; |
||||
} |
||||
|
||||
ChannelzRegistry::ChannelzRegistry() : uuid_(1) { |
||||
gpr_mu_init(&mu_); |
||||
avl_ = grpc_avl_create(&avl_vtable); |
||||
} |
||||
|
||||
ChannelzRegistry::~ChannelzRegistry() { |
||||
grpc_avl_unref(avl_, nullptr); |
||||
gpr_mu_destroy(&mu_); |
||||
} |
||||
|
||||
void ChannelzRegistry::InternalUnregister(intptr_t uuid) { |
||||
gpr_mu_lock(&mu_); |
||||
avl_ = grpc_avl_remove(avl_, (void*)uuid, nullptr); |
||||
gpr_mu_unlock(&mu_); |
||||
} |
||||
|
||||
} // namespace grpc_core
|
@ -0,0 +1,99 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2017 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_LIB_CHANNEL_CHANNELZ_REGISTRY_H |
||||
#define GRPC_CORE_LIB_CHANNEL_CHANNELZ_REGISTRY_H |
||||
|
||||
#include <grpc/impl/codegen/port_platform.h> |
||||
|
||||
#include "src/core/lib/avl/avl.h" |
||||
#include "src/core/lib/channel/channel_trace.h" |
||||
|
||||
#include <stdint.h> |
||||
|
||||
namespace grpc_core { |
||||
|
||||
// singleton registry object to track all objects that are needed to support
|
||||
// channelz bookkeeping. All objects share globally distributed uuids.
|
||||
class ChannelzRegistry { |
||||
public: |
||||
// To be called in grpc_init()
|
||||
static void Init(); |
||||
|
||||
// To be callen in grpc_shutdown();
|
||||
static void Shutdown(); |
||||
|
||||
// globally registers a channelz Object. Returns its unique uuid
|
||||
template <typename Object> |
||||
static intptr_t Register(Object* object) { |
||||
return Default()->InternalRegister(object); |
||||
} |
||||
|
||||
// globally unregisters the object that is associated to uuid.
|
||||
static void Unregister(intptr_t uuid) { Default()->InternalUnregister(uuid); } |
||||
|
||||
// if object with uuid has previously been registered, returns the
|
||||
// Object associated with that uuid. Else returns nullptr.
|
||||
template <typename Object> |
||||
static Object* Get(intptr_t uuid) { |
||||
return Default()->InternalGet<Object>(uuid); |
||||
} |
||||
|
||||
private: |
||||
GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW |
||||
GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE |
||||
|
||||
ChannelzRegistry(); |
||||
~ChannelzRegistry(); |
||||
|
||||
// Returned the singleton instance of ChannelzRegistry;
|
||||
static ChannelzRegistry* Default(); |
||||
|
||||
// globally registers a channelz Object. Returns its unique uuid
|
||||
template <typename Object> |
||||
intptr_t InternalRegister(Object* object) { |
||||
intptr_t prior = gpr_atm_no_barrier_fetch_add(&uuid_, 1); |
||||
gpr_mu_lock(&mu_); |
||||
avl_ = grpc_avl_add(avl_, (void*)prior, object, nullptr); |
||||
gpr_mu_unlock(&mu_); |
||||
return prior; |
||||
} |
||||
|
||||
// globally unregisters the object that is associated to uuid.
|
||||
void InternalUnregister(intptr_t uuid); |
||||
|
||||
// if object with uuid has previously been registered, returns the
|
||||
// Object associated with that uuid. Else returns nullptr.
|
||||
template <typename Object> |
||||
Object* InternalGet(intptr_t uuid) { |
||||
gpr_mu_lock(&mu_); |
||||
Object* ret = |
||||
static_cast<Object*>(grpc_avl_get(avl_, (void*)uuid, nullptr)); |
||||
gpr_mu_unlock(&mu_); |
||||
return ret; |
||||
} |
||||
|
||||
// private members
|
||||
gpr_mu mu_; |
||||
grpc_avl avl_; |
||||
gpr_atm uuid_; |
||||
}; |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNELZ_REGISTRY_H */ |
@ -0,0 +1,120 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2017 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 <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include <gtest/gtest.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
#include "src/core/lib/channel/channel_trace.h" |
||||
#include "src/core/lib/channel/channelz_registry.h" |
||||
#include "src/core/lib/gpr/useful.h" |
||||
#include "src/core/lib/gprpp/memory.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
#include "src/core/lib/json/json.h" |
||||
|
||||
#include "test/core/util/test_config.h" |
||||
|
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
namespace grpc_core { |
||||
namespace testing { |
||||
|
||||
// Tests basic ChannelTrace functionality like construction, adding trace, and
|
||||
// lookups by uuid.
|
||||
TEST(ChannelzRegistryTest, UuidStartsAboveZeroTest) { |
||||
int object_to_register; |
||||
intptr_t uuid = ChannelzRegistry::Register(&object_to_register); |
||||
EXPECT_GT(uuid, 0) << "First uuid chose must be greater than zero. Zero if " |
||||
"reserved according to " |
||||
"https://github.com/grpc/proposal/blob/master/" |
||||
"A14-channelz.md"; |
||||
ChannelzRegistry::Unregister(uuid); |
||||
} |
||||
|
||||
TEST(ChannelzRegistryTest, UuidsAreIncreasing) { |
||||
int object_to_register; |
||||
std::vector<intptr_t> uuids; |
||||
for (int i = 0; i < 10; ++i) { |
||||
// reregister the same object. It's ok since we are just testing uuids
|
||||
uuids.push_back(ChannelzRegistry::Register(&object_to_register)); |
||||
} |
||||
for (size_t i = 1; i < uuids.size(); ++i) { |
||||
EXPECT_LT(uuids[i - 1], uuids[i]) << "Uuids must always be increasing"; |
||||
} |
||||
} |
||||
|
||||
TEST(ChannelzRegistryTest, RegisterGetTest) { |
||||
int object_to_register = 42; |
||||
intptr_t uuid = ChannelzRegistry::Register(&object_to_register); |
||||
int* retrieved = ChannelzRegistry::Get<int>(uuid); |
||||
EXPECT_EQ(&object_to_register, retrieved); |
||||
} |
||||
|
||||
TEST(ChannelzRegistryTest, MultipleTypeTest) { |
||||
int int_to_register = 42; |
||||
intptr_t int_uuid = ChannelzRegistry::Register(&int_to_register); |
||||
std::string str_to_register = "hello world"; |
||||
intptr_t str_uuid = ChannelzRegistry::Register(&str_to_register); |
||||
int* retrieved_int = ChannelzRegistry::Get<int>(int_uuid); |
||||
std::string* retrieved_str = ChannelzRegistry::Get<std::string>(str_uuid); |
||||
EXPECT_EQ(&int_to_register, retrieved_int); |
||||
EXPECT_EQ(&str_to_register, retrieved_str); |
||||
} |
||||
|
||||
namespace { |
||||
class Foo { |
||||
public: |
||||
int bar; |
||||
}; |
||||
} // namespace
|
||||
|
||||
TEST(ChannelzRegistryTest, CustomObjectTest) { |
||||
Foo* foo = New<Foo>(); |
||||
foo->bar = 1024; |
||||
intptr_t uuid = ChannelzRegistry::Register(foo); |
||||
Foo* retrieved = ChannelzRegistry::Get<Foo>(uuid); |
||||
EXPECT_EQ(foo, retrieved); |
||||
} |
||||
|
||||
TEST(ChannelzRegistryTest, NullIfNotPresentTest) { |
||||
int object_to_register = 42; |
||||
intptr_t uuid = ChannelzRegistry::Register(&object_to_register); |
||||
// try to pull out a uuid that does not exist.
|
||||
int* nonexistant = ChannelzRegistry::Get<int>(uuid + 1); |
||||
EXPECT_EQ(nonexistant, nullptr); |
||||
int* retrieved = ChannelzRegistry::Get<int>(uuid); |
||||
EXPECT_EQ(object_to_register, *retrieved); |
||||
EXPECT_EQ(&object_to_register, retrieved); |
||||
} |
||||
|
||||
} // namespace testing
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) { |
||||
grpc_test_init(argc, argv); |
||||
grpc_init(); |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
int ret = RUN_ALL_TESTS(); |
||||
grpc_shutdown(); |
||||
return ret; |
||||
} |
Loading…
Reference in new issue