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