diff options
author | ncteisen <ncteisen@gmail.com> | 2018-07-20 14:26:04 -0700 |
---|---|---|
committer | ncteisen <ncteisen@gmail.com> | 2018-07-20 14:26:04 -0700 |
commit | 8cb2d0c64afd9c766ea6b4c41f3125879091d08a (patch) | |
tree | 4b1124a4bdcb40612c78612e39f729610a02ee09 | |
parent | ca32a8a85286ae0c9c94c3eaeaee3100d0304f99 (diff) |
Restructure everything
-rw-r--r-- | src/core/ext/filters/client_channel/client_channel_channelz.cc | 79 | ||||
-rw-r--r-- | src/core/ext/filters/client_channel/client_channel_channelz.h | 37 | ||||
-rw-r--r-- | src/core/ext/filters/client_channel/subchannel.cc | 8 | ||||
-rw-r--r-- | src/core/lib/channel/channelz.cc | 89 | ||||
-rw-r--r-- | src/core/lib/channel/channelz.h | 122 | ||||
-rw-r--r-- | src/core/lib/channel/channelz_registry.cc | 51 | ||||
-rw-r--r-- | src/core/lib/channel/channelz_registry.h | 50 | ||||
-rw-r--r-- | test/core/channel/channelz_registry_test.cc | 30 | ||||
-rw-r--r-- | test/core/channel/channelz_test.cc | 42 |
9 files changed, 223 insertions, 285 deletions
diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 0688ee2abb..1d72b9c9d2 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -20,6 +20,7 @@ #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/client_channel_channelz.h" +#include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/connectivity_state.h" @@ -97,6 +98,38 @@ void ClientChannelNode::PopulateChildRefs(grpc_json* json) { } } +grpc_json* ClientChannelNode::RenderJson() { + // We need to track these three json objects to build our object + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + // create and fill the ref child + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "channelId", channel_uuid()); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + PopulateConnectivityState(json); + // populate the target. + GPR_ASSERT(target_view() != nullptr); + grpc_json_create_child(nullptr, json, "target", target_view(), + GRPC_JSON_STRING, false); + // as CallCountingAndTracingNode to populate trace and call count data. + PopulateTrace(json); + PopulateCallData(json); + PopulateChildRefs(json); + return top_level_json; +} + grpc_arg ClientChannelNode::CreateChannelArg() { return grpc_channel_arg_pointer_create( const_cast<char*>(GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC), @@ -111,20 +144,21 @@ RefCountedPtr<ChannelNode> ClientChannelNode::MakeClientChannelNode( channel, channel_tracer_max_nodes, is_top_level_channel); } -ClientChannelSubchannelNode::ClientChannelSubchannelNode( - size_t channel_tracer_max_nodes, grpc_subchannel* subchannel) - : SubchannelNode(channel_tracer_max_nodes), +SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, + size_t channel_tracer_max_nodes) + : CallCountingAndTracingNode(EntityType::kSubchannel, + channel_tracer_max_nodes), subchannel_(subchannel), target_(UniquePtr<char>( - gpr_strdup(grpc_subchannel_get_target(subchannel_)))) {} + gpr_strdup(grpc_subchannel_get_target(subchannel_)))) { + subchannel_uuid_ = ChannelzRegistry::Register(this); +} -void ClientChannelSubchannelNode::PopulateTarget(grpc_json* json) { - GPR_ASSERT(target_.get() != nullptr); - grpc_json_create_child(nullptr, json, "target", target_.get(), - GRPC_JSON_STRING, false); +SubchannelNode::~SubchannelNode() { + ChannelzRegistry::Unregister(subchannel_uuid_); } -void ClientChannelSubchannelNode::PopulateConnectivityState(grpc_json* json) { +void SubchannelNode::PopulateConnectivityState(grpc_json* json) { grpc_connectivity_state state; if (subchannel_ == nullptr) { state = GRPC_CHANNEL_SHUTDOWN; @@ -138,5 +172,32 @@ void ClientChannelSubchannelNode::PopulateConnectivityState(grpc_json* json) { false); } +grpc_json* SubchannelNode::RenderJson() { + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, + GRPC_JSON_OBJECT, false); + json = json_iterator; + json_iterator = nullptr; + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "subchannelId", subchannel_uuid_); + // reset json iterators to top level object + json = top_level_json; + json_iterator = nullptr; + // create and fill the data child. + grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, + GRPC_JSON_OBJECT, false); + json = data; + json_iterator = nullptr; + PopulateConnectivityState(json); + GPR_ASSERT(target_.get() != nullptr); + grpc_json_create_child(nullptr, json, "target", target_.get(), + GRPC_JSON_STRING, false); + PopulateTrace(json); + PopulateCallData(json); + return top_level_json; +} + } // namespace channelz } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index b1bd8db89e..73eea7cecf 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -45,12 +45,7 @@ class ClientChannelNode : public ChannelNode { grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); - // Override this functionality since client_channels have a notion of - // channel connectivity. - void PopulateConnectivityState(grpc_json* json) override; - - // Override this functionality since client_channels have subchannels - void PopulateChildRefs(grpc_json* json) override; + grpc_json* RenderJson() override; // Helper to create a channel arg to ensure this type of ChannelNode is // created. @@ -65,35 +60,35 @@ class ClientChannelNode : public ChannelNode { GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW grpc_channel_element* client_channel_; + + // helpers + void PopulateConnectivityState(grpc_json* json); + void PopulateChildRefs(grpc_json* json); }; -// Subtype of SubchannelNode that overrides and provides client_channel -// specific functionality like querying for connectivity_state and -// subchannel target. -class ClientChannelSubchannelNode : public SubchannelNode { +// Handles channelz bookkeeping for sockets +class SubchannelNode : public CallCountingAndTracingNode { public: - ClientChannelSubchannelNode(size_t channel_tracer_max_nodes, - grpc_subchannel* subchannel); - ~ClientChannelSubchannelNode() override {} - - // Override this functionality since subchannels have a notion of - // channel connectivity. - void PopulateConnectivityState(grpc_json* json) override; - - // Override this functionality since client_channels subchannels hold - // their own target. - void PopulateTarget(grpc_json* json) override; + SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes); + ~SubchannelNode() override; void MarkSubchannelDestroyed() { GPR_ASSERT(subchannel_ != nullptr); subchannel_ = nullptr; } + grpc_json* RenderJson() override; + + intptr_t subchannel_uuid() { return subchannel_uuid_; } + private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + intptr_t subchannel_uuid_; grpc_subchannel* subchannel_; UniquePtr<char> target_; + + void PopulateConnectivityState(grpc_json* json); }; } // namespace channelz diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 0c3313c5de..8dfbd33ffe 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -135,7 +135,7 @@ struct grpc_subchannel { /** our alarm */ grpc_timer alarm; - grpc_core::RefCountedPtr<grpc_core::channelz::ClientChannelSubchannelNode> + grpc_core::RefCountedPtr<grpc_core::channelz::SubchannelNode> channelz_subchannel; }; @@ -393,9 +393,9 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, size_t channel_tracer_max_nodes = (size_t)grpc_channel_arg_get_integer(arg, options); if (channelz_enabled) { - c->channelz_subchannel = grpc_core::MakeRefCounted< - grpc_core::channelz::ClientChannelSubchannelNode>( - channel_tracer_max_nodes, c); + c->channelz_subchannel = + grpc_core::MakeRefCounted<grpc_core::channelz::SubchannelNode>( + c, channel_tracer_max_nodes); c->channelz_subchannel->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel created")); diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 7fe086da3c..d7f2d6a9a2 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -41,21 +41,30 @@ namespace grpc_core { namespace channelz { -CallCountingBase::CallCountingBase(size_t channel_tracer_max_nodes) { +char* BaseNode::RenderJsonString() { + grpc_json* json = RenderJson(); + char* json_str = grpc_json_dump_to_string(json, 0); + grpc_json_destroy(json); + return json_str; +} + +CallCountingAndTracingNode::CallCountingAndTracingNode( + EntityType type, size_t channel_tracer_max_nodes) + : BaseNode(type) { trace_.Init(channel_tracer_max_nodes); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -CallCountingBase::~CallCountingBase() { trace_.Destroy(); } +CallCountingAndTracingNode::~CallCountingAndTracingNode() { trace_.Destroy(); } -void CallCountingBase::RecordCallStarted() { +void CallCountingAndTracingNode::RecordCallStarted() { gpr_atm_no_barrier_fetch_add(&calls_started_, (gpr_atm)1); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -void CallCountingBase::PopulateTrace(grpc_json* json) { +void CallCountingAndTracingNode::PopulateTrace(grpc_json* json) { // fill in the channel trace if applicable grpc_json* trace_json = trace_->RenderJson(); if (trace_json != nullptr) { @@ -66,7 +75,7 @@ void CallCountingBase::PopulateTrace(grpc_json* json) { } } -void CallCountingBase::PopulateCallData(grpc_json* json) { +void CallCountingAndTracingNode::PopulateCallData(grpc_json* json) { grpc_json* json_iterator = nullptr; if (calls_started_ != 0) { json_iterator = grpc_json_add_number_string_child( @@ -87,31 +96,18 @@ void CallCountingBase::PopulateCallData(grpc_json* json) { gpr_format_timespec(ts), GRPC_JSON_STRING, true); } -char* CallCountingBase::RenderJsonString() { - grpc_json* json = RenderJson(); - char* json_str = grpc_json_dump_to_string(json, 0); - grpc_json_destroy(json); - return json_str; -} - ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel) - : CallCountingBase(channel_tracer_max_nodes), + : CallCountingAndTracingNode(is_top_level_channel + ? EntityType::kTopLevelChannel + : EntityType::kInternalChannel, + channel_tracer_max_nodes), channel_(channel), - is_top_level_channel_(is_top_level_channel) { - target_ = UniquePtr<char>(grpc_channel_get_target(channel_)); - channel_uuid_ = ChannelzRegistry::RegisterChannelNode(this); + target_(UniquePtr<char>(grpc_channel_get_target(channel_))) { + channel_uuid_ = ChannelzRegistry::Register(this); } -ChannelNode::~ChannelNode() { - ChannelzRegistry::UnregisterChannelNode(channel_uuid_); -} - -void ChannelNode::PopulateTarget(grpc_json* json) { - GPR_ASSERT(target_.get() != nullptr); - grpc_json_create_child(nullptr, json, "target", target_.get(), - GRPC_JSON_STRING, false); -} +ChannelNode::~ChannelNode() { ChannelzRegistry::Unregister(channel_uuid_); } grpc_json* ChannelNode::RenderJson() { // We need to track these three json objects to build our object @@ -133,11 +129,13 @@ grpc_json* ChannelNode::RenderJson() { GRPC_JSON_OBJECT, false); json = data; json_iterator = nullptr; - PopulateConnectivityState(json); - PopulateTarget(json); + // populate the target. + GPR_ASSERT(target_.get() != nullptr); + grpc_json_create_child(nullptr, json, "target", target_.get(), + GRPC_JSON_STRING, false); + // as CallCountingAndTracingNode to populate trace and call count data. PopulateTrace(json); PopulateCallData(json); - PopulateChildRefs(json); return top_level_json; } @@ -148,40 +146,5 @@ RefCountedPtr<ChannelNode> ChannelNode::MakeChannelNode( channel, channel_tracer_max_nodes, is_top_level_channel); } -SubchannelNode::SubchannelNode(size_t channel_tracer_max_nodes) - : CallCountingBase(channel_tracer_max_nodes) { - subchannel_uuid_ = ChannelzRegistry::RegisterSubchannelNode(this); -} - -SubchannelNode::~SubchannelNode() { - ChannelzRegistry::UnregisterSubchannelNode(subchannel_uuid_); -} - -grpc_json* SubchannelNode::RenderJson() { - grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); - grpc_json* json = top_level_json; - grpc_json* json_iterator = nullptr; - json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr, - GRPC_JSON_OBJECT, false); - json = json_iterator; - json_iterator = nullptr; - json_iterator = grpc_json_add_number_string_child( - json, json_iterator, "subchannelId", subchannel_uuid_); - // reset json iterators to top level object - json = top_level_json; - json_iterator = nullptr; - // create and fill the data child. - grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr, - GRPC_JSON_OBJECT, false); - json = data; - json_iterator = nullptr; - PopulateConnectivityState(json); - PopulateTarget(json); - PopulateTrace(json); - PopulateCallData(json); - PopulateChildRefs(json); - return top_level_json; -} - } // namespace channelz } // namespace grpc_core diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 1cd55bab43..1273545663 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -43,30 +43,40 @@ namespace grpc_core { namespace channelz { namespace testing { -class ChannelNodePeer; +class CallCountingAndTracingNodePeer; } // base class for all channelz entities class BaseNode : public RefCounted<BaseNode> { public: - BaseNode() {} + // There are only four high level channelz entities. However, to support + // GetTopChannelsRequest, we split the Channel entity into two different + // types. All children of BaseNode must be one of these types. + enum class EntityType { + kTopLevelChannel, + kInternalChannel, + kSubchannel, + kServer, + kSocket, + }; + + // we track is_top_level_channel to support GetTopChannels + BaseNode(EntityType type) : type_(type) {} virtual ~BaseNode() {} - private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW -}; + // All children must implement this function. + virtual grpc_json* RenderJson() GRPC_ABSTRACT; -// Handles channelz bookkeeping for sockets -// TODO(ncteisen): implement in subsequent PR. -class SocketNode : public BaseNode { - public: - SocketNode() : BaseNode() {} - ~SocketNode() override {} + // Renders the json and returns allocated string that must be freed by the + // caller. + char* RenderJsonString(); + + EntityType type() const { return type_; } private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + EntityType type_; }; // This class is the parent for the channelz entities that deal with Channels @@ -76,16 +86,10 @@ class SocketNode : public BaseNode { // - track last_call_started_timestamp // - hold the channel trace. // - perform common rendering. -// -// This class also defines some fat interfaces so that its children can -// implement the functionality differently. For example, querying the -// connectivity state looks different for channels than for subchannels, and -// does not make sense for servers. So servers will not override, and channels -// and subchannels will override with their own way to query connectivity state. -class CallCountingBase : public BaseNode { +class CallCountingAndTracingNode : public BaseNode { public: - CallCountingBase(size_t channel_tracer_max_nodes); - ~CallCountingBase() override; + CallCountingAndTracingNode(EntityType type, size_t channel_tracer_max_nodes); + ~CallCountingAndTracingNode() override; void RecordCallStarted(); void RecordCallFailed() { @@ -96,34 +100,19 @@ class CallCountingBase : public BaseNode { } ChannelTrace* trace() { return trace_.get(); } - // Fat interface for ConnectivityState. Default is to leave it out, however, - // things like Channel and Subchannel will override with their mechanism - // for querying connectivity state. - virtual void PopulateConnectivityState(grpc_json* json) {} - - // Fat interface for Targets. - virtual void PopulateTarget(grpc_json* json) {} - - // Fat interface for ChildRefs. Allows children to populate with whatever - // combination of child_refs, subchannel_refs, and socket_refs is correct. - virtual void PopulateChildRefs(grpc_json* json) {} - - // All children must implement their custom JSON rendering. - virtual grpc_json* RenderJson() GRPC_ABSTRACT; - // Common rendering of the channel trace. void PopulateTrace(grpc_json* json); // Common rendering of the call count data and last_call_started_timestamp. void PopulateCallData(grpc_json* json); - // Common rendering of grpc_json from RenderJson() to allocated string. - char* RenderJsonString(); - private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + // testing peer friend. + friend class testing::CallCountingAndTracingNodePeer; + gpr_atm calls_started_ = 0; gpr_atm calls_succeeded_ = 0; gpr_atm calls_failed_ = 0; @@ -131,71 +120,64 @@ class CallCountingBase : public BaseNode { ManualConstructor<ChannelTrace> trace_; }; -// Handles channelz bookkeeping for servers -// TODO(ncteisen): implement in subsequent PR. -class ServerNode : public CallCountingBase { - public: - ServerNode(size_t channel_tracer_max_nodes) - : CallCountingBase(channel_tracer_max_nodes) {} - ~ServerNode() override {} - - private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW -}; - -// Overrides Channel specific functionality. -class ChannelNode : public CallCountingBase { +// Handles channelz bookkeeping for channels +class ChannelNode : public CallCountingAndTracingNode { public: static RefCountedPtr<ChannelNode> MakeChannelNode( grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); + grpc_json* RenderJson() override; + void MarkChannelDestroyed() { GPR_ASSERT(channel_ != nullptr); channel_ = nullptr; } - grpc_json* RenderJson() override; - - void PopulateTarget(grpc_json* json) override; - bool ChannelIsDestroyed() { return channel_ == nullptr; } intptr_t channel_uuid() { return channel_uuid_; } - bool is_top_level_channel() { return is_top_level_channel_; } protected: ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); ~ChannelNode() override; + // provides view of target for child. + char* target_view() { return target_.get(); } private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - // testing peer friend. - friend class testing::ChannelNodePeer; - grpc_channel* channel_ = nullptr; UniquePtr<char> target_; intptr_t channel_uuid_; - bool is_top_level_channel_ = true; }; -// Overrides Subchannel specific functionality. -class SubchannelNode : public CallCountingBase { +// Handles channelz bookkeeping for servers +// TODO(ncteisen): implement in subsequent PR. +class ServerNode : public CallCountingAndTracingNode { public: - SubchannelNode(size_t channel_tracer_max_nodes); - ~SubchannelNode() override; - grpc_json* RenderJson() override; - intptr_t subchannel_uuid() { return subchannel_uuid_; } + ServerNode(size_t channel_tracer_max_nodes) + : CallCountingAndTracingNode(EntityType::kServer, + channel_tracer_max_nodes) {} + ~ServerNode() override {} private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW +}; - intptr_t subchannel_uuid_; +// Handles channelz bookkeeping for sockets +// TODO(ncteisen): implement in subsequent PR. +class SocketNode : public BaseNode { + public: + SocketNode() : BaseNode(EntityType::kSocket) {} + ~SocketNode() override {} + + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW }; // Creation functions diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index aeeb6958e4..7f70908989 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -52,54 +52,46 @@ ChannelzRegistry::ChannelzRegistry() { gpr_mu_init(&mu_); } ChannelzRegistry::~ChannelzRegistry() { gpr_mu_destroy(&mu_); } -intptr_t ChannelzRegistry::InternalRegisterEntry(const RegistryEntry& entry) { +intptr_t ChannelzRegistry::InternalRegister(BaseNode* node) { mu_guard guard(&mu_); - entities_.push_back(entry); + entities_.push_back(node); intptr_t uuid = entities_.size(); return uuid; } -void ChannelzRegistry::InternalUnregisterEntry(intptr_t uuid, EntityType type) { +void ChannelzRegistry::InternalUnregister(intptr_t uuid) { GPR_ASSERT(uuid >= 1); mu_guard guard(&mu_); GPR_ASSERT(static_cast<size_t>(uuid) <= entities_.size()); - GPR_ASSERT(entities_[uuid - 1].type == type); - entities_[uuid - 1].object = nullptr; - entities_[uuid - 1].type = EntityType::kUnset; + entities_[uuid - 1] = nullptr; } -void* ChannelzRegistry::InternalGetEntry(intptr_t uuid, EntityType type) { +BaseNode* ChannelzRegistry::InternalGet(intptr_t uuid) { mu_guard guard(&mu_); if (uuid < 1 || uuid > static_cast<intptr_t>(entities_.size())) { return nullptr; } - if (entities_[uuid - 1].type == type) { - return entities_[uuid - 1].object; - } else { - return nullptr; - } + return entities_[uuid - 1]; } char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) { grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; grpc_json* json_iterator = nullptr; - InlinedVector<ChannelNode*, 10> top_level_channels; + InlinedVector<BaseNode*, 10> top_level_channels; // uuids index into entities one-off (idx 0 is really uuid 1, since 0 is // reserved). However, we want to support requests coming in with // start_channel_id=0, which signifies "give me everything." Hence this // funky looking line below. size_t start_idx = start_channel_id == 0 ? 0 : start_channel_id - 1; for (size_t i = start_idx; i < entities_.size(); ++i) { - if (entities_[i].type == EntityType::kChannelNode) { - ChannelNode* channel_node = - static_cast<ChannelNode*>(entities_[i].object); - if (channel_node->is_top_level_channel()) { - top_level_channels.push_back(channel_node); - } + if (entities_[i] != nullptr && + entities_[i]->type() == + grpc_core::channelz::BaseNode::EntityType::kTopLevelChannel) { + top_level_channels.push_back(entities_[i]); } } - if (top_level_channels.size() > 0) { + if (!top_level_channels.empty()) { // create list of channels grpc_json* array_parent = grpc_json_create_child( nullptr, json, "channel", nullptr, GRPC_JSON_ARRAY, false); @@ -128,9 +120,14 @@ char* grpc_channelz_get_top_channels(intptr_t start_channel_id) { } char* grpc_channelz_get_channel(intptr_t channel_id) { - grpc_core::channelz::ChannelNode* channel_node = - grpc_core::channelz::ChannelzRegistry::GetChannelNode(channel_id); - if (channel_node == nullptr) { + grpc_core::channelz::BaseNode* channel_node = + grpc_core::channelz::ChannelzRegistry::Get(channel_id); + if (channel_node == nullptr || + + (channel_node->type() != + grpc_core::channelz::BaseNode::EntityType::kTopLevelChannel && + channel_node->type() != + grpc_core::channelz::BaseNode::EntityType::kInternalChannel)) { return nullptr; } grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); @@ -144,9 +141,11 @@ char* grpc_channelz_get_channel(intptr_t channel_id) { } char* grpc_channelz_get_subchannel(intptr_t subchannel_id) { - grpc_core::channelz::SubchannelNode* subchannel_node = - grpc_core::channelz::ChannelzRegistry::GetSubchannelNode(subchannel_id); - if (subchannel_node == nullptr) { + grpc_core::channelz::BaseNode* subchannel_node = + grpc_core::channelz::ChannelzRegistry::Get(subchannel_id); + if (subchannel_node == nullptr || + subchannel_node->type() != + grpc_core::channelz::BaseNode::EntityType::kSubchannel) { return nullptr; } grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); diff --git a/src/core/lib/channel/channelz_registry.h b/src/core/lib/channel/channelz_registry.h index 5d7c936726..142c039220 100644 --- a/src/core/lib/channel/channelz_registry.h +++ b/src/core/lib/channel/channelz_registry.h @@ -40,32 +40,11 @@ class ChannelzRegistry { // To be called in grpc_shutdown(); static void Shutdown(); - // Register/Unregister/Get for ChannelNode - static intptr_t RegisterChannelNode(ChannelNode* channel_node) { - RegistryEntry entry(channel_node, EntityType::kChannelNode); - return Default()->InternalRegisterEntry(entry); - } - static void UnregisterChannelNode(intptr_t uuid) { - Default()->InternalUnregisterEntry(uuid, EntityType::kChannelNode); - } - static ChannelNode* GetChannelNode(intptr_t uuid) { - void* gotten = Default()->InternalGetEntry(uuid, EntityType::kChannelNode); - return gotten == nullptr ? nullptr : static_cast<ChannelNode*>(gotten); - } - - // Register/Unregister/Get for SubchannelNode - static intptr_t RegisterSubchannelNode(SubchannelNode* channel_node) { - RegistryEntry entry(channel_node, EntityType::kSubchannelNode); - return Default()->InternalRegisterEntry(entry); - } - static void UnregisterSubchannelNode(intptr_t uuid) { - Default()->InternalUnregisterEntry(uuid, EntityType::kSubchannelNode); - } - static SubchannelNode* GetSubchannelNode(intptr_t uuid) { - void* gotten = - Default()->InternalGetEntry(uuid, EntityType::kSubchannelNode); - return gotten == nullptr ? nullptr : static_cast<SubchannelNode*>(gotten); + static intptr_t Register(BaseNode* node) { + return Default()->InternalRegister(node); } + static void Unregister(intptr_t uuid) { Default()->InternalUnregister(uuid); } + static BaseNode* Get(intptr_t uuid) { return Default()->InternalGet(uuid); } // Returns the allocated JSON string that represents the proto // GetTopChannelsResponse as per channelz.proto. @@ -74,19 +53,6 @@ class ChannelzRegistry { } private: - enum class EntityType { - kChannelNode, - kSubchannelNode, - kUnset, - }; - - struct RegistryEntry { - RegistryEntry(void* object_in, EntityType type_in) - : object(object_in), type(type_in) {} - void* object; - EntityType type; - }; - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE @@ -97,21 +63,21 @@ class ChannelzRegistry { static ChannelzRegistry* Default(); // globally registers an Entry. Returns its unique uuid - intptr_t InternalRegisterEntry(const RegistryEntry& entry); + intptr_t InternalRegister(BaseNode* node); // globally unregisters the object that is associated to uuid. Also does // sanity check that an object doesn't try to unregister the wrong type. - void InternalUnregisterEntry(intptr_t uuid, EntityType type); + void InternalUnregister(intptr_t uuid); // if object with uuid has previously been registered as the correct type, // returns the void* associated with that uuid. Else returns nullptr. - void* InternalGetEntry(intptr_t uuid, EntityType type); + BaseNode* InternalGet(intptr_t uuid); char* InternalGetTopChannels(intptr_t start_channel_id); // protects entities_ and uuid_ gpr_mu mu_; - InlinedVector<RegistryEntry, 20> entities_; + InlinedVector<BaseNode*, 20> entities_; }; } // namespace channelz diff --git a/test/core/channel/channelz_registry_test.cc b/test/core/channel/channelz_registry_test.cc index 581e867584..c02d525c81 100644 --- a/test/core/channel/channelz_registry_test.cc +++ b/test/core/channel/channelz_registry_test.cc @@ -44,22 +44,22 @@ namespace channelz { namespace testing { TEST(ChannelzRegistryTest, UuidStartsAboveZeroTest) { - ChannelNode* channelz_channel = nullptr; - intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); + BaseNode* channelz_channel = nullptr; + intptr_t uuid = ChannelzRegistry::Register(channelz_channel); 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::UnregisterChannelNode(uuid); + ChannelzRegistry::Unregister(uuid); } TEST(ChannelzRegistryTest, UuidsAreIncreasing) { - ChannelNode* channelz_channel = nullptr; + BaseNode* channelz_channel = nullptr; std::vector<intptr_t> uuids; uuids.reserve(10); for (int i = 0; i < 10; ++i) { // reregister the same object. It's ok since we are just testing uuids - uuids.push_back(ChannelzRegistry::RegisterChannelNode(channelz_channel)); + uuids.push_back(ChannelzRegistry::Register(channelz_channel)); } for (size_t i = 1; i < uuids.size(); ++i) { EXPECT_LT(uuids[i - 1], uuids[i]) << "Uuids must always be increasing"; @@ -68,30 +68,30 @@ TEST(ChannelzRegistryTest, UuidsAreIncreasing) { TEST(ChannelzRegistryTest, RegisterGetTest) { // we hackily jam an intptr_t into this pointer to check for equality later - ChannelNode* channelz_channel = (ChannelNode*)42; - intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); - ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); + BaseNode* channelz_channel = (BaseNode*)42; + intptr_t uuid = ChannelzRegistry::Register(channelz_channel); + BaseNode* retrieved = ChannelzRegistry::Get(uuid); EXPECT_EQ(channelz_channel, retrieved); } TEST(ChannelzRegistryTest, RegisterManyItems) { // we hackily jam an intptr_t into this pointer to check for equality later - ChannelNode* channelz_channel = (ChannelNode*)42; + BaseNode* channelz_channel = (BaseNode*)42; for (int i = 0; i < 100; i++) { - intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); - ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); + intptr_t uuid = ChannelzRegistry::Register(channelz_channel); + BaseNode* retrieved = ChannelzRegistry::Get(uuid); EXPECT_EQ(channelz_channel, retrieved); } } TEST(ChannelzRegistryTest, NullIfNotPresentTest) { // we hackily jam an intptr_t into this pointer to check for equality later - ChannelNode* channelz_channel = (ChannelNode*)42; - intptr_t uuid = ChannelzRegistry::RegisterChannelNode(channelz_channel); + BaseNode* channelz_channel = (BaseNode*)42; + intptr_t uuid = ChannelzRegistry::Register(channelz_channel); // try to pull out a uuid that does not exist. - ChannelNode* nonexistant = ChannelzRegistry::GetChannelNode(uuid + 1); + BaseNode* nonexistant = ChannelzRegistry::Get(uuid + 1); EXPECT_EQ(nonexistant, nullptr); - ChannelNode* retrieved = ChannelzRegistry::GetChannelNode(uuid); + BaseNode* retrieved = ChannelzRegistry::Get(uuid); EXPECT_EQ(channelz_channel, retrieved); } diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index b8e65ebfb3..ec1c9f6faf 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -44,16 +44,17 @@ namespace channelz { namespace testing { // testing peer to access channel internals -class ChannelNodePeer { +class CallCountingAndTracingNodePeer { public: - ChannelNodePeer(ChannelNode* channel) : channel_(channel) {} + CallCountingAndTracingNodePeer(CallCountingAndTracingNode* node) + : node_(node) {} grpc_millis last_call_started_millis() { return (grpc_millis)gpr_atm_no_barrier_load( - &channel_->last_call_started_millis_); + &node_->last_call_started_millis_); } private: - ChannelNode* channel_; + CallCountingAndTracingNode* node_; }; namespace { @@ -163,16 +164,8 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) { gpr_free(core_api_json_str); } -void ValidateSubchannel(SubchannelNode* subchannel, - validate_channel_data_args args) { - char* json_str = subchannel->RenderJsonString(); - grpc::testing::ValidateSubchannelProtoJsonTranslation(json_str); - ValidateCounters(json_str, args); - gpr_free(json_str); -} - -grpc_millis GetLastCallStartedMillis(ChannelNode* channel) { - ChannelNodePeer peer(channel); +grpc_millis GetLastCallStartedMillis(CallCountingAndTracingNode* channel) { + CallCountingAndTracingNodePeer peer(channel); return peer.last_call_started_millis(); } @@ -283,29 +276,8 @@ TEST(ChannelzGetTopChannelsTest, InternalChannelTest) { grpc_channel_destroy(internal_channel); } -class ChannelzSubchannelTest : public ::testing::TestWithParam<size_t> {}; - -TEST_P(ChannelzSubchannelTest, BasicTest) { - grpc_core::ExecCtx exec_ctx; - RefCountedPtr<SubchannelNode> channelz_subchannel = - MakeRefCounted<SubchannelNode>(GetParam()); - channelz_subchannel->RecordCallStarted(); - channelz_subchannel->RecordCallFailed(); - channelz_subchannel->RecordCallSucceeded(); - ValidateSubchannel(channelz_subchannel.get(), {1, 1, 1}); - channelz_subchannel->RecordCallStarted(); - channelz_subchannel->RecordCallFailed(); - channelz_subchannel->RecordCallSucceeded(); - channelz_subchannel->RecordCallStarted(); - channelz_subchannel->RecordCallFailed(); - channelz_subchannel->RecordCallSucceeded(); - ValidateSubchannel(channelz_subchannel.get(), {3, 3, 3}); -} - INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest, ::testing::Values(0, 1, 2, 6, 10, 15)); -INSTANTIATE_TEST_CASE_P(ChannelzSubchannelTestSweep, ChannelzSubchannelTest, - ::testing::Values(0, 1, 10, 15)); } // namespace testing } // namespace channelz |