From bbee13661c82c13e2f1b728c94f9535112f54d92 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 18 Jul 2018 18:31:09 -0700 Subject: Add channelz subchannel support --- .../client_channel/client_channel_channelz.cc | 29 +++++ .../client_channel/client_channel_channelz.h | 35 ++++- src/core/ext/filters/client_channel/subchannel.cc | 31 ++++- src/core/ext/filters/client_channel/subchannel.h | 2 + src/core/lib/channel/channel_trace.cc | 30 +++-- src/core/lib/channel/channelz.cc | 142 +++++++++++++-------- src/core/lib/channel/channelz.h | 131 ++++++++++++++----- src/core/lib/channel/channelz_registry.cc | 16 +++ src/core/lib/surface/channel.cc | 3 + 9 files changed, 316 insertions(+), 103 deletions(-) (limited to 'src/core') 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 d43e9ea67a..5a0eec5d15 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -24,6 +24,8 @@ #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/connectivity_state.h" +#include + namespace grpc_core { namespace channelz { namespace { @@ -109,5 +111,32 @@ RefCountedPtr 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), subchannel_(subchannel) { + target_ = + UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_))); +} + +void ClientChannelSubchannelNode::PopulateTarget(grpc_json* json) { + GPR_ASSERT(target_.get() != nullptr); + grpc_json_create_child(nullptr, json, "target", target_.get(), + GRPC_JSON_STRING, false); +} + +void ClientChannelSubchannelNode::PopulateConnectivityState(grpc_json* json) { + grpc_connectivity_state state; + if (subchannel_ == nullptr) { + state = GRPC_CHANNEL_SHUTDOWN; + } else { + state = grpc_subchannel_check_connectivity(subchannel_, nullptr); + } + json = grpc_json_create_child(nullptr, json, "state", nullptr, + GRPC_JSON_OBJECT, false); + grpc_json_create_child(nullptr, json, "state", + grpc_connectivity_state_name(state), GRPC_JSON_STRING, + false); +} + } // 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 6f27b5c8b7..b1bd8db89e 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -26,6 +26,8 @@ #include "src/core/lib/channel/channelz.h" #include "src/core/lib/gprpp/inlined_vector.h" +typedef struct grpc_subchannel grpc_subchannel; + namespace grpc_core { // TODO(ncteisen), this only contains the uuids of the children for now, @@ -55,16 +57,45 @@ class ClientChannelNode : public ChannelNode { static grpc_arg CreateChannelArg(); protected: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW ClientChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); virtual ~ClientChannelNode() {} private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW grpc_channel_element* client_channel_; }; +// Subtype of SubchannelNode that overrides and provides client_channel +// specific functionality like querying for connectivity_state and +// subchannel target. +class ClientChannelSubchannelNode : public SubchannelNode { + 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; + + void MarkSubchannelDestroyed() { + GPR_ASSERT(subchannel_ != nullptr); + subchannel_ = nullptr; + } + + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + grpc_subchannel* subchannel_; + UniquePtr target_; +}; + } // namespace channelz } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 93df2aff70..0c3313c5de 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::RefCountedPtr channelz_subchannel; }; @@ -181,7 +181,13 @@ static void connection_destroy(void* arg, grpc_error* error) { static void subchannel_destroy(void* arg, grpc_error* error) { grpc_subchannel* c = static_cast(arg); - c->channelz_subchannel.reset(); + if (c->channelz_subchannel != nullptr) { + c->channelz_subchannel->trace()->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Subchannel destroyed")); + c->channelz_subchannel->MarkSubchannelDestroyed(); + c->channelz_subchannel.reset(); + } gpr_free((void*)c->filters); grpc_channel_args_destroy(c->args); grpc_connectivity_state_destroy(&c->state_tracker); @@ -381,9 +387,18 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, const grpc_arg* arg = grpc_channel_args_find(c->args, GRPC_ARG_ENABLE_CHANNELZ); bool channelz_enabled = grpc_channel_arg_get_bool(arg, false); + arg = grpc_channel_args_find(c->args, + GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE); + const grpc_integer_options options = {0, 0, INT_MAX}; + size_t channel_tracer_max_nodes = + (size_t)grpc_channel_arg_get_integer(arg, options); if (channelz_enabled) { - c->channelz_subchannel = - grpc_core::MakeRefCounted(); + c->channelz_subchannel = grpc_core::MakeRefCounted< + grpc_core::channelz::ClientChannelSubchannelNode>( + channel_tracer_max_nodes, c); + c->channelz_subchannel->trace()->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Subchannel created")); } return grpc_subchannel_index_register(key, c); @@ -757,6 +772,14 @@ void grpc_get_subchannel_address_arg(const grpc_channel_args* args, } } +const char* grpc_subchannel_get_target(grpc_subchannel* subchannel) { + const grpc_arg* addr_arg = + grpc_channel_args_find(subchannel->args, GRPC_ARG_SUBCHANNEL_ADDRESS); + const char* addr_str = grpc_channel_arg_get_string(addr_arg); + GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. + return addr_str; +} + const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args) { const grpc_arg* addr_arg = grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 9e53f7d542..dd3a2d9621 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -177,6 +177,8 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, void grpc_get_subchannel_address_arg(const grpc_channel_args* args, grpc_resolved_address* addr); +const char* grpc_subchannel_get_target(grpc_subchannel* subchannel); + /// Returns the URI string for the address to connect to. const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args); diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc index b3443310ac..dd6fdeed54 100644 --- a/src/core/lib/channel/channel_trace.cc +++ b/src/core/lib/channel/channel_trace.cc @@ -178,24 +178,26 @@ grpc_json* ChannelTrace::RenderJson() const { if (!max_list_size_) return nullptr; // tracing is disabled if max_events == 0 grpc_json* json = grpc_json_create(GRPC_JSON_OBJECT); - char* num_events_logged_str; - gpr_asprintf(&num_events_logged_str, "%" PRId64, num_events_logged_); grpc_json* json_iterator = nullptr; - json_iterator = - grpc_json_create_child(json_iterator, json, "numEventsLogged", - num_events_logged_str, GRPC_JSON_STRING, true); + if (num_events_logged_ > 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "numEventsLogged", num_events_logged_); + } json_iterator = grpc_json_create_child( json_iterator, json, "creationTimestamp", gpr_format_timespec(time_created_), GRPC_JSON_STRING, true); - grpc_json* events = grpc_json_create_child(json_iterator, json, "events", - nullptr, GRPC_JSON_ARRAY, false); - json_iterator = nullptr; - TraceEvent* it = head_trace_; - while (it != nullptr) { - json_iterator = grpc_json_create_child(json_iterator, events, nullptr, - nullptr, GRPC_JSON_OBJECT, false); - it->RenderTraceEvent(json_iterator); - it = it->next(); + // only add in the event list if it is non-empty. + if (num_events_logged_ > 0) { + grpc_json* events = grpc_json_create_child(json_iterator, json, "events", + nullptr, GRPC_JSON_ARRAY, false); + json_iterator = nullptr; + TraceEvent* it = head_trace_; + while (it != nullptr) { + json_iterator = grpc_json_create_child(json_iterator, events, nullptr, + nullptr, GRPC_JSON_OBJECT, false); + it->RenderTraceEvent(json_iterator); + it = it->next(); + } } return json; } diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 9d6002ed8a..7fe086da3c 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -41,69 +41,33 @@ namespace grpc_core { namespace channelz { -ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, - bool is_top_level_channel) - : channel_(channel), - target_(nullptr), - channel_uuid_(-1), - is_top_level_channel_(is_top_level_channel) { +CallCountingBase::CallCountingBase(size_t channel_tracer_max_nodes) { trace_.Init(channel_tracer_max_nodes); - target_ = UniquePtr(grpc_channel_get_target(channel_)); - channel_uuid_ = ChannelzRegistry::RegisterChannelNode(this); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -ChannelNode::~ChannelNode() { - trace_.Destroy(); - ChannelzRegistry::UnregisterChannelNode(channel_uuid_); -} +CallCountingBase::~CallCountingBase() { trace_.Destroy(); } -void ChannelNode::RecordCallStarted() { +void CallCountingBase::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 ChannelNode::PopulateConnectivityState(grpc_json* json) {} - -void ChannelNode::PopulateChildRefs(grpc_json* json) {} - -grpc_json* ChannelNode::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); - GPR_ASSERT(target_.get() != nullptr); - json_iterator = grpc_json_create_child( - json_iterator, json, "target", target_.get(), GRPC_JSON_STRING, false); +void CallCountingBase::PopulateTrace(grpc_json* json) { // fill in the channel trace if applicable - grpc_json* trace = trace_->RenderJson(); - if (trace != nullptr) { + grpc_json* trace_json = trace_->RenderJson(); + if (trace_json != nullptr) { // we manually link up and fill the child since it was created for us in // ChannelTrace::RenderJson - trace->key = "trace"; // this object is named trace in channelz.proto - json_iterator = grpc_json_link_child(json, trace, json_iterator); + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); } - // reset the parent to be the data object. - json = data; - json_iterator = nullptr; +} + +void CallCountingBase::PopulateCallData(grpc_json* json) { + grpc_json* json_iterator = nullptr; if (calls_started_ != 0) { json_iterator = grpc_json_add_number_string_child( json, json_iterator, "callsStarted", calls_started_); @@ -121,19 +85,62 @@ grpc_json* ChannelNode::RenderJson() { json_iterator = grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp", gpr_format_timespec(ts), GRPC_JSON_STRING, true); - json = top_level_json; - json_iterator = nullptr; - PopulateChildRefs(json); - return top_level_json; } -char* ChannelNode::RenderJsonString() { +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), + channel_(channel), + is_top_level_channel_(is_top_level_channel) { + target_ = UniquePtr(grpc_channel_get_target(channel_)); + channel_uuid_ = ChannelzRegistry::RegisterChannelNode(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); +} + +grpc_json* ChannelNode::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); + PopulateTarget(json); + PopulateTrace(json); + PopulateCallData(json); + PopulateChildRefs(json); + return top_level_json; +} + RefCountedPtr ChannelNode::MakeChannelNode( grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel) { @@ -141,7 +148,8 @@ RefCountedPtr ChannelNode::MakeChannelNode( channel, channel_tracer_max_nodes, is_top_level_channel); } -SubchannelNode::SubchannelNode() { +SubchannelNode::SubchannelNode(size_t channel_tracer_max_nodes) + : CallCountingBase(channel_tracer_max_nodes) { subchannel_uuid_ = ChannelzRegistry::RegisterSubchannelNode(this); } @@ -149,5 +157,31 @@ 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 07eb73d626..97e27c69fc 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -46,11 +46,44 @@ namespace testing { class ChannelNodePeer; } -class ChannelNode : public RefCounted { +// base class for all channelz entities +class ChannelzBaseNode : public RefCounted { public: - static RefCountedPtr MakeChannelNode( - grpc_channel* channel, size_t channel_tracer_max_nodes, - bool is_top_level_channel); + ChannelzBaseNode() {} + virtual ~ChannelzBaseNode() {} + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW +}; + +// Handles channelz bookkeeping for sockets +// TODO(ncteisen): implement in subsequent PR. +class SocketNode : public ChannelzBaseNode { + public: + SocketNode() : ChannelzBaseNode() {} + ~SocketNode() override {} + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW +}; + +// This class is the parent for the channelz entities that deal with Channels +// Subchannels, and Servers, since those have similar proto definitions. +// This class has the ability to: +// - track calls_{started,succeeded,failed} +// - 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 different. For example, querying the +// connectivity state looks different for channels and 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 ChannelzBaseNode { + public: + CallCountingBase(size_t channel_tracer_max_nodes); + ~CallCountingBase() override; void RecordCallStarted(); void RecordCallFailed() { @@ -59,66 +92,106 @@ class ChannelNode : public RefCounted { void RecordCallSucceeded() { gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1))); } + 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) {} - grpc_json* RenderJson(); + // 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(); - // helper for getting and populating connectivity state. It is virtual - // because it allows the client_channel specific code to live in ext/ - // instead of lib/ - virtual void PopulateConnectivityState(grpc_json* json); + private: + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE + GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - virtual void PopulateChildRefs(grpc_json* json); + gpr_atm calls_started_ = 0; + gpr_atm calls_succeeded_ = 0; + gpr_atm calls_failed_ = 0; + gpr_atm last_call_started_millis_ = 0; + ManualConstructor trace_; +}; - ChannelTrace* trace() { return trace_.get(); } +// 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 { + public: + static RefCountedPtr MakeChannelNode( + grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); 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: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); - virtual ~ChannelNode(); + ~ChannelNode() override; 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 target_; - gpr_atm calls_started_ = 0; - gpr_atm calls_succeeded_ = 0; - gpr_atm calls_failed_ = 0; - gpr_atm last_call_started_millis_ = 0; intptr_t channel_uuid_; bool is_top_level_channel_ = true; - ManualConstructor trace_; }; -// Placeholds channelz class for subchannels. All this can do now is track its -// uuid (this information is needed by the parent channelz class). -// TODO(ncteisen): build this out to support the GetSubchannel channelz request. -class SubchannelNode : public RefCounted { +// Overrides Subchannel specific functionality. +class SubchannelNode : public CallCountingBase { public: - SubchannelNode(); - virtual ~SubchannelNode(); - + SubchannelNode(size_t channel_tracer_max_nodes); + ~SubchannelNode() override; + grpc_json* RenderJson() override; intptr_t subchannel_uuid() { return subchannel_uuid_; } - protected: + private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - - private: + intptr_t subchannel_uuid_; }; diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index 38496b3d78..aeeb6958e4 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -142,3 +142,19 @@ char* grpc_channelz_get_channel(intptr_t channel_id) { grpc_json_destroy(top_level_json); return json_str; } + +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) { + return nullptr; + } + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* subchannel_json = subchannel_node->RenderJson(); + subchannel_json->key = "subchannel"; + grpc_json_link_child(json, subchannel_json, nullptr); + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 7cbd61adef..01caadaaba 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -417,6 +417,9 @@ void grpc_channel_internal_unref(grpc_channel* c REF_ARG) { static void destroy_channel(void* arg, grpc_error* error) { grpc_channel* channel = static_cast(arg); if (channel->channelz_channel != nullptr) { + channel->channelz_channel->trace()->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Channel destroyed")); channel->channelz_channel->MarkChannelDestroyed(); channel->channelz_channel.reset(); } -- cgit v1.2.3 From ca32a8a85286ae0c9c94c3eaeaee3100d0304f99 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Thu, 19 Jul 2018 16:59:50 -0700 Subject: reviewer feedback --- .../client_channel/client_channel_channelz.cc | 8 +++---- src/core/lib/channel/channelz.h | 25 ++++++++++++---------- 2 files changed, 18 insertions(+), 15 deletions(-) (limited to 'src/core') 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 5a0eec5d15..0688ee2abb 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -113,10 +113,10 @@ RefCountedPtr ClientChannelNode::MakeClientChannelNode( ClientChannelSubchannelNode::ClientChannelSubchannelNode( size_t channel_tracer_max_nodes, grpc_subchannel* subchannel) - : SubchannelNode(channel_tracer_max_nodes), subchannel_(subchannel) { - target_ = - UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_))); -} + : SubchannelNode(channel_tracer_max_nodes), + subchannel_(subchannel), + target_(UniquePtr( + gpr_strdup(grpc_subchannel_get_target(subchannel_)))) {} void ClientChannelSubchannelNode::PopulateTarget(grpc_json* json) { GPR_ASSERT(target_.get() != nullptr); diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 97e27c69fc..1cd55bab43 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -47,10 +47,11 @@ class ChannelNodePeer; } // base class for all channelz entities -class ChannelzBaseNode : public RefCounted { +class BaseNode : public RefCounted { public: - ChannelzBaseNode() {} - virtual ~ChannelzBaseNode() {} + BaseNode() {} + virtual ~BaseNode() {} + private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW @@ -58,10 +59,11 @@ class ChannelzBaseNode : public RefCounted { // Handles channelz bookkeeping for sockets // TODO(ncteisen): implement in subsequent PR. -class SocketNode : public ChannelzBaseNode { +class SocketNode : public BaseNode { public: - SocketNode() : ChannelzBaseNode() {} + SocketNode() : BaseNode() {} ~SocketNode() override {} + private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW @@ -76,11 +78,11 @@ class SocketNode : public ChannelzBaseNode { // - perform common rendering. // // This class also defines some fat interfaces so that its children can -// implement the functionality different. For example, querying the -// connectivity state looks different for channels and 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 ChannelzBaseNode { +// 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 { public: CallCountingBase(size_t channel_tracer_max_nodes); ~CallCountingBase() override; @@ -136,6 +138,7 @@ class ServerNode : public CallCountingBase { 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 @@ -191,7 +194,7 @@ class SubchannelNode : public CallCountingBase { private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - + intptr_t subchannel_uuid_; }; -- cgit v1.2.3 From 8cb2d0c64afd9c766ea6b4c41f3125879091d08a Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 20 Jul 2018 14:26:04 -0700 Subject: Restructure everything --- .../client_channel/client_channel_channelz.cc | 79 +++++++++++-- .../client_channel/client_channel_channelz.h | 37 +++---- src/core/ext/filters/client_channel/subchannel.cc | 8 +- src/core/lib/channel/channelz.cc | 89 +++++---------- src/core/lib/channel/channelz.h | 122 +++++++++------------ src/core/lib/channel/channelz_registry.cc | 51 +++++---- src/core/lib/channel/channelz_registry.h | 50 ++------- test/core/channel/channelz_registry_test.cc | 30 ++--- test/core/channel/channelz_test.cc | 42 ++----- 9 files changed, 223 insertions(+), 285 deletions(-) (limited to 'src/core') 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(GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC), @@ -111,20 +144,21 @@ RefCountedPtr 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( - 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 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::RefCountedPtr 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( + 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(grpc_channel_get_target(channel_)); - channel_uuid_ = ChannelzRegistry::RegisterChannelNode(this); + target_(UniquePtr(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::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 { 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 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 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 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(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(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 top_level_channels; + InlinedVector 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(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(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(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 entities_; + InlinedVector 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 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 {}; - -TEST_P(ChannelzSubchannelTest, BasicTest) { - grpc_core::ExecCtx exec_ctx; - RefCountedPtr channelz_subchannel = - MakeRefCounted(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 -- cgit v1.2.3 From 835dab6a464b3246f6bdc3b1bb0fe706551a0260 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 20 Jul 2018 16:17:48 -0700 Subject: Full subchannel support --- .../ext/filters/client_channel/client_channel.cc | 5 +++- .../client_channel/client_channel_channelz.cc | 2 ++ src/core/ext/filters/client_channel/subchannel.cc | 33 ++++++++++++++-------- src/core/ext/filters/client_channel/subchannel.h | 10 ++++++- src/core/lib/channel/channel_stack.h | 1 + src/core/lib/surface/call.cc | 22 ++++++++++++++- src/core/lib/surface/call.h | 13 +++++++++ test/core/channel/channel_stack_test.cc | 3 +- test/core/end2end/tests/channelz.cc | 4 +++ 9 files changed, 77 insertions(+), 16 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 024c9d737e..13a0b95511 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -892,6 +892,7 @@ typedef struct client_channel_call_data { grpc_millis deadline; gpr_arena* arena; grpc_call_stack* owning_call; + grpc_call* call; grpc_call_combiner* call_combiner; grpc_core::RefCountedPtr retry_throttle_data; @@ -2561,7 +2562,8 @@ static void create_subchannel_call(grpc_call_element* elem, grpc_error* error) { calld->arena, // arena calld->pick.subchannel_call_context, // context calld->call_combiner, // call_combiner - parent_data_size // parent_data_size + parent_data_size, // parent_data_size + calld->call // call }; grpc_error* new_error = calld->pick.connected_subchannel->CreateCall( call_args, &calld->subchannel_call); @@ -3092,6 +3094,7 @@ static grpc_error* cc_init_call_elem(grpc_call_element* elem, calld->arena = args->arena; calld->owning_call = args->call_stack; calld->call_combiner = args->call_combiner; + calld->call = args->call; if (GPR_LIKELY(chand->deadline_checking_enabled)) { grpc_deadline_state_init(elem, args->call_stack, args->call_combiner, calld->deadline); 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 0db9799a65..a1ecbe75a2 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -126,6 +126,8 @@ grpc_json* ClientChannelNode::RenderJson() { // as CallCountingAndTracingNode to populate trace and call count data. PopulateTrace(json); PopulateCallData(json); + // reset to the top level + json = top_level_json; PopulateChildRefs(json); return top_level_json; } diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 8dfbd33ffe..a15cfd43c3 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -46,6 +46,7 @@ #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel_init.h" #include "src/core/lib/transport/connectivity_state.h" @@ -640,8 +641,8 @@ static bool publish_transport_locked(grpc_subchannel* c) { } /* publish */ - c->connected_subchannel.reset( - grpc_core::New(stk)); + c->connected_subchannel.reset(grpc_core::New( + stk, c->channelz_subchannel.get())); gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p", c->connected_subchannel.get(), c); @@ -796,9 +797,12 @@ grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr) { namespace grpc_core { -ConnectedSubchannel::ConnectedSubchannel(grpc_channel_stack* channel_stack) +ConnectedSubchannel::ConnectedSubchannel( + grpc_channel_stack* channel_stack, + channelz::SubchannelNode* channelz_subchannel) : RefCountedWithTracing(&grpc_trace_stream_refcount), - channel_stack_(channel_stack) {} + channel_stack_(channel_stack), + channelz_subchannel_(channelz_subchannel) {} ConnectedSubchannel::~ConnectedSubchannel() { GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor"); @@ -845,14 +849,15 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, connection.release(); // Ref is passed to the grpc_subchannel_call object. (*call)->connection = this; const grpc_call_element_args call_args = { - callstk, /* call_stack */ - nullptr, /* server_transport_data */ - args.context, /* context */ - args.path, /* path */ - args.start_time, /* start_time */ - args.deadline, /* deadline */ - args.arena, /* arena */ - args.call_combiner /* call_combiner */ + callstk, /* call_stack */ + nullptr, /* server_transport_data */ + args.context, /* context */ + args.path, /* path */ + args.start_time, /* start_time */ + args.deadline, /* deadline */ + args.arena, /* arena */ + args.call_combiner, /* call_combiner */ + args.call /* call */ }; grpc_error* error = grpc_call_stack_init( channel_stack_, 1, subchannel_call_destroy, *call, &call_args); @@ -861,6 +866,10 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, gpr_log(GPR_ERROR, "error: %s", error_string); return error; } + if (channelz_subchannel_ != nullptr) { + channelz_subchannel_->RecordCallStarted(); + grpc_call_set_channelz_subchannel(args.call, channelz_subchannel_); + } grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); return GRPC_ERROR_NONE; } diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index dd3a2d9621..d62348488e 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -83,9 +83,11 @@ class ConnectedSubchannel : public RefCountedWithTracing { grpc_call_context_element* context; grpc_call_combiner* call_combiner; size_t parent_data_size; + grpc_call* call; }; - explicit ConnectedSubchannel(grpc_channel_stack* channel_stack); + explicit ConnectedSubchannel(grpc_channel_stack* channel_stack, + channelz::SubchannelNode* channelz_subchannel); ~ConnectedSubchannel(); grpc_channel_stack* channel_stack() { return channel_stack_; } @@ -94,9 +96,15 @@ class ConnectedSubchannel : public RefCountedWithTracing { grpc_closure* closure); void Ping(grpc_closure* on_initiate, grpc_closure* on_ack); grpc_error* CreateCall(const CallArgs& args, grpc_subchannel_call** call); + channelz::SubchannelNode* channelz_subchannel() { + return channelz_subchannel_; + } private: grpc_channel_stack* channel_stack_; + // backpointer to the channelz node in this connected subchannel's + // owning subchannel. + channelz::SubchannelNode* channelz_subchannel_; }; } // namespace grpc_core diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h index 7581f937b6..727f36a6f8 100644 --- a/src/core/lib/channel/channel_stack.h +++ b/src/core/lib/channel/channel_stack.h @@ -71,6 +71,7 @@ typedef struct { grpc_millis deadline; gpr_arena* arena; grpc_call_combiner* call_combiner; + grpc_call* call; } grpc_call_element_args; typedef struct { diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 88e015ce22..6545af8f72 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -170,6 +170,11 @@ struct grpc_call { /* parent_call* */ gpr_atm parent_call_atm; child_call* child; + // the call holds onto this so that once the call knows if the RPC was + // a success or failure, it can update the channelz bookkeeping for the + // subchannel that sent it. + grpc_core::channelz::CallCountingAndTracingNode* channelz_subchannel_; + /* client or server call */ bool is_client; /** has grpc_call_unref been called */ @@ -269,6 +274,11 @@ struct grpc_call { gpr_atm recv_state; }; +void grpc_call_set_channelz_subchannel( + grpc_call* call, grpc_core::channelz::CallCountingAndTracingNode* node) { + call->channelz_subchannel_ = node; +} + grpc_core::TraceFlag grpc_call_error_trace(false, "call_error"); grpc_core::TraceFlag grpc_compression_trace(false, "compression"); @@ -444,7 +454,8 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, call->start_time, send_deadline, call->arena, - &call->call_combiner}; + &call->call_combiner, + call}; add_init_error(&error, grpc_call_stack_init(channel_stack, 1, destroy_call, call, &call_args)); // Publish this call to parent only after the call stack has been initialized. @@ -1263,6 +1274,7 @@ static void post_batch_completion(batch_control* bctl) { get_final_status(call, set_cancelled_value, call->final_op.server.cancelled, nullptr, nullptr); } + // Record channelz data for the channel. grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(call->channel); if (channelz_channel != nullptr) { @@ -1272,6 +1284,14 @@ static void post_batch_completion(batch_control* bctl) { channelz_channel->RecordCallSucceeded(); } } + // Record channelz data for the subchannel. + if (call->channelz_subchannel_ != nullptr) { + if (*call->final_op.client.status != GRPC_STATUS_OK) { + call->channelz_subchannel_->RecordCallFailed(); + } else { + call->channelz_subchannel_->RecordCallSucceeded(); + } + } GRPC_ERROR_UNREF(error); error = GRPC_ERROR_NONE; } diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h index b3b06059d4..200c840c61 100644 --- a/src/core/lib/surface/call.h +++ b/src/core/lib/surface/call.h @@ -110,6 +110,19 @@ size_t grpc_call_get_initial_size_estimate(); grpc_compression_algorithm grpc_call_compression_for_level( grpc_call* call, grpc_compression_level level); +namespace grpc_core { +namespace channelz { +class CallCountingAndTracingNode; +} // namespace channelz +} // namespace grpc_core + +// We need this so that a subchannel selected for a call can add itself to +// the call's data structure. This allows the call to trigger the correct +// channelz bookkeeping on the subchannel once the call knows if the RPC was +// successful or not. +void grpc_call_set_channelz_subchannel( + grpc_call* call, grpc_core::channelz::CallCountingAndTracingNode* node); + extern grpc_core::TraceFlag grpc_call_error_trace; extern grpc_core::TraceFlag grpc_compression_trace; diff --git a/test/core/channel/channel_stack_test.cc b/test/core/channel/channel_stack_test.cc index 2f5329a96d..4dc2ee3f55 100644 --- a/test/core/channel/channel_stack_test.cc +++ b/test/core/channel/channel_stack_test.cc @@ -124,7 +124,8 @@ static void test_create_channel_stack(void) { gpr_now(GPR_CLOCK_MONOTONIC), /* start_time */ GRPC_MILLIS_INF_FUTURE, /* deadline */ nullptr, /* arena */ - nullptr /* call_combiner */ + nullptr, /* call_combiner */ + nullptr /* call */ }; grpc_error* error = grpc_call_stack_init(channel_stack, 1, free_call, call_stack, &args); diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 533703a2be..754c3d3741 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -241,6 +241,10 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); + json = grpc_channelz_get_subchannel(2); + gpr_log(GPR_INFO, "%s", json); + gpr_free(json); + end_test(&f); config.tear_down_data(&f); } -- cgit v1.2.3 From f081cf67d16049dc07141420601272d9f5988b1c Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 20 Jul 2018 17:55:36 -0700 Subject: refactor --- .../client_channel/client_channel_channelz.cc | 16 ++-- .../client_channel/client_channel_channelz.h | 2 - .../client_channel/lb_policy/grpclb/grpclb.cc | 2 +- .../client_channel/lb_policy/subchannel_list.h | 2 +- src/core/lib/channel/channel_trace.cc | 42 ++++----- src/core/lib/channel/channel_trace.h | 26 +++--- src/core/lib/channel/channelz.cc | 14 +-- src/core/lib/channel/channelz.h | 10 +-- test/core/channel/channel_trace_test.cc | 100 +++++++++++---------- test/core/channel/channelz_test.cc | 2 +- 10 files changed, 102 insertions(+), 114 deletions(-) (limited to 'src/core') 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 a1ecbe75a2..996a871f38 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -108,8 +108,8 @@ grpc_json* ClientChannelNode::RenderJson() { GRPC_JSON_OBJECT, false); json = json_iterator; json_iterator = nullptr; - json_iterator = grpc_json_add_number_string_child( - json, json_iterator, "channelId", channel_uuid()); + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "channelId", uuid()); // reset json iterators to top level object json = top_level_json; json_iterator = nullptr; @@ -152,13 +152,9 @@ SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, channel_tracer_max_nodes), subchannel_(subchannel), target_(UniquePtr( - gpr_strdup(grpc_subchannel_get_target(subchannel_)))) { - subchannel_uuid_ = ChannelzRegistry::Register(this); -} + gpr_strdup(grpc_subchannel_get_target(subchannel_)))) {} -SubchannelNode::~SubchannelNode() { - ChannelzRegistry::Unregister(subchannel_uuid_); -} +SubchannelNode::~SubchannelNode() {} void SubchannelNode::PopulateConnectivityState(grpc_json* json) { grpc_connectivity_state state; @@ -182,8 +178,8 @@ grpc_json* SubchannelNode::RenderJson() { GRPC_JSON_OBJECT, false); json = json_iterator; json_iterator = nullptr; - json_iterator = grpc_json_add_number_string_child( - json, json_iterator, "subchannelId", subchannel_uuid_); + json_iterator = grpc_json_add_number_string_child(json, json_iterator, + "subchannelId", uuid()); // reset json iterators to top level object json = top_level_json; json_iterator = nullptr; 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 73eea7cecf..45df756b91 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -79,8 +79,6 @@ class SubchannelNode : public CallCountingAndTracingNode { 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 diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 959c7441a3..dc475d3d68 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -1294,7 +1294,7 @@ void GrpcLb::FillChildRefsForChannelz(ChildRefsList* child_subchannels, grpc_core::channelz::ChannelNode* channel_node = grpc_channel_get_channelz_node(lb_channel_); if (channel_node != nullptr) { - child_channels->push_back(channel_node->channel_uuid()); + child_channels->push_back(channel_node->uuid()); } } } diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h index 018ac3bb86..199b9a3c13 100644 --- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h @@ -196,7 +196,7 @@ class SubchannelList grpc_core::channelz::SubchannelNode* subchannel_node = grpc_subchannel_get_channelz_node(subchannels_[i].subchannel()); if (subchannel_node != nullptr) { - refs_list->push_back(subchannel_node->subchannel_uuid()); + refs_list->push_back(subchannel_node->uuid()); } } } diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc index dd6fdeed54..ba2b3bcad6 100644 --- a/src/core/lib/channel/channel_trace.cc +++ b/src/core/lib/channel/channel_trace.cc @@ -41,16 +41,14 @@ namespace grpc_core { namespace channelz { -ChannelTrace::TraceEvent::TraceEvent( - Severity severity, grpc_slice data, - RefCountedPtr referenced_channel, ReferencedType type) +ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data, + RefCountedPtr referenced_entity) : severity_(severity), data_(data), timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), GPR_CLOCK_REALTIME)), next_(nullptr), - referenced_channel_(std::move(referenced_channel)), - referenced_type_(type) {} + referenced_entity_(std::move(referenced_entity)) {} ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data) : severity_(severity), @@ -112,21 +110,11 @@ void ChannelTrace::AddTraceEvent(Severity severity, grpc_slice data) { void ChannelTrace::AddTraceEventReferencingChannel( Severity severity, grpc_slice data, - RefCountedPtr referenced_channel) { - if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 - // create and fill up the new event - AddTraceEventHelper(New( - severity, data, std::move(referenced_channel), ReferencedType::Channel)); -} - -void ChannelTrace::AddTraceEventReferencingSubchannel( - Severity severity, grpc_slice data, - RefCountedPtr referenced_subchannel) { + RefCountedPtr referenced_entity) { if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 // create and fill up the new event - AddTraceEventHelper(New(severity, data, - std::move(referenced_subchannel), - ReferencedType::Subchannel)); + AddTraceEventHelper( + New(severity, data, std::move(referenced_entity))); } namespace { @@ -157,18 +145,24 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const { json_iterator = grpc_json_create_child(json_iterator, json, "timestamp", gpr_format_timespec(timestamp_), GRPC_JSON_STRING, true); - if (referenced_channel_ != nullptr) { + if (referenced_entity_ != nullptr) { + GPR_ASSERT( + referenced_entity_->type() == BaseNode::EntityType::kSubchannel || + referenced_entity_->type() == BaseNode::EntityType::kTopLevelChannel || + referenced_entity_->type() == BaseNode::EntityType::kInternalChannel); char* uuid_str; - gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_channel_->channel_uuid()); + gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_entity_->uuid()); grpc_json* child_ref = grpc_json_create_child( json_iterator, json, - (referenced_type_ == ReferencedType::Channel) ? "channelRef" - : "subchannelRef", + (referenced_entity_->type() == BaseNode::EntityType::kSubchannel) + ? "subchannelRef" + : "channelRef", nullptr, GRPC_JSON_OBJECT, false); json_iterator = grpc_json_create_child( nullptr, child_ref, - (referenced_type_ == ReferencedType::Channel) ? "channelId" - : "subchannelId", + (referenced_entity_->type() == BaseNode::EntityType::kSubchannel) + ? "subchannelId" + : "channelId", uuid_str, GRPC_JSON_STRING, true); json_iterator = child_ref; } diff --git a/src/core/lib/channel/channel_trace.h b/src/core/lib/channel/channel_trace.h index 596af7402f..cef8814d5f 100644 --- a/src/core/lib/channel/channel_trace.h +++ b/src/core/lib/channel/channel_trace.h @@ -30,7 +30,7 @@ namespace grpc_core { namespace channelz { -class ChannelNode; +class BaseNode; // Object used to hold live data for a channel. This data is exposed via the // channelz service: @@ -55,35 +55,32 @@ class ChannelTrace { void AddTraceEvent(Severity severity, grpc_slice data); // Adds a new trace event to the tracing object. This trace event refers to a - // an event on a child of the channel. For example, if this channel has - // created a new subchannel, then it would record that with a TraceEvent - // referencing the new subchannel. + // an event that concerns a different channelz entity. For example, if this + // channel has created a new subchannel, then it would record that with + // a TraceEvent referencing the new subchannel. // // TODO(ncteisen): as this call is used more and more throughout the gRPC // stack, determine if it makes more sense to accept a char* instead of a // slice. void AddTraceEventReferencingChannel( Severity severity, grpc_slice data, - RefCountedPtr referenced_channel); - void AddTraceEventReferencingSubchannel( - Severity severity, grpc_slice data, - RefCountedPtr referenced_subchannel); + RefCountedPtr referenced_entity); + // void AddTraceEventWithReference( + // Severity severity, grpc_slice data, + // RefCountedPtr referenced_entity); // Creates and returns the raw grpc_json object, so a parent channelz // object may incorporate the json before rendering. grpc_json* RenderJson() const; private: - // Types of objects that can be references by trace events. - enum class ReferencedType { Channel, Subchannel }; // Private class to encapsulate all the data and bookkeeping needed for a // a trace event. class TraceEvent { public: // Constructor for a TraceEvent that references a different channel. TraceEvent(Severity severity, grpc_slice data, - RefCountedPtr referenced_channel, - ReferencedType type); + RefCountedPtr referenced); // Constructor for a TraceEvent that does not reverence a different // channel. @@ -105,10 +102,7 @@ class ChannelTrace { gpr_timespec timestamp_; TraceEvent* next_; // the tracer object for the (sub)channel that this trace event refers to. - RefCountedPtr referenced_channel_; - // the type that the referenced tracer points to. Unused if this trace - // does not point to any channel or subchannel - ReferencedType referenced_type_; + RefCountedPtr referenced_entity_; }; // TraceEvent // Internal helper to add and link in a trace event diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index d7f2d6a9a2..eec2cd61b2 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -41,6 +41,12 @@ namespace grpc_core { namespace channelz { +BaseNode::BaseNode(EntityType type) : type_(type) { + uuid_ = ChannelzRegistry::Register(this); +} + +BaseNode::~BaseNode() { ChannelzRegistry::Unregister(uuid_); } + char* BaseNode::RenderJsonString() { grpc_json* json = RenderJson(); char* json_str = grpc_json_dump_to_string(json, 0); @@ -103,11 +109,9 @@ ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, : EntityType::kInternalChannel, channel_tracer_max_nodes), channel_(channel), - target_(UniquePtr(grpc_channel_get_target(channel_))) { - channel_uuid_ = ChannelzRegistry::Register(this); -} + target_(UniquePtr(grpc_channel_get_target(channel_))) {} -ChannelNode::~ChannelNode() { ChannelzRegistry::Unregister(channel_uuid_); } +ChannelNode::~ChannelNode() {} grpc_json* ChannelNode::RenderJson() { // We need to track these three json objects to build our object @@ -120,7 +124,7 @@ grpc_json* ChannelNode::RenderJson() { json = json_iterator; json_iterator = nullptr; json_iterator = grpc_json_add_number_string_child(json, json_iterator, - "channelId", channel_uuid_); + "channelId", uuid()); // reset json iterators to top level object json = top_level_json; json_iterator = nullptr; diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 1273545663..67cd1fec2d 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -60,9 +60,8 @@ class BaseNode : public RefCounted { kSocket, }; - // we track is_top_level_channel to support GetTopChannels - BaseNode(EntityType type) : type_(type) {} - virtual ~BaseNode() {} + BaseNode(EntityType type); + virtual ~BaseNode(); // All children must implement this function. virtual grpc_json* RenderJson() GRPC_ABSTRACT; @@ -72,11 +71,14 @@ class BaseNode : public RefCounted { char* RenderJsonString(); EntityType type() const { return type_; } + intptr_t uuid() const { return uuid_; } private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW + friend class ChannelTrace; EntityType type_; + intptr_t uuid_; }; // This class is the parent for the channelz entities that deal with Channels @@ -136,8 +138,6 @@ class ChannelNode : public CallCountingAndTracingNode { bool ChannelIsDestroyed() { return channel_ == nullptr; } - intptr_t channel_uuid() { return channel_uuid_; } - protected: ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index 99d9a4847f..703a9e457f 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -156,7 +156,7 @@ TEST_P(ChannelTracerTest, ComplexTest) { ChannelFixture channel1(GetParam()); RefCountedPtr sc1 = MakeRefCounted(channel1.channel(), GetParam(), true); - tracer.AddTraceEventReferencingSubchannel( + tracer.AddTraceEventReferencingChannel( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); @@ -177,7 +177,7 @@ TEST_P(ChannelTracerTest, ComplexTest) { tracer.AddTraceEventReferencingChannel( ChannelTrace::Severity::Info, grpc_slice_from_static_string("LB channel two created"), sc2); - tracer.AddTraceEventReferencingSubchannel( + tracer.AddTraceEventReferencingChannel( ChannelTrace::Severity::Warning, grpc_slice_from_static_string("subchannel one inactive"), sc1); ValidateChannelTrace(&tracer, 7, GetParam()); @@ -191,53 +191,55 @@ TEST_P(ChannelTracerTest, ComplexTest) { sc2.reset(nullptr); } -// Test a case in which the parent channel has subchannels and the subchannels -// have connections. Ensures that everything lives as long as it should then -// gets deleted. -TEST_P(ChannelTracerTest, TestNesting) { - grpc_core::ExecCtx exec_ctx; - ChannelTrace tracer(GetParam()); - AddSimpleTrace(&tracer); - AddSimpleTrace(&tracer); - ValidateChannelTrace(&tracer, 2, GetParam()); - ChannelFixture channel1(GetParam()); - RefCountedPtr sc1 = - MakeRefCounted(channel1.channel(), GetParam(), true); - tracer.AddTraceEventReferencingChannel( - ChannelTrace::Severity::Info, - grpc_slice_from_static_string("subchannel one created"), sc1); - ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(sc1->trace()); - ChannelFixture channel2(GetParam()); - RefCountedPtr conn1 = - MakeRefCounted(channel2.channel(), GetParam(), true); - // nesting one level deeper. - sc1->trace()->AddTraceEventReferencingSubchannel( - ChannelTrace::Severity::Info, - grpc_slice_from_static_string("connection one created"), conn1); - ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(conn1->trace()); - AddSimpleTrace(&tracer); - AddSimpleTrace(&tracer); - ValidateChannelTrace(&tracer, 5, GetParam()); - ValidateChannelTrace(conn1->trace(), 1, GetParam()); - ChannelFixture channel3(GetParam()); - RefCountedPtr sc2 = - MakeRefCounted(channel3.channel(), GetParam(), true); - tracer.AddTraceEventReferencingSubchannel( - ChannelTrace::Severity::Info, - grpc_slice_from_static_string("subchannel two created"), sc2); - // this trace should not get added to the parents children since it is already - // present in the tracer. - tracer.AddTraceEventReferencingChannel( - ChannelTrace::Severity::Warning, - grpc_slice_from_static_string("subchannel one inactive"), sc1); - AddSimpleTrace(&tracer); - ValidateChannelTrace(&tracer, 8, GetParam()); - sc1.reset(nullptr); - sc2.reset(nullptr); - conn1.reset(nullptr); -} +// // Test a case in which the parent channel has subchannels and the +// subchannels +// // have connections. Ensures that everything lives as long as it should then +// // gets deleted. +// TEST_P(ChannelTracerTest, TestNesting) { +// grpc_core::ExecCtx exec_ctx; +// ChannelTrace tracer(GetParam()); +// AddSimpleTrace(&tracer); +// AddSimpleTrace(&tracer); +// ValidateChannelTrace(&tracer, 2, GetParam()); +// ChannelFixture channel1(GetParam()); +// RefCountedPtr sc1 = +// MakeRefCounted(channel1.channel(), GetParam(), true); +// tracer.AddTraceEventReferencingChannel( +// ChannelTrace::Severity::Info, +// grpc_slice_from_static_string("subchannel one created"), sc1); +// ValidateChannelTrace(&tracer, 3, GetParam()); +// AddSimpleTrace(sc1->trace()); +// ChannelFixture channel2(GetParam()); +// RefCountedPtr conn1 = +// MakeRefCounted(channel2.channel(), GetParam(), true); +// // nesting one level deeper. +// sc1->trace()->AddTraceEventReferencingChannel( +// ChannelTrace::Severity::Info, +// grpc_slice_from_static_string("connection one created"), conn1); +// ValidateChannelTrace(&tracer, 3, GetParam()); +// AddSimpleTrace(conn1->trace()); +// AddSimpleTrace(&tracer); +// AddSimpleTrace(&tracer); +// ValidateChannelTrace(&tracer, 5, GetParam()); +// ValidateChannelTrace(conn1->trace(), 1, GetParam()); +// ChannelFixture channel3(GetParam()); +// RefCountedPtr sc2 = +// MakeRefCounted(channel3.channel(), GetParam(), true); +// tracer.AddTraceEventReferencingChannel( +// ChannelTrace::Severity::Info, +// grpc_slice_from_static_string("subchannel two created"), sc2); +// // this trace should not get added to the parents children since it is +// already +// // present in the tracer. +// tracer.AddTraceEventReferencingChannel( +// ChannelTrace::Severity::Warning, +// grpc_slice_from_static_string("subchannel one inactive"), sc1); +// AddSimpleTrace(&tracer); +// ValidateChannelTrace(&tracer, 8, GetParam()); +// sc1.reset(nullptr); +// sc2.reset(nullptr); +// conn1.reset(nullptr); +// } INSTANTIATE_TEST_CASE_P(ChannelTracerTestSweep, ChannelTracerTest, ::testing::Values(0, 1, 2, 6, 10, 15)); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index ec1c9f6faf..9f3756c182 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -158,7 +158,7 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) { ValidateCounters(json_str, args); gpr_free(json_str); // also check that the core API formats this the correct way - char* core_api_json_str = grpc_channelz_get_channel(channel->channel_uuid()); + char* core_api_json_str = grpc_channelz_get_channel(channel->uuid()); grpc::testing::ValidateGetChannelResponseProtoJsonTranslation( core_api_json_str); gpr_free(core_api_json_str); -- cgit v1.2.3 From 1dc063c093745279452877861da2bacfcaaea95f Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 23 Jul 2018 19:05:27 -0700 Subject: Refactor ChannelTrace to compile --- src/core/lib/channel/channel_trace.cc | 63 +++++++++++++++++++++++------------ src/core/lib/channel/channel_trace.h | 20 +++++++---- src/core/lib/gprpp/ref_counted.h | 3 +- 3 files changed, 56 insertions(+), 30 deletions(-) (limited to 'src/core') diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc index ba2b3bcad6..7d8bb391f8 100644 --- a/src/core/lib/channel/channel_trace.cc +++ b/src/core/lib/channel/channel_trace.cc @@ -41,14 +41,25 @@ namespace grpc_core { namespace channelz { -ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data, - RefCountedPtr referenced_entity) +ChannelTrace::TraceEvent::TraceEvent( + Severity severity, grpc_slice data, + RefCountedPtr referenced_channel) : severity_(severity), data_(data), timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), GPR_CLOCK_REALTIME)), next_(nullptr), - referenced_entity_(std::move(referenced_entity)) {} + referenced_channel_(std::move(referenced_channel)) {} + +// ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data, +// RefCountedPtr +// referenced_subchannel) +// : severity_(severity), +// data_(data), +// timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), +// GPR_CLOCK_REALTIME)), +// next_(nullptr), +// referenced_subchannel_(std::move(referenced_subchannel)) {} ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data) : severity_(severity), @@ -110,13 +121,22 @@ void ChannelTrace::AddTraceEvent(Severity severity, grpc_slice data) { void ChannelTrace::AddTraceEventReferencingChannel( Severity severity, grpc_slice data, - RefCountedPtr referenced_entity) { + RefCountedPtr referenced_channel) { if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 // create and fill up the new event AddTraceEventHelper( - New(severity, data, std::move(referenced_entity))); + New(severity, data, std::move(referenced_channel))); } +// void ChannelTrace::AddTraceEventReferencingSubchannel( +// Severity severity, grpc_slice data, +// RefCountedPtr referenced_subchannel) { +// if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 +// // create and fill up the new event +// AddTraceEventHelper( +// New(severity, data, std::move(referenced_subchannel))); +// } + namespace { const char* severity_string(ChannelTrace::Severity severity) { @@ -145,27 +165,26 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const { json_iterator = grpc_json_create_child(json_iterator, json, "timestamp", gpr_format_timespec(timestamp_), GRPC_JSON_STRING, true); - if (referenced_entity_ != nullptr) { - GPR_ASSERT( - referenced_entity_->type() == BaseNode::EntityType::kSubchannel || - referenced_entity_->type() == BaseNode::EntityType::kTopLevelChannel || - referenced_entity_->type() == BaseNode::EntityType::kInternalChannel); + if (referenced_channel_ != nullptr) { char* uuid_str; - gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_entity_->uuid()); + gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_channel_->uuid()); grpc_json* child_ref = grpc_json_create_child( - json_iterator, json, - (referenced_entity_->type() == BaseNode::EntityType::kSubchannel) - ? "subchannelRef" - : "channelRef", - nullptr, GRPC_JSON_OBJECT, false); - json_iterator = grpc_json_create_child( - nullptr, child_ref, - (referenced_entity_->type() == BaseNode::EntityType::kSubchannel) - ? "subchannelId" - : "channelId", - uuid_str, GRPC_JSON_STRING, true); + json_iterator, json, "channelRef", nullptr, GRPC_JSON_OBJECT, false); + json_iterator = grpc_json_create_child(nullptr, child_ref, "channelId", + uuid_str, GRPC_JSON_STRING, true); json_iterator = child_ref; } + // else { + // char* uuid_str; + // gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_subchannel_->uuid()); + // grpc_json* child_ref = grpc_json_create_child( + // json_iterator, json, "subchannelRef", + // nullptr, GRPC_JSON_OBJECT, false); + // json_iterator = grpc_json_create_child( + // nullptr, child_ref, "subchannelId", + // uuid_str, GRPC_JSON_STRING, true); + // json_iterator = child_ref; + // } } grpc_json* ChannelTrace::RenderJson() const { diff --git a/src/core/lib/channel/channel_trace.h b/src/core/lib/channel/channel_trace.h index cef8814d5f..543eabf13a 100644 --- a/src/core/lib/channel/channel_trace.h +++ b/src/core/lib/channel/channel_trace.h @@ -30,7 +30,8 @@ namespace grpc_core { namespace channelz { -class BaseNode; +class ChannelNode; +class SubchannelNode; // Object used to hold live data for a channel. This data is exposed via the // channelz service: @@ -64,10 +65,10 @@ class ChannelTrace { // slice. void AddTraceEventReferencingChannel( Severity severity, grpc_slice data, - RefCountedPtr referenced_entity); - // void AddTraceEventWithReference( + RefCountedPtr referenced_channel); + // void AddTraceEventReferencingSubchannel( // Severity severity, grpc_slice data, - // RefCountedPtr referenced_entity); + // RefCountedPtr referenced_subchannel); // Creates and returns the raw grpc_json object, so a parent channelz // object may incorporate the json before rendering. @@ -78,9 +79,13 @@ class ChannelTrace { // a trace event. class TraceEvent { public: - // Constructor for a TraceEvent that references a different channel. + // Constructor for a TraceEvent that references a channel. TraceEvent(Severity severity, grpc_slice data, - RefCountedPtr referenced); + RefCountedPtr referenced_channel); + + // Constructor for a TraceEvent that references a subchannel. + TraceEvent(Severity severity, grpc_slice data, + RefCountedPtr referenced_subchannel); // Constructor for a TraceEvent that does not reverence a different // channel. @@ -102,7 +107,8 @@ class ChannelTrace { gpr_timespec timestamp_; TraceEvent* next_; // the tracer object for the (sub)channel that this trace event refers to. - RefCountedPtr referenced_entity_; + RefCountedPtr referenced_channel_; + // RefCountedPtr referenced_subchannel_; }; // TraceEvent // Internal helper to add and link in a trace event diff --git a/src/core/lib/gprpp/ref_counted.h b/src/core/lib/gprpp/ref_counted.h index ddac5bd475..3d6a32ddcf 100644 --- a/src/core/lib/gprpp/ref_counted.h +++ b/src/core/lib/gprpp/ref_counted.h @@ -73,7 +73,8 @@ class RefCounted { private: // Allow RefCountedPtr<> to access IncrementRefCount(). - friend class RefCountedPtr; + template + friend class RefCountedPtr; void IncrementRefCount() { gpr_ref(&refs_); } -- cgit v1.2.3 From a8d5c21b8864202e205fc210e369dc72abe606f2 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 24 Jul 2018 09:41:07 -0700 Subject: reviewer feedback --- .../client_channel/client_channel_channelz.h | 14 ++++--------- src/core/lib/channel/channelz.cc | 5 ++--- src/core/lib/channel/channelz.h | 24 +++++----------------- 3 files changed, 11 insertions(+), 32 deletions(-) (limited to 'src/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 45df756b91..1bc555448c 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -45,20 +45,17 @@ class ClientChannelNode : public ChannelNode { grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); + ClientChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); + virtual ~ClientChannelNode() {} + grpc_json* RenderJson() override; // Helper to create a channel arg to ensure this type of ChannelNode is // created. static grpc_arg CreateChannelArg(); - protected: - ClientChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, - bool is_top_level_channel); - virtual ~ClientChannelNode() {} - private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW grpc_channel_element* client_channel_; // helpers @@ -80,9 +77,6 @@ class SubchannelNode : public CallCountingAndTracingNode { grpc_json* RenderJson() override; 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 target_; diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index eec2cd61b2..4fbc441c0a 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -41,9 +41,8 @@ namespace grpc_core { namespace channelz { -BaseNode::BaseNode(EntityType type) : type_(type) { - uuid_ = ChannelzRegistry::Register(this); -} +BaseNode::BaseNode(EntityType type) + : type_(type), uuid_(ChannelzRegistry::Register(this)) {} BaseNode::~BaseNode() { ChannelzRegistry::Unregister(uuid_); } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 67cd1fec2d..5496163fb9 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -74,11 +74,9 @@ class BaseNode : public RefCounted { intptr_t uuid() const { return uuid_; } private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW friend class ChannelTrace; EntityType type_; - intptr_t uuid_; + const intptr_t uuid_; }; // This class is the parent for the channelz entities that deal with Channels @@ -109,9 +107,6 @@ class CallCountingAndTracingNode : public BaseNode { void PopulateCallData(grpc_json* json); private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW - // testing peer friend. friend class testing::CallCountingAndTracingNodePeer; @@ -129,6 +124,10 @@ class ChannelNode : public CallCountingAndTracingNode { grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel); + ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, + bool is_top_level_channel); + ~ChannelNode() override; + grpc_json* RenderJson() override; void MarkChannelDestroyed() { @@ -139,19 +138,12 @@ class ChannelNode : public CallCountingAndTracingNode { bool ChannelIsDestroyed() { return channel_ == nullptr; } 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 - grpc_channel* channel_ = nullptr; UniquePtr target_; - intptr_t channel_uuid_; }; // Handles channelz bookkeeping for servers @@ -162,10 +154,6 @@ class ServerNode : public CallCountingAndTracingNode { : 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 }; // Handles channelz bookkeeping for sockets @@ -176,8 +164,6 @@ class SocketNode : public BaseNode { ~SocketNode() override {} private: - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW }; // Creation functions -- cgit v1.2.3 From bfdfe9fefbc92f78da6247a85e7e7de4b30727b9 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 24 Jul 2018 10:13:52 -0700 Subject: Restructure heirarchy --- .../ext/filters/client_channel/client_channel.cc | 1 - .../client_channel/client_channel_channelz.cc | 16 +-- .../client_channel/client_channel_channelz.h | 7 +- src/core/ext/filters/client_channel/subchannel.cc | 9 +- src/core/lib/channel/channel_stack.h | 1 - src/core/lib/channel/channelz.cc | 16 ++- src/core/lib/channel/channelz.h | 21 ++-- src/core/lib/surface/call.cc | 27 +---- src/core/lib/surface/call.h | 13 --- src/core/lib/surface/channel.cc | 4 +- test/core/channel/channel_stack_test.cc | 1 - test/core/channel/channel_trace_test.cc | 112 ++++++++++----------- test/core/channel/channelz_test.cc | 38 +++---- 13 files changed, 116 insertions(+), 150 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 13a0b95511..683cb0e01d 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -3094,7 +3094,6 @@ static grpc_error* cc_init_call_elem(grpc_call_element* elem, calld->arena = args->arena; calld->owning_call = args->call_stack; calld->call_combiner = args->call_combiner; - calld->call = args->call; if (GPR_LIKELY(chand->deadline_checking_enabled)) { grpc_deadline_state_init(elem, args->call_stack, args->call_combiner, calld->deadline); 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 996a871f38..b209acc2ea 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -124,8 +124,8 @@ grpc_json* ClientChannelNode::RenderJson() { 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); + counter_and_tracer()->PopulateTrace(json); + counter_and_tracer()->PopulateCallData(json); // reset to the top level json = top_level_json; PopulateChildRefs(json); @@ -148,11 +148,11 @@ RefCountedPtr ClientChannelNode::MakeClientChannelNode( SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes) - : CallCountingAndTracingNode(EntityType::kSubchannel, - channel_tracer_max_nodes), + : BaseNode(EntityType::kSubchannel), subchannel_(subchannel), - target_(UniquePtr( - gpr_strdup(grpc_subchannel_get_target(subchannel_)))) {} + target_( + UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_)))), + counter_and_tracer_(channel_tracer_max_nodes) {} SubchannelNode::~SubchannelNode() {} @@ -192,8 +192,8 @@ grpc_json* SubchannelNode::RenderJson() { GPR_ASSERT(target_.get() != nullptr); grpc_json_create_child(nullptr, json, "target", target_.get(), GRPC_JSON_STRING, false); - PopulateTrace(json); - PopulateCallData(json); + counter_and_tracer_.PopulateTrace(json); + counter_and_tracer_.PopulateCallData(json); return top_level_json; } 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 1bc555448c..f5344c049e 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -64,7 +64,7 @@ class ClientChannelNode : public ChannelNode { }; // Handles channelz bookkeeping for sockets -class SubchannelNode : public CallCountingAndTracingNode { +class SubchannelNode : public BaseNode { public: SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes); ~SubchannelNode() override; @@ -76,9 +76,14 @@ class SubchannelNode : public CallCountingAndTracingNode { grpc_json* RenderJson() override; + CallCountingAndTracingNode* counter_and_tracer() { + return &counter_and_tracer_; + } + private: grpc_subchannel* subchannel_; UniquePtr target_; + CallCountingAndTracingNode counter_and_tracer_; void PopulateConnectivityState(grpc_json* json); }; diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index a15cfd43c3..5894d52e6b 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -183,7 +183,7 @@ static void connection_destroy(void* arg, grpc_error* error) { static void subchannel_destroy(void* arg, grpc_error* error) { grpc_subchannel* c = static_cast(arg); if (c->channelz_subchannel != nullptr) { - c->channelz_subchannel->trace()->AddTraceEvent( + c->channelz_subchannel->counter_and_tracer()->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel destroyed")); c->channelz_subchannel->MarkSubchannelDestroyed(); @@ -397,7 +397,7 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, c->channelz_subchannel = grpc_core::MakeRefCounted( c, channel_tracer_max_nodes); - c->channelz_subchannel->trace()->AddTraceEvent( + c->channelz_subchannel->counter_and_tracer()->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel created")); } @@ -857,7 +857,6 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, args.deadline, /* deadline */ args.arena, /* arena */ args.call_combiner, /* call_combiner */ - args.call /* call */ }; grpc_error* error = grpc_call_stack_init( channel_stack_, 1, subchannel_call_destroy, *call, &call_args); @@ -866,10 +865,6 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, gpr_log(GPR_ERROR, "error: %s", error_string); return error; } - if (channelz_subchannel_ != nullptr) { - channelz_subchannel_->RecordCallStarted(); - grpc_call_set_channelz_subchannel(args.call, channelz_subchannel_); - } grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); return GRPC_ERROR_NONE; } diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h index 727f36a6f8..7581f937b6 100644 --- a/src/core/lib/channel/channel_stack.h +++ b/src/core/lib/channel/channel_stack.h @@ -71,7 +71,6 @@ typedef struct { grpc_millis deadline; gpr_arena* arena; grpc_call_combiner* call_combiner; - grpc_call* call; } grpc_call_element_args; typedef struct { diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 4fbc441c0a..ee1717ce9f 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -54,8 +54,7 @@ char* BaseNode::RenderJsonString() { } CallCountingAndTracingNode::CallCountingAndTracingNode( - EntityType type, size_t channel_tracer_max_nodes) - : BaseNode(type) { + size_t channel_tracer_max_nodes) { trace_.Init(channel_tracer_max_nodes); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); @@ -103,12 +102,11 @@ void CallCountingAndTracingNode::PopulateCallData(grpc_json* json) { ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, bool is_top_level_channel) - : CallCountingAndTracingNode(is_top_level_channel - ? EntityType::kTopLevelChannel - : EntityType::kInternalChannel, - channel_tracer_max_nodes), + : BaseNode(is_top_level_channel ? EntityType::kTopLevelChannel + : EntityType::kInternalChannel), channel_(channel), - target_(UniquePtr(grpc_channel_get_target(channel_))) {} + target_(UniquePtr(grpc_channel_get_target(channel_))), + counter_and_tracer_(channel_tracer_max_nodes) {} ChannelNode::~ChannelNode() {} @@ -137,8 +135,8 @@ grpc_json* ChannelNode::RenderJson() { 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); + counter_and_tracer_.PopulateTrace(json); + counter_and_tracer_.PopulateCallData(json); return top_level_json; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 5496163fb9..7bc4567ad2 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -86,10 +86,10 @@ class BaseNode : public RefCounted { // - track last_call_started_timestamp // - hold the channel trace. // - perform common rendering. -class CallCountingAndTracingNode : public BaseNode { +class CallCountingAndTracingNode { public: - CallCountingAndTracingNode(EntityType type, size_t channel_tracer_max_nodes); - ~CallCountingAndTracingNode() override; + CallCountingAndTracingNode(size_t channel_tracer_max_nodes); + ~CallCountingAndTracingNode(); void RecordCallStarted(); void RecordCallFailed() { @@ -118,7 +118,7 @@ class CallCountingAndTracingNode : public BaseNode { }; // Handles channelz bookkeeping for channels -class ChannelNode : public CallCountingAndTracingNode { +class ChannelNode : public BaseNode { public: static RefCountedPtr MakeChannelNode( grpc_channel* channel, size_t channel_tracer_max_nodes, @@ -137,6 +137,10 @@ class ChannelNode : public CallCountingAndTracingNode { bool ChannelIsDestroyed() { return channel_ == nullptr; } + CallCountingAndTracingNode* counter_and_tracer() { + return &counter_and_tracer_; + } + protected: // provides view of target for child. char* target_view() { return target_.get(); } @@ -144,15 +148,14 @@ class ChannelNode : public CallCountingAndTracingNode { private: grpc_channel* channel_ = nullptr; UniquePtr target_; + CallCountingAndTracingNode counter_and_tracer_; }; // Handles channelz bookkeeping for servers // TODO(ncteisen): implement in subsequent PR. -class ServerNode : public CallCountingAndTracingNode { +class ServerNode : public BaseNode { public: - ServerNode(size_t channel_tracer_max_nodes) - : CallCountingAndTracingNode(EntityType::kServer, - channel_tracer_max_nodes) {} + ServerNode(size_t channel_tracer_max_nodes) : BaseNode(EntityType::kServer) {} ~ServerNode() override {} }; @@ -162,8 +165,6 @@ class SocketNode : public BaseNode { public: SocketNode() : BaseNode(EntityType::kSocket) {} ~SocketNode() override {} - - private: }; // Creation functions diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 6545af8f72..b86ff048cf 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -170,11 +170,6 @@ struct grpc_call { /* parent_call* */ gpr_atm parent_call_atm; child_call* child; - // the call holds onto this so that once the call knows if the RPC was - // a success or failure, it can update the channelz bookkeeping for the - // subchannel that sent it. - grpc_core::channelz::CallCountingAndTracingNode* channelz_subchannel_; - /* client or server call */ bool is_client; /** has grpc_call_unref been called */ @@ -274,11 +269,6 @@ struct grpc_call { gpr_atm recv_state; }; -void grpc_call_set_channelz_subchannel( - grpc_call* call, grpc_core::channelz::CallCountingAndTracingNode* node) { - call->channelz_subchannel_ = node; -} - grpc_core::TraceFlag grpc_call_error_trace(false, "call_error"); grpc_core::TraceFlag grpc_compression_trace(false, "compression"); @@ -454,8 +444,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, call->start_time, send_deadline, call->arena, - &call->call_combiner, - call}; + &call->call_combiner}; add_init_error(&error, grpc_call_stack_init(channel_stack, 1, destroy_call, call, &call_args)); // Publish this call to parent only after the call stack has been initialized. @@ -500,7 +489,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(call->channel); if (channelz_channel != nullptr) { - channelz_channel->RecordCallStarted(); + channelz_channel->counter_and_tracer()->RecordCallStarted(); } grpc_slice_unref_internal(path); @@ -1279,17 +1268,9 @@ static void post_batch_completion(batch_control* bctl) { grpc_channel_get_channelz_node(call->channel); if (channelz_channel != nullptr) { if (*call->final_op.client.status != GRPC_STATUS_OK) { - channelz_channel->RecordCallFailed(); - } else { - channelz_channel->RecordCallSucceeded(); - } - } - // Record channelz data for the subchannel. - if (call->channelz_subchannel_ != nullptr) { - if (*call->final_op.client.status != GRPC_STATUS_OK) { - call->channelz_subchannel_->RecordCallFailed(); + channelz_channel->counter_and_tracer()->RecordCallFailed(); } else { - call->channelz_subchannel_->RecordCallSucceeded(); + channelz_channel->counter_and_tracer()->RecordCallSucceeded(); } } GRPC_ERROR_UNREF(error); diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h index 200c840c61..b3b06059d4 100644 --- a/src/core/lib/surface/call.h +++ b/src/core/lib/surface/call.h @@ -110,19 +110,6 @@ size_t grpc_call_get_initial_size_estimate(); grpc_compression_algorithm grpc_call_compression_for_level( grpc_call* call, grpc_compression_level level); -namespace grpc_core { -namespace channelz { -class CallCountingAndTracingNode; -} // namespace channelz -} // namespace grpc_core - -// We need this so that a subchannel selected for a call can add itself to -// the call's data structure. This allows the call to trigger the correct -// channelz bookkeeping on the subchannel once the call knows if the RPC was -// successful or not. -void grpc_call_set_channelz_subchannel( - grpc_call* call, grpc_core::channelz::CallCountingAndTracingNode* node); - extern grpc_core::TraceFlag grpc_call_error_trace; extern grpc_core::TraceFlag grpc_compression_trace; diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 01caadaaba..16d3322a9d 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -170,7 +170,7 @@ grpc_channel* grpc_channel_create_with_builder( bool is_top_level_channel = channel->is_client && !internal_channel; channel->channelz_channel = channel_node_create_func( channel, channel_tracer_max_nodes, is_top_level_channel); - channel->channelz_channel->trace()->AddTraceEvent( + channel->channelz_channel->counter_and_tracer()->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel created")); } @@ -417,7 +417,7 @@ void grpc_channel_internal_unref(grpc_channel* c REF_ARG) { static void destroy_channel(void* arg, grpc_error* error) { grpc_channel* channel = static_cast(arg); if (channel->channelz_channel != nullptr) { - channel->channelz_channel->trace()->AddTraceEvent( + channel->channelz_channel->counter_and_tracer()->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel destroyed")); channel->channelz_channel->MarkChannelDestroyed(); diff --git a/test/core/channel/channel_stack_test.cc b/test/core/channel/channel_stack_test.cc index 4dc2ee3f55..6f0bfa06d2 100644 --- a/test/core/channel/channel_stack_test.cc +++ b/test/core/channel/channel_stack_test.cc @@ -125,7 +125,6 @@ static void test_create_channel_stack(void) { GRPC_MILLIS_INF_FUTURE, /* deadline */ nullptr, /* arena */ nullptr, /* call_combiner */ - nullptr /* call */ }; grpc_error* error = grpc_call_stack_init(channel_stack, 1, free_call, call_stack, &args); diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index 703a9e457f..3d6aff03eb 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -160,14 +160,14 @@ TEST_P(ChannelTracerTest, ComplexTest) { ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - ValidateChannelTrace(sc1->trace(), 3, GetParam()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - ValidateChannelTrace(sc1->trace(), 6, GetParam()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + ValidateChannelTrace(sc1->counter_and_tracer()->trace(), 3, GetParam()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + ValidateChannelTrace(sc1->counter_and_tracer()->trace(), 6, GetParam()); AddSimpleTrace(&tracer); AddSimpleTrace(&tracer); ValidateChannelTrace(&tracer, 5, GetParam()); @@ -191,55 +191,53 @@ TEST_P(ChannelTracerTest, ComplexTest) { sc2.reset(nullptr); } -// // Test a case in which the parent channel has subchannels and the -// subchannels -// // have connections. Ensures that everything lives as long as it should then -// // gets deleted. -// TEST_P(ChannelTracerTest, TestNesting) { -// grpc_core::ExecCtx exec_ctx; -// ChannelTrace tracer(GetParam()); -// AddSimpleTrace(&tracer); -// AddSimpleTrace(&tracer); -// ValidateChannelTrace(&tracer, 2, GetParam()); -// ChannelFixture channel1(GetParam()); -// RefCountedPtr sc1 = -// MakeRefCounted(channel1.channel(), GetParam(), true); -// tracer.AddTraceEventReferencingChannel( -// ChannelTrace::Severity::Info, -// grpc_slice_from_static_string("subchannel one created"), sc1); -// ValidateChannelTrace(&tracer, 3, GetParam()); -// AddSimpleTrace(sc1->trace()); -// ChannelFixture channel2(GetParam()); -// RefCountedPtr conn1 = -// MakeRefCounted(channel2.channel(), GetParam(), true); -// // nesting one level deeper. -// sc1->trace()->AddTraceEventReferencingChannel( -// ChannelTrace::Severity::Info, -// grpc_slice_from_static_string("connection one created"), conn1); -// ValidateChannelTrace(&tracer, 3, GetParam()); -// AddSimpleTrace(conn1->trace()); -// AddSimpleTrace(&tracer); -// AddSimpleTrace(&tracer); -// ValidateChannelTrace(&tracer, 5, GetParam()); -// ValidateChannelTrace(conn1->trace(), 1, GetParam()); -// ChannelFixture channel3(GetParam()); -// RefCountedPtr sc2 = -// MakeRefCounted(channel3.channel(), GetParam(), true); -// tracer.AddTraceEventReferencingChannel( -// ChannelTrace::Severity::Info, -// grpc_slice_from_static_string("subchannel two created"), sc2); -// // this trace should not get added to the parents children since it is -// already -// // present in the tracer. -// tracer.AddTraceEventReferencingChannel( -// ChannelTrace::Severity::Warning, -// grpc_slice_from_static_string("subchannel one inactive"), sc1); -// AddSimpleTrace(&tracer); -// ValidateChannelTrace(&tracer, 8, GetParam()); -// sc1.reset(nullptr); -// sc2.reset(nullptr); -// conn1.reset(nullptr); -// } +// Test a case in which the parent channel has subchannels and the subchannels +// have connections. Ensures that everything lives as long as it should then +// gets deleted. +TEST_P(ChannelTracerTest, TestNesting) { + grpc_core::ExecCtx exec_ctx; + ChannelTrace tracer(GetParam()); + AddSimpleTrace(&tracer); + AddSimpleTrace(&tracer); + ValidateChannelTrace(&tracer, 2, GetParam()); + ChannelFixture channel1(GetParam()); + RefCountedPtr sc1 = + MakeRefCounted(channel1.channel(), GetParam(), true); + tracer.AddTraceEventReferencingChannel( + ChannelTrace::Severity::Info, + grpc_slice_from_static_string("subchannel one created"), sc1); + ValidateChannelTrace(&tracer, 3, GetParam()); + AddSimpleTrace(sc1->counter_and_tracer()->trace()); + ChannelFixture channel2(GetParam()); + RefCountedPtr conn1 = + MakeRefCounted(channel2.channel(), GetParam(), true); + // nesting one level deeper. + sc1->counter_and_tracer()->trace()->AddTraceEventReferencingChannel( + ChannelTrace::Severity::Info, + grpc_slice_from_static_string("connection one created"), conn1); + ValidateChannelTrace(&tracer, 3, GetParam()); + AddSimpleTrace(conn1->counter_and_tracer()->trace()); + AddSimpleTrace(&tracer); + AddSimpleTrace(&tracer); + ValidateChannelTrace(&tracer, 5, GetParam()); + ValidateChannelTrace(conn1->counter_and_tracer()->trace(), 1, GetParam()); + ChannelFixture channel3(GetParam()); + RefCountedPtr sc2 = + MakeRefCounted(channel3.channel(), GetParam(), true); + tracer.AddTraceEventReferencingChannel( + ChannelTrace::Severity::Info, + grpc_slice_from_static_string("subchannel two created"), sc2); + // this trace should not get added to the parents children since it is already + // present in the tracer. + tracer.AddTraceEventReferencingChannel( + ChannelTrace::Severity::Warning, + grpc_slice_from_static_string("subchannel one inactive"), sc1); + AddSimpleTrace(&tracer); + ValidateChannelTrace(&tracer, 8, GetParam()); + sc1.reset(nullptr); + sc2.reset(nullptr); + conn1.reset(nullptr); +} INSTANTIATE_TEST_CASE_P(ChannelTracerTestSweep, ChannelTracerTest, ::testing::Values(0, 1, 2, 6, 10, 15)); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index 9f3756c182..5e9a3f89a2 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -201,16 +201,16 @@ TEST_P(ChannelzChannelTest, BasicChannelAPIFunctionality) { ChannelFixture channel(GetParam()); ChannelNode* channelz_channel = grpc_channel_get_channelz_node(channel.channel()); - channelz_channel->RecordCallStarted(); - channelz_channel->RecordCallFailed(); - channelz_channel->RecordCallSucceeded(); + channelz_channel->counter_and_tracer()->RecordCallStarted(); + channelz_channel->counter_and_tracer()->RecordCallFailed(); + channelz_channel->counter_and_tracer()->RecordCallSucceeded(); ValidateChannel(channelz_channel, {1, 1, 1}); - channelz_channel->RecordCallStarted(); - channelz_channel->RecordCallFailed(); - channelz_channel->RecordCallSucceeded(); - channelz_channel->RecordCallStarted(); - channelz_channel->RecordCallFailed(); - channelz_channel->RecordCallSucceeded(); + channelz_channel->counter_and_tracer()->RecordCallStarted(); + channelz_channel->counter_and_tracer()->RecordCallFailed(); + channelz_channel->counter_and_tracer()->RecordCallSucceeded(); + channelz_channel->counter_and_tracer()->RecordCallStarted(); + channelz_channel->counter_and_tracer()->RecordCallFailed(); + channelz_channel->counter_and_tracer()->RecordCallSucceeded(); ValidateChannel(channelz_channel, {3, 3, 3}); } @@ -220,23 +220,27 @@ TEST_P(ChannelzChannelTest, LastCallStartedMillis) { ChannelNode* channelz_channel = grpc_channel_get_channelz_node(channel.channel()); // start a call to set the last call started timestamp - channelz_channel->RecordCallStarted(); - grpc_millis millis1 = GetLastCallStartedMillis(channelz_channel); + channelz_channel->counter_and_tracer()->RecordCallStarted(); + grpc_millis millis1 = + GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); // time gone by should not affect the timestamp ChannelzSleep(100); - grpc_millis millis2 = GetLastCallStartedMillis(channelz_channel); + grpc_millis millis2 = + GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); EXPECT_EQ(millis1, millis2); // calls succeeded or failed should not affect the timestamp ChannelzSleep(100); - channelz_channel->RecordCallFailed(); - channelz_channel->RecordCallSucceeded(); - grpc_millis millis3 = GetLastCallStartedMillis(channelz_channel); + channelz_channel->counter_and_tracer()->RecordCallFailed(); + channelz_channel->counter_and_tracer()->RecordCallSucceeded(); + grpc_millis millis3 = + GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); EXPECT_EQ(millis1, millis3); // another call started should affect the timestamp // sleep for extra long to avoid flakes (since we cache Now()) ChannelzSleep(5000); - channelz_channel->RecordCallStarted(); - grpc_millis millis4 = GetLastCallStartedMillis(channelz_channel); + channelz_channel->counter_and_tracer()->RecordCallStarted(); + grpc_millis millis4 = + GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); EXPECT_NE(millis1, millis4); } -- cgit v1.2.3 From 37f7b5399dcf5b29e41ac1c0ff2a1c81c9933a93 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 24 Jul 2018 10:18:54 -0700 Subject: reviewer feedback --- src/core/lib/channel/channelz_registry.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'src/core') diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index 7f70908989..d2c403cc1b 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -123,7 +123,6 @@ char* grpc_channelz_get_channel(intptr_t channel_id) { 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() != -- cgit v1.2.3 From 864e68e96d20c91ead272c17ff36c74422c7de3f Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 27 Jul 2018 02:27:58 -0700 Subject: Fix channel trace polymorphism --- grpc.def | 1 + src/core/lib/channel/channel_trace.cc | 58 +++++++------------------- src/core/lib/channel/channel_trace.h | 20 +++------ src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 + src/ruby/ext/grpc/rb_grpc_imports.generated.h | 3 ++ test/core/channel/channel_trace_test.cc | 15 +++---- test/core/surface/public_headers_must_be_c89.c | 1 + 7 files changed, 36 insertions(+), 64 deletions(-) (limited to 'src/core') diff --git a/grpc.def b/grpc.def index 5b98792662..5d699e890a 100644 --- a/grpc.def +++ b/grpc.def @@ -71,6 +71,7 @@ EXPORTS grpc_resource_quota_arg_vtable grpc_channelz_get_top_channels grpc_channelz_get_channel + grpc_channelz_get_subchannel grpc_insecure_channel_create_from_fd grpc_server_add_insecure_channel_from_fd grpc_use_signal diff --git a/src/core/lib/channel/channel_trace.cc b/src/core/lib/channel/channel_trace.cc index 7d8bb391f8..cfb2faba51 100644 --- a/src/core/lib/channel/channel_trace.cc +++ b/src/core/lib/channel/channel_trace.cc @@ -41,25 +41,14 @@ namespace grpc_core { namespace channelz { -ChannelTrace::TraceEvent::TraceEvent( - Severity severity, grpc_slice data, - RefCountedPtr referenced_channel) +ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data, + RefCountedPtr referenced_entity) : severity_(severity), data_(data), timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), GPR_CLOCK_REALTIME)), next_(nullptr), - referenced_channel_(std::move(referenced_channel)) {} - -// ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data, -// RefCountedPtr -// referenced_subchannel) -// : severity_(severity), -// data_(data), -// timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), -// GPR_CLOCK_REALTIME)), -// next_(nullptr), -// referenced_subchannel_(std::move(referenced_subchannel)) {} + referenced_entity_(std::move(referenced_entity)) {} ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data) : severity_(severity), @@ -119,24 +108,15 @@ void ChannelTrace::AddTraceEvent(Severity severity, grpc_slice data) { AddTraceEventHelper(New(severity, data)); } -void ChannelTrace::AddTraceEventReferencingChannel( +void ChannelTrace::AddTraceEventWithReference( Severity severity, grpc_slice data, - RefCountedPtr referenced_channel) { + RefCountedPtr referenced_entity) { if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 // create and fill up the new event AddTraceEventHelper( - New(severity, data, std::move(referenced_channel))); + New(severity, data, std::move(referenced_entity))); } -// void ChannelTrace::AddTraceEventReferencingSubchannel( -// Severity severity, grpc_slice data, -// RefCountedPtr referenced_subchannel) { -// if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0 -// // create and fill up the new event -// AddTraceEventHelper( -// New(severity, data, std::move(referenced_subchannel))); -// } - namespace { const char* severity_string(ChannelTrace::Severity severity) { @@ -165,26 +145,20 @@ void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const { json_iterator = grpc_json_create_child(json_iterator, json, "timestamp", gpr_format_timespec(timestamp_), GRPC_JSON_STRING, true); - if (referenced_channel_ != nullptr) { + if (referenced_entity_ != nullptr) { + const bool is_channel = + (referenced_entity_->type() == BaseNode::EntityType::kTopLevelChannel || + referenced_entity_->type() == BaseNode::EntityType::kInternalChannel); char* uuid_str; - gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_channel_->uuid()); + gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_entity_->uuid()); grpc_json* child_ref = grpc_json_create_child( - json_iterator, json, "channelRef", nullptr, GRPC_JSON_OBJECT, false); - json_iterator = grpc_json_create_child(nullptr, child_ref, "channelId", - uuid_str, GRPC_JSON_STRING, true); + json_iterator, json, is_channel ? "channelRef" : "subchannelRef", + nullptr, GRPC_JSON_OBJECT, false); + json_iterator = grpc_json_create_child( + nullptr, child_ref, is_channel ? "channelId" : "subchannelId", uuid_str, + GRPC_JSON_STRING, true); json_iterator = child_ref; } - // else { - // char* uuid_str; - // gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_subchannel_->uuid()); - // grpc_json* child_ref = grpc_json_create_child( - // json_iterator, json, "subchannelRef", - // nullptr, GRPC_JSON_OBJECT, false); - // json_iterator = grpc_json_create_child( - // nullptr, child_ref, "subchannelId", - // uuid_str, GRPC_JSON_STRING, true); - // json_iterator = child_ref; - // } } grpc_json* ChannelTrace::RenderJson() const { diff --git a/src/core/lib/channel/channel_trace.h b/src/core/lib/channel/channel_trace.h index 543eabf13a..230faa483e 100644 --- a/src/core/lib/channel/channel_trace.h +++ b/src/core/lib/channel/channel_trace.h @@ -30,8 +30,7 @@ namespace grpc_core { namespace channelz { -class ChannelNode; -class SubchannelNode; +class BaseNode; // Object used to hold live data for a channel. This data is exposed via the // channelz service: @@ -63,12 +62,8 @@ class ChannelTrace { // TODO(ncteisen): as this call is used more and more throughout the gRPC // stack, determine if it makes more sense to accept a char* instead of a // slice. - void AddTraceEventReferencingChannel( - Severity severity, grpc_slice data, - RefCountedPtr referenced_channel); - // void AddTraceEventReferencingSubchannel( - // Severity severity, grpc_slice data, - // RefCountedPtr referenced_subchannel); + void AddTraceEventWithReference(Severity severity, grpc_slice data, + RefCountedPtr referenced_channel); // Creates and returns the raw grpc_json object, so a parent channelz // object may incorporate the json before rendering. @@ -81,11 +76,7 @@ class ChannelTrace { public: // Constructor for a TraceEvent that references a channel. TraceEvent(Severity severity, grpc_slice data, - RefCountedPtr referenced_channel); - - // Constructor for a TraceEvent that references a subchannel. - TraceEvent(Severity severity, grpc_slice data, - RefCountedPtr referenced_subchannel); + RefCountedPtr referenced_entity_); // Constructor for a TraceEvent that does not reverence a different // channel. @@ -107,8 +98,7 @@ class ChannelTrace { gpr_timespec timestamp_; TraceEvent* next_; // the tracer object for the (sub)channel that this trace event refers to. - RefCountedPtr referenced_channel_; - // RefCountedPtr referenced_subchannel_; + RefCountedPtr referenced_entity_; }; // TraceEvent // Internal helper to add and link in a trace event diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 2443532bb8..5018bbbfa1 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -94,6 +94,7 @@ grpc_resource_quota_resize_type grpc_resource_quota_resize_import; grpc_resource_quota_arg_vtable_type grpc_resource_quota_arg_vtable_import; grpc_channelz_get_top_channels_type grpc_channelz_get_top_channels_import; grpc_channelz_get_channel_type grpc_channelz_get_channel_import; +grpc_channelz_get_subchannel_type grpc_channelz_get_subchannel_import; grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import; grpc_server_add_insecure_channel_from_fd_type grpc_server_add_insecure_channel_from_fd_import; grpc_use_signal_type grpc_use_signal_import; @@ -344,6 +345,7 @@ void grpc_rb_load_imports(HMODULE library) { grpc_resource_quota_arg_vtable_import = (grpc_resource_quota_arg_vtable_type) GetProcAddress(library, "grpc_resource_quota_arg_vtable"); grpc_channelz_get_top_channels_import = (grpc_channelz_get_top_channels_type) GetProcAddress(library, "grpc_channelz_get_top_channels"); grpc_channelz_get_channel_import = (grpc_channelz_get_channel_type) GetProcAddress(library, "grpc_channelz_get_channel"); + grpc_channelz_get_subchannel_import = (grpc_channelz_get_subchannel_type) GetProcAddress(library, "grpc_channelz_get_subchannel"); grpc_insecure_channel_create_from_fd_import = (grpc_insecure_channel_create_from_fd_type) GetProcAddress(library, "grpc_insecure_channel_create_from_fd"); grpc_server_add_insecure_channel_from_fd_import = (grpc_server_add_insecure_channel_from_fd_type) GetProcAddress(library, "grpc_server_add_insecure_channel_from_fd"); grpc_use_signal_import = (grpc_use_signal_type) GetProcAddress(library, "grpc_use_signal"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index b08a1f94f7..edb7e98605 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -257,6 +257,9 @@ extern grpc_channelz_get_top_channels_type grpc_channelz_get_top_channels_import typedef char*(*grpc_channelz_get_channel_type)(intptr_t channel_id); extern grpc_channelz_get_channel_type grpc_channelz_get_channel_import; #define grpc_channelz_get_channel grpc_channelz_get_channel_import +typedef char*(*grpc_channelz_get_subchannel_type)(intptr_t subchannel_id); +extern grpc_channelz_get_subchannel_type grpc_channelz_get_subchannel_import; +#define grpc_channelz_get_subchannel grpc_channelz_get_subchannel_import typedef grpc_channel*(*grpc_insecure_channel_create_from_fd_type)(const char* target, int fd, const grpc_channel_args* args); extern grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import; #define grpc_insecure_channel_create_from_fd grpc_insecure_channel_create_from_fd_import diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index efa625bccf..9bc9dde8d6 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -89,6 +89,7 @@ void ValidateChannelTrace(ChannelTrace* tracer, grpc_json* json = tracer->RenderJson(); EXPECT_NE(json, nullptr); char* json_str = grpc_json_dump_to_string(json, 0); + gpr_log(GPR_ERROR, "%s", json_str); grpc_json_destroy(json); grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str); grpc_json* parsed_json = grpc_json_parse_string(json_str); @@ -156,7 +157,7 @@ TEST_P(ChannelTracerTest, ComplexTest) { ChannelFixture channel1(GetParam()); RefCountedPtr sc1 = MakeRefCounted(channel1.channel(), GetParam(), true); - tracer.AddTraceEventReferencingChannel( + tracer.AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); @@ -174,10 +175,10 @@ TEST_P(ChannelTracerTest, ComplexTest) { ChannelFixture channel2(GetParam()); RefCountedPtr sc2 = MakeRefCounted(channel2.channel(), GetParam(), true); - tracer.AddTraceEventReferencingChannel( + tracer.AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("LB channel two created"), sc2); - tracer.AddTraceEventReferencingChannel( + tracer.AddTraceEventWithReference( ChannelTrace::Severity::Warning, grpc_slice_from_static_string("subchannel one inactive"), sc1); ValidateChannelTrace(&tracer, 7, GetParam()); @@ -203,7 +204,7 @@ TEST_P(ChannelTracerTest, TestNesting) { ChannelFixture channel1(GetParam()); RefCountedPtr sc1 = MakeRefCounted(channel1.channel(), GetParam(), true); - tracer.AddTraceEventReferencingChannel( + tracer.AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); @@ -212,7 +213,7 @@ TEST_P(ChannelTracerTest, TestNesting) { RefCountedPtr conn1 = MakeRefCounted(channel2.channel(), GetParam(), true); // nesting one level deeper. - sc1->counter_and_tracer()->trace()->AddTraceEventReferencingChannel( + sc1->counter_and_tracer()->trace()->AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("connection one created"), conn1); ValidateChannelTrace(&tracer, 3, GetParam()); @@ -224,12 +225,12 @@ TEST_P(ChannelTracerTest, TestNesting) { ChannelFixture channel3(GetParam()); RefCountedPtr sc2 = MakeRefCounted(channel3.channel(), GetParam(), true); - tracer.AddTraceEventReferencingChannel( + tracer.AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel two created"), sc2); // this trace should not get added to the parents children since it is already // present in the tracer. - tracer.AddTraceEventReferencingChannel( + tracer.AddTraceEventWithReference( ChannelTrace::Severity::Warning, grpc_slice_from_static_string("subchannel one inactive"), sc1); AddSimpleTrace(&tracer); diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 9f4ad2b4d7..d492685915 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -133,6 +133,7 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) grpc_resource_quota_arg_vtable); printf("%lx", (unsigned long) grpc_channelz_get_top_channels); printf("%lx", (unsigned long) grpc_channelz_get_channel); + printf("%lx", (unsigned long) grpc_channelz_get_subchannel); printf("%lx", (unsigned long) grpc_auth_property_iterator_next); printf("%lx", (unsigned long) grpc_auth_context_property_iterator); printf("%lx", (unsigned long) grpc_auth_context_peer_identity); -- cgit v1.2.3 From 58db94e5d9f3e55f14760f936a42e5e6ddb6bd5b Mon Sep 17 00:00:00 2001 From: ncteisen Date: Sun, 29 Jul 2018 20:30:05 -0700 Subject: reviewer comments --- .../client_channel/client_channel_channelz.cc | 30 ++++++++---- .../client_channel/client_channel_channelz.h | 11 +++-- src/core/ext/filters/client_channel/subchannel.cc | 4 +- src/core/lib/channel/channelz.cc | 39 +++++++--------- src/core/lib/channel/channelz.h | 41 ++++++++--------- src/core/lib/surface/call.cc | 6 +-- src/core/lib/surface/channel.cc | 4 +- test/core/channel/channel_trace_test.cc | 25 +++++----- test/core/channel/channelz_test.cc | 53 ++++++++++------------ 9 files changed, 106 insertions(+), 107 deletions(-) (limited to 'src/core') 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 f797ef1b09..7120ec57f1 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -123,9 +123,14 @@ grpc_json* ClientChannelNode::RenderJson() { 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. - counter_and_tracer()->PopulateTrace(json); - counter_and_tracer()->PopulateCallData(json); + // fill in the channel trace if applicable + grpc_json* trace_json = trace()->RenderJson(); + if (trace_json != nullptr) { + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); + } + // ask CallCountingHelper to populate trace and call count data. + call_counter()->PopulateCallData(json); // reset to the top level json = top_level_json; PopulateChildRefs(json); @@ -150,11 +155,12 @@ SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes) : BaseNode(EntityType::kSubchannel), subchannel_(subchannel), - target_( - UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_)))), - counter_and_tracer_(channel_tracer_max_nodes) {} + target_(UniquePtr( + gpr_strdup(grpc_subchannel_get_target(subchannel_)))) { + trace_.Init(channel_tracer_max_nodes); +} -SubchannelNode::~SubchannelNode() {} +SubchannelNode::~SubchannelNode() { trace_.Destroy(); } void SubchannelNode::PopulateConnectivityState(grpc_json* json) { grpc_connectivity_state state; @@ -192,8 +198,14 @@ grpc_json* SubchannelNode::RenderJson() { GPR_ASSERT(target_.get() != nullptr); grpc_json_create_child(nullptr, json, "target", target_.get(), GRPC_JSON_STRING, false); - counter_and_tracer_.PopulateTrace(json); - counter_and_tracer_.PopulateCallData(json); + // fill in the channel trace if applicable + grpc_json* trace_json = trace_->RenderJson(); + if (trace_json != nullptr) { + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); + } + // ask CallCountingHelper to populate trace and call count data. + call_counter_.PopulateCallData(json); return top_level_json; } 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 f5344c049e..735ffacfd2 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -76,14 +76,17 @@ class SubchannelNode : public BaseNode { grpc_json* RenderJson() override; - CallCountingAndTracingNode* counter_and_tracer() { - return &counter_and_tracer_; - } + // proxy methods to composed classes. + ChannelTrace* trace() { return trace_.get(); } + void RecordCallStarted() { call_counter_.RecordCallStarted(); } + void RecordCallFailed() { call_counter_.RecordCallFailed(); } + void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } private: grpc_subchannel* subchannel_; UniquePtr target_; - CallCountingAndTracingNode counter_and_tracer_; + CallCountingHelper call_counter_; + ManualConstructor trace_; void PopulateConnectivityState(grpc_json* json); }; diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index d7b64a900f..f0f8d94ef4 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -183,7 +183,7 @@ static void connection_destroy(void* arg, grpc_error* error) { static void subchannel_destroy(void* arg, grpc_error* error) { grpc_subchannel* c = static_cast(arg); if (c->channelz_subchannel != nullptr) { - c->channelz_subchannel->counter_and_tracer()->trace()->AddTraceEvent( + c->channelz_subchannel->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel destroyed")); c->channelz_subchannel->MarkSubchannelDestroyed(); @@ -397,7 +397,7 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, c->channelz_subchannel = grpc_core::MakeRefCounted( c, channel_tracer_max_nodes); - c->channelz_subchannel->counter_and_tracer()->trace()->AddTraceEvent( + 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 ee1717ce9f..a75a05023a 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -53,33 +53,20 @@ char* BaseNode::RenderJsonString() { return json_str; } -CallCountingAndTracingNode::CallCountingAndTracingNode( - size_t channel_tracer_max_nodes) { - trace_.Init(channel_tracer_max_nodes); +CallCountingHelper::CallCountingHelper() { gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -CallCountingAndTracingNode::~CallCountingAndTracingNode() { trace_.Destroy(); } +CallCountingHelper::~CallCountingHelper() {} -void CallCountingAndTracingNode::RecordCallStarted() { +void CallCountingHelper::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 CallCountingAndTracingNode::PopulateTrace(grpc_json* json) { - // fill in the channel trace if applicable - grpc_json* trace_json = trace_->RenderJson(); - if (trace_json != nullptr) { - // we manually link up and fill the child since it was created for us in - // ChannelTrace::RenderJson - trace_json->key = "trace"; // this object is named trace in channelz.proto - grpc_json_link_child(json, trace_json, nullptr); - } -} - -void CallCountingAndTracingNode::PopulateCallData(grpc_json* json) { +void CallCountingHelper::PopulateCallData(grpc_json* json) { grpc_json* json_iterator = nullptr; if (calls_started_ != 0) { json_iterator = grpc_json_add_number_string_child( @@ -105,10 +92,11 @@ ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, : BaseNode(is_top_level_channel ? EntityType::kTopLevelChannel : EntityType::kInternalChannel), channel_(channel), - target_(UniquePtr(grpc_channel_get_target(channel_))), - counter_and_tracer_(channel_tracer_max_nodes) {} + target_(UniquePtr(grpc_channel_get_target(channel_))) { + trace_.Init(channel_tracer_max_nodes); +} -ChannelNode::~ChannelNode() {} +ChannelNode::~ChannelNode() { trace_.Destroy(); } grpc_json* ChannelNode::RenderJson() { // We need to track these three json objects to build our object @@ -134,9 +122,14 @@ grpc_json* ChannelNode::RenderJson() { 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. - counter_and_tracer_.PopulateTrace(json); - counter_and_tracer_.PopulateCallData(json); + // fill in the channel trace if applicable + grpc_json* trace_json = trace_->RenderJson(); + if (trace_json != nullptr) { + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); + } + // ask CallCountingHelper to populate trace and call count data. + call_counter_.PopulateCallData(json); return top_level_json; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 7bc4567ad2..6e20f31b68 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -43,7 +43,7 @@ namespace grpc_core { namespace channelz { namespace testing { -class CallCountingAndTracingNodePeer; +class CallCountingHelperPeer; } // base class for all channelz entities @@ -60,7 +60,7 @@ class BaseNode : public RefCounted { kSocket, }; - BaseNode(EntityType type); + explicit BaseNode(EntityType type); virtual ~BaseNode(); // All children must implement this function. @@ -74,22 +74,20 @@ class BaseNode : public RefCounted { intptr_t uuid() const { return uuid_; } private: - friend class ChannelTrace; - EntityType type_; + const EntityType type_; const intptr_t uuid_; }; -// This class is the parent for the channelz entities that deal with Channels +// This class is a helper class for channelz entities that deal with Channels // Subchannels, and Servers, since those have similar proto definitions. // This class has the ability to: // - track calls_{started,succeeded,failed} // - track last_call_started_timestamp -// - hold the channel trace. -// - perform common rendering. -class CallCountingAndTracingNode { +// - perform rendering of the above items +class CallCountingHelper { public: - CallCountingAndTracingNode(size_t channel_tracer_max_nodes); - ~CallCountingAndTracingNode(); + CallCountingHelper(); + ~CallCountingHelper(); void RecordCallStarted(); void RecordCallFailed() { @@ -98,23 +96,18 @@ class CallCountingAndTracingNode { void RecordCallSucceeded() { gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1))); } - ChannelTrace* trace() { return trace_.get(); } - - // 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); private: // testing peer friend. - friend class testing::CallCountingAndTracingNodePeer; + friend class testing::CallCountingHelperPeer; gpr_atm calls_started_ = 0; gpr_atm calls_succeeded_ = 0; gpr_atm calls_failed_ = 0; gpr_atm last_call_started_millis_ = 0; - ManualConstructor trace_; }; // Handles channelz bookkeeping for channels @@ -137,25 +130,31 @@ class ChannelNode : public BaseNode { bool ChannelIsDestroyed() { return channel_ == nullptr; } - CallCountingAndTracingNode* counter_and_tracer() { - return &counter_and_tracer_; - } + // proxy methods to composed classes. + ChannelTrace* trace() { return trace_.get(); } + void RecordCallStarted() { call_counter_.RecordCallStarted(); } + void RecordCallFailed() { call_counter_.RecordCallFailed(); } + void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } protected: // provides view of target for child. char* target_view() { return target_.get(); } + // provides access to call_counter_ for child. + CallCountingHelper* call_counter() { return &call_counter_; } private: grpc_channel* channel_ = nullptr; UniquePtr target_; - CallCountingAndTracingNode counter_and_tracer_; + CallCountingHelper call_counter_; + ManualConstructor trace_; }; // Handles channelz bookkeeping for servers // TODO(ncteisen): implement in subsequent PR. class ServerNode : public BaseNode { public: - ServerNode(size_t channel_tracer_max_nodes) : BaseNode(EntityType::kServer) {} + explicit ServerNode(size_t channel_tracer_max_nodes) + : BaseNode(EntityType::kServer) {} ~ServerNode() override {} }; diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 03b7cedcdb..a6d626e495 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -489,7 +489,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(call->channel); if (channelz_channel != nullptr) { - channelz_channel->counter_and_tracer()->RecordCallStarted(); + channelz_channel->RecordCallStarted(); } grpc_slice_unref_internal(path); @@ -1269,9 +1269,9 @@ static void post_batch_completion(batch_control* bctl) { grpc_channel_get_channelz_node(call->channel); if (channelz_channel != nullptr) { if (*call->final_op.client.status != GRPC_STATUS_OK) { - channelz_channel->counter_and_tracer()->RecordCallFailed(); + channelz_channel->RecordCallFailed(); } else { - channelz_channel->counter_and_tracer()->RecordCallSucceeded(); + channelz_channel->RecordCallSucceeded(); } } GRPC_ERROR_UNREF(error); diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 16d3322a9d..01caadaaba 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -170,7 +170,7 @@ grpc_channel* grpc_channel_create_with_builder( bool is_top_level_channel = channel->is_client && !internal_channel; channel->channelz_channel = channel_node_create_func( channel, channel_tracer_max_nodes, is_top_level_channel); - channel->channelz_channel->counter_and_tracer()->trace()->AddTraceEvent( + channel->channelz_channel->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel created")); } @@ -417,7 +417,7 @@ void grpc_channel_internal_unref(grpc_channel* c REF_ARG) { static void destroy_channel(void* arg, grpc_error* error) { grpc_channel* channel = static_cast(arg); if (channel->channelz_channel != nullptr) { - channel->channelz_channel->counter_and_tracer()->trace()->AddTraceEvent( + channel->channelz_channel->trace()->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel destroyed")); channel->channelz_channel->MarkChannelDestroyed(); diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index 9bc9dde8d6..3f5aa85c8c 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -89,7 +89,6 @@ void ValidateChannelTrace(ChannelTrace* tracer, grpc_json* json = tracer->RenderJson(); EXPECT_NE(json, nullptr); char* json_str = grpc_json_dump_to_string(json, 0); - gpr_log(GPR_ERROR, "%s", json_str); grpc_json_destroy(json); grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str); grpc_json* parsed_json = grpc_json_parse_string(json_str); @@ -161,14 +160,14 @@ TEST_P(ChannelTracerTest, ComplexTest) { ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); - ValidateChannelTrace(sc1->counter_and_tracer()->trace(), 3, GetParam()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); - ValidateChannelTrace(sc1->counter_and_tracer()->trace(), 6, GetParam()); + AddSimpleTrace(sc1->trace()); + AddSimpleTrace(sc1->trace()); + AddSimpleTrace(sc1->trace()); + ValidateChannelTrace(sc1->trace(), 3, GetParam()); + AddSimpleTrace(sc1->trace()); + AddSimpleTrace(sc1->trace()); + AddSimpleTrace(sc1->trace()); + ValidateChannelTrace(sc1->trace(), 6, GetParam()); AddSimpleTrace(&tracer); AddSimpleTrace(&tracer); ValidateChannelTrace(&tracer, 5, GetParam()); @@ -208,20 +207,20 @@ TEST_P(ChannelTracerTest, TestNesting) { ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(sc1->counter_and_tracer()->trace()); + AddSimpleTrace(sc1->trace()); ChannelFixture channel2(GetParam()); RefCountedPtr conn1 = MakeRefCounted(channel2.channel(), GetParam(), true); // nesting one level deeper. - sc1->counter_and_tracer()->trace()->AddTraceEventWithReference( + sc1->trace()->AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("connection one created"), conn1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(conn1->counter_and_tracer()->trace()); + AddSimpleTrace(conn1->trace()); AddSimpleTrace(&tracer); AddSimpleTrace(&tracer); ValidateChannelTrace(&tracer, 5, GetParam()); - ValidateChannelTrace(conn1->counter_and_tracer()->trace(), 1, GetParam()); + ValidateChannelTrace(conn1->trace(), 1, GetParam()); ChannelFixture channel3(GetParam()); RefCountedPtr sc2 = MakeRefCounted(channel3.channel(), GetParam(), true); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index 5e9a3f89a2..8fa46a18da 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -44,17 +44,16 @@ namespace channelz { namespace testing { // testing peer to access channel internals -class CallCountingAndTracingNodePeer { +class CallCountingHelperPeer { public: - CallCountingAndTracingNodePeer(CallCountingAndTracingNode* node) - : node_(node) {} + CallCountingHelperPeer(CallCountingHelper* node) : node_(node) {} grpc_millis last_call_started_millis() { return (grpc_millis)gpr_atm_no_barrier_load( &node_->last_call_started_millis_); } private: - CallCountingAndTracingNode* node_; + CallCountingHelper* node_; }; namespace { @@ -164,8 +163,8 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) { gpr_free(core_api_json_str); } -grpc_millis GetLastCallStartedMillis(CallCountingAndTracingNode* channel) { - CallCountingAndTracingNodePeer peer(channel); +grpc_millis GetLastCallStartedMillis(CallCountingHelper* channel) { + CallCountingHelperPeer peer(channel); return peer.last_call_started_millis(); } @@ -201,46 +200,40 @@ TEST_P(ChannelzChannelTest, BasicChannelAPIFunctionality) { ChannelFixture channel(GetParam()); ChannelNode* channelz_channel = grpc_channel_get_channelz_node(channel.channel()); - channelz_channel->counter_and_tracer()->RecordCallStarted(); - channelz_channel->counter_and_tracer()->RecordCallFailed(); - channelz_channel->counter_and_tracer()->RecordCallSucceeded(); + channelz_channel->RecordCallStarted(); + channelz_channel->RecordCallFailed(); + channelz_channel->RecordCallSucceeded(); ValidateChannel(channelz_channel, {1, 1, 1}); - channelz_channel->counter_and_tracer()->RecordCallStarted(); - channelz_channel->counter_and_tracer()->RecordCallFailed(); - channelz_channel->counter_and_tracer()->RecordCallSucceeded(); - channelz_channel->counter_and_tracer()->RecordCallStarted(); - channelz_channel->counter_and_tracer()->RecordCallFailed(); - channelz_channel->counter_and_tracer()->RecordCallSucceeded(); + channelz_channel->RecordCallStarted(); + channelz_channel->RecordCallFailed(); + channelz_channel->RecordCallSucceeded(); + channelz_channel->RecordCallStarted(); + channelz_channel->RecordCallFailed(); + channelz_channel->RecordCallSucceeded(); ValidateChannel(channelz_channel, {3, 3, 3}); } TEST_P(ChannelzChannelTest, LastCallStartedMillis) { grpc_core::ExecCtx exec_ctx; - ChannelFixture channel(GetParam()); - ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(channel.channel()); + CallCountingHelper counter; // start a call to set the last call started timestamp - channelz_channel->counter_and_tracer()->RecordCallStarted(); - grpc_millis millis1 = - GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); + counter.RecordCallStarted(); + grpc_millis millis1 = GetLastCallStartedMillis(&counter); // time gone by should not affect the timestamp ChannelzSleep(100); - grpc_millis millis2 = - GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); + grpc_millis millis2 = GetLastCallStartedMillis(&counter); EXPECT_EQ(millis1, millis2); // calls succeeded or failed should not affect the timestamp ChannelzSleep(100); - channelz_channel->counter_and_tracer()->RecordCallFailed(); - channelz_channel->counter_and_tracer()->RecordCallSucceeded(); - grpc_millis millis3 = - GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); + counter.RecordCallFailed(); + counter.RecordCallSucceeded(); + grpc_millis millis3 = GetLastCallStartedMillis(&counter); EXPECT_EQ(millis1, millis3); // another call started should affect the timestamp // sleep for extra long to avoid flakes (since we cache Now()) ChannelzSleep(5000); - channelz_channel->counter_and_tracer()->RecordCallStarted(); - grpc_millis millis4 = - GetLastCallStartedMillis(channelz_channel->counter_and_tracer()); + counter.RecordCallStarted(); + grpc_millis millis4 = GetLastCallStartedMillis(&counter); EXPECT_NE(millis1, millis4); } -- cgit v1.2.3 From 844d4efcd2325504c6d916f7ad3b3cc638fada70 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Sun, 29 Jul 2018 20:43:05 -0700 Subject: Count calls for subchannels --- .../ext/filters/client_channel/client_channel.cc | 22 ++++++---------------- src/core/ext/filters/client_channel/subchannel.cc | 3 +++ 2 files changed, 9 insertions(+), 16 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 683cb0e01d..0368590a6a 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -1154,16 +1154,6 @@ static void pending_batches_add(grpc_call_element* elem, grpc_connected_subchannel_call_get_parent_data( calld->subchannel_call)); retry_commit(elem, retry_state); - // If we are not going to retry and have not yet started, pretend - // retries are disabled so that we don't bother with retry overhead. - if (calld->num_attempts_completed == 0) { - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: disabling retries before first attempt", - chand, calld); - } - calld->enable_retries = false; - } } } } @@ -1942,6 +1932,12 @@ static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { grpc_mdelem* server_pushback_md = nullptr; get_call_status(batch_data, GRPC_ERROR_REF(error), &status, &server_pushback_md); + if (status == GRPC_STATUS_OK) { + calld->pick.connected_subchannel->channelz_subchannel() + ->RecordCallSucceeded(); + } else { + calld->pick.connected_subchannel->channelz_subchannel()->RecordCallFailed(); + } if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: call finished, status=%s", chand, calld, grpc_status_code_to_string(status)); @@ -2797,12 +2793,6 @@ static void apply_service_config_to_call_locked(grpc_call_element* elem) { } } } - // If no retry policy, disable retries. - // TODO(roth): Remove this when adding support for transparent retries. - if (calld->method_params == nullptr || - calld->method_params->retry_policy() == nullptr) { - calld->enable_retries = false; - } } // Invoked once resolver results are available. diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index f0f8d94ef4..b74a354e9e 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -865,6 +865,9 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, gpr_log(GPR_ERROR, "error: %s", error_string); return error; } + if (channelz_subchannel_ != nullptr) { + channelz_subchannel_->RecordCallStarted(); + } grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); return GRPC_ERROR_NONE; } -- cgit v1.2.3 From d030114058b167ba3cbe71796ae30b99bc0c2e22 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 30 Jul 2018 22:06:46 -0700 Subject: Add back in disable retries --- src/core/ext/filters/client_channel/client_channel.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 0368590a6a..888a5efda3 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -1154,6 +1154,16 @@ static void pending_batches_add(grpc_call_element* elem, grpc_connected_subchannel_call_get_parent_data( calld->subchannel_call)); retry_commit(elem, retry_state); + // If we are not going to retry and have not yet started, pretend + // retries are disabled so that we don't bother with retry overhead. + if (calld->num_attempts_completed == 0) { + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: disabling retries before first attempt", + chand, calld); + } + calld->enable_retries = false; + } } } } @@ -2793,6 +2803,12 @@ static void apply_service_config_to_call_locked(grpc_call_element* elem) { } } } + // If no retry policy, disable retries. + // TODO(roth): Remove this when adding support for transparent retries. + if (calld->method_params == nullptr || + calld->method_params->retry_policy() == nullptr) { + calld->enable_retries = false; + } } // Invoked once resolver results are available. -- cgit v1.2.3 From e888e93293310259b9d4bbabff2baf312cdd8973 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 30 Jul 2018 22:29:47 -0700 Subject: reviewer feedback --- .../client_channel/client_channel_channelz.h | 9 ++++- src/core/ext/filters/client_channel/subchannel.cc | 4 +-- src/core/lib/channel/channelz.h | 16 +++++++-- src/core/lib/surface/channel.cc | 4 +-- test/core/channel/channel_trace_test.cc | 38 +++++++++++++++------- 5 files changed, 52 insertions(+), 19 deletions(-) (limited to 'src/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 735ffacfd2..5e01fdf2a3 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -77,7 +77,14 @@ class SubchannelNode : public BaseNode { grpc_json* RenderJson() override; // proxy methods to composed classes. - ChannelTrace* trace() { return trace_.get(); } + void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { + trace_->AddTraceEvent(severity, data); + } + void AddTraceEventWithReference(ChannelTrace::Severity severity, + grpc_slice data, + RefCountedPtr referenced_channel) { + trace_->AddTraceEventWithReference(severity, data, referenced_channel); + } void RecordCallStarted() { call_counter_.RecordCallStarted(); } void RecordCallFailed() { call_counter_.RecordCallFailed(); } void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index b74a354e9e..639a5fe9db 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -183,7 +183,7 @@ static void connection_destroy(void* arg, grpc_error* error) { static void subchannel_destroy(void* arg, grpc_error* error) { grpc_subchannel* c = static_cast(arg); if (c->channelz_subchannel != nullptr) { - c->channelz_subchannel->trace()->AddTraceEvent( + c->channelz_subchannel->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel destroyed")); c->channelz_subchannel->MarkSubchannelDestroyed(); @@ -397,7 +397,7 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, c->channelz_subchannel = grpc_core::MakeRefCounted( c, channel_tracer_max_nodes); - c->channelz_subchannel->trace()->AddTraceEvent( + c->channelz_subchannel->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Subchannel created")); } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 6e20f31b68..74b203af44 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -44,7 +44,8 @@ namespace channelz { namespace testing { class CallCountingHelperPeer; -} +class ChannelNodePeer; +} // namespace testing // base class for all channelz entities class BaseNode : public RefCounted { @@ -131,7 +132,14 @@ class ChannelNode : public BaseNode { bool ChannelIsDestroyed() { return channel_ == nullptr; } // proxy methods to composed classes. - ChannelTrace* trace() { return trace_.get(); } + void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { + trace_->AddTraceEvent(severity, data); + } + void AddTraceEventWithReference(ChannelTrace::Severity severity, + grpc_slice data, + RefCountedPtr referenced_channel) { + trace_->AddTraceEventWithReference(severity, data, referenced_channel); + } void RecordCallStarted() { call_counter_.RecordCallStarted(); } void RecordCallFailed() { call_counter_.RecordCallFailed(); } void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } @@ -141,8 +149,12 @@ class ChannelNode : public BaseNode { char* target_view() { return target_.get(); } // provides access to call_counter_ for child. CallCountingHelper* call_counter() { return &call_counter_; } + // provides access to channel trace for child. + ChannelTrace* trace() { return trace_.get(); } private: + // to allow the channel trace test to access trace(); + friend class testing::ChannelNodePeer; grpc_channel* channel_ = nullptr; UniquePtr target_; CallCountingHelper call_counter_; diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 01caadaaba..0b3508e27c 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -170,7 +170,7 @@ grpc_channel* grpc_channel_create_with_builder( bool is_top_level_channel = channel->is_client && !internal_channel; channel->channelz_channel = channel_node_create_func( channel, channel_tracer_max_nodes, is_top_level_channel); - channel->channelz_channel->trace()->AddTraceEvent( + channel->channelz_channel->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel created")); } @@ -417,7 +417,7 @@ void grpc_channel_internal_unref(grpc_channel* c REF_ARG) { static void destroy_channel(void* arg, grpc_error* error) { grpc_channel* channel = static_cast(arg); if (channel->channelz_channel != nullptr) { - channel->channelz_channel->trace()->AddTraceEvent( + channel->channelz_channel->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel destroyed")); channel->channelz_channel->MarkChannelDestroyed(); diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index 3f5aa85c8c..8a5ddc2723 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -40,6 +40,17 @@ namespace grpc_core { namespace channelz { namespace testing { + +// testing peer to access channel internals +class ChannelNodePeer { + public: + ChannelNodePeer(ChannelNode* node) : node_(node) {} + ChannelTrace* trace() { return node_->trace_.get(); } + + private: + ChannelNode* node_; +}; + namespace { grpc_json* GetJsonChild(grpc_json* parent, const char* key) { @@ -156,18 +167,19 @@ TEST_P(ChannelTracerTest, ComplexTest) { ChannelFixture channel1(GetParam()); RefCountedPtr sc1 = MakeRefCounted(channel1.channel(), GetParam(), true); + ChannelNodePeer sc1_peer(sc1.get()); tracer.AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - ValidateChannelTrace(sc1->trace(), 3, GetParam()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - AddSimpleTrace(sc1->trace()); - ValidateChannelTrace(sc1->trace(), 6, GetParam()); + AddSimpleTrace(sc1_peer.trace()); + AddSimpleTrace(sc1_peer.trace()); + AddSimpleTrace(sc1_peer.trace()); + ValidateChannelTrace(sc1_peer.trace(), 3, GetParam()); + AddSimpleTrace(sc1_peer.trace()); + AddSimpleTrace(sc1_peer.trace()); + AddSimpleTrace(sc1_peer.trace()); + ValidateChannelTrace(sc1_peer.trace(), 6, GetParam()); AddSimpleTrace(&tracer); AddSimpleTrace(&tracer); ValidateChannelTrace(&tracer, 5, GetParam()); @@ -203,24 +215,26 @@ TEST_P(ChannelTracerTest, TestNesting) { ChannelFixture channel1(GetParam()); RefCountedPtr sc1 = MakeRefCounted(channel1.channel(), GetParam(), true); + ChannelNodePeer sc1_peer(sc1.get()); tracer.AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("subchannel one created"), sc1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(sc1->trace()); + AddSimpleTrace(sc1_peer.trace()); ChannelFixture channel2(GetParam()); RefCountedPtr conn1 = MakeRefCounted(channel2.channel(), GetParam(), true); + ChannelNodePeer conn1_peer(conn1.get()); // nesting one level deeper. - sc1->trace()->AddTraceEventWithReference( + sc1_peer.trace()->AddTraceEventWithReference( ChannelTrace::Severity::Info, grpc_slice_from_static_string("connection one created"), conn1); ValidateChannelTrace(&tracer, 3, GetParam()); - AddSimpleTrace(conn1->trace()); + AddSimpleTrace(conn1_peer.trace()); AddSimpleTrace(&tracer); AddSimpleTrace(&tracer); ValidateChannelTrace(&tracer, 5, GetParam()); - ValidateChannelTrace(conn1->trace(), 1, GetParam()); + ValidateChannelTrace(conn1_peer.trace(), 1, GetParam()); ChannelFixture channel3(GetParam()); RefCountedPtr sc2 = MakeRefCounted(channel3.channel(), GetParam(), true); -- cgit v1.2.3 From 885c33da8bb363014e4231f8b5f3da024923f287 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 30 Jul 2018 22:36:25 -0700 Subject: reviewer feedback --- .../ext/filters/client_channel/client_channel_channelz.cc | 11 +++++------ src/core/ext/filters/client_channel/client_channel_channelz.h | 7 ++++--- src/core/lib/channel/channelz.cc | 9 ++++----- src/core/lib/channel/channelz.h | 8 ++++---- 4 files changed, 17 insertions(+), 18 deletions(-) (limited to 'src/core') 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 7120ec57f1..d904fc28b2 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -155,12 +155,11 @@ SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes) : BaseNode(EntityType::kSubchannel), subchannel_(subchannel), - target_(UniquePtr( - gpr_strdup(grpc_subchannel_get_target(subchannel_)))) { - trace_.Init(channel_tracer_max_nodes); -} + target_( + UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_)))), + trace_(channel_tracer_max_nodes) {} -SubchannelNode::~SubchannelNode() { trace_.Destroy(); } +SubchannelNode::~SubchannelNode() {} void SubchannelNode::PopulateConnectivityState(grpc_json* json) { grpc_connectivity_state state; @@ -199,7 +198,7 @@ grpc_json* SubchannelNode::RenderJson() { grpc_json_create_child(nullptr, json, "target", target_.get(), GRPC_JSON_STRING, false); // fill in the channel trace if applicable - grpc_json* trace_json = trace_->RenderJson(); + grpc_json* trace_json = trace_.RenderJson(); if (trace_json != nullptr) { trace_json->key = "trace"; // this object is named trace in channelz.proto grpc_json_link_child(json, trace_json, nullptr); 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 5e01fdf2a3..9a3fc1d6f1 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -23,6 +23,7 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/channel/channel_trace.h" #include "src/core/lib/channel/channelz.h" #include "src/core/lib/gprpp/inlined_vector.h" @@ -78,12 +79,12 @@ class SubchannelNode : public BaseNode { // proxy methods to composed classes. void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { - trace_->AddTraceEvent(severity, data); + trace_.AddTraceEvent(severity, data); } void AddTraceEventWithReference(ChannelTrace::Severity severity, grpc_slice data, RefCountedPtr referenced_channel) { - trace_->AddTraceEventWithReference(severity, data, referenced_channel); + trace_.AddTraceEventWithReference(severity, data, referenced_channel); } void RecordCallStarted() { call_counter_.RecordCallStarted(); } void RecordCallFailed() { call_counter_.RecordCallFailed(); } @@ -93,7 +94,7 @@ class SubchannelNode : public BaseNode { grpc_subchannel* subchannel_; UniquePtr target_; CallCountingHelper call_counter_; - ManualConstructor trace_; + ChannelTrace trace_; void PopulateConnectivityState(grpc_json* json); }; diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index a75a05023a..b908363b1b 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -92,11 +92,10 @@ ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes, : BaseNode(is_top_level_channel ? EntityType::kTopLevelChannel : EntityType::kInternalChannel), channel_(channel), - target_(UniquePtr(grpc_channel_get_target(channel_))) { - trace_.Init(channel_tracer_max_nodes); -} + target_(UniquePtr(grpc_channel_get_target(channel_))), + trace_(channel_tracer_max_nodes) {} -ChannelNode::~ChannelNode() { trace_.Destroy(); } +ChannelNode::~ChannelNode() {} grpc_json* ChannelNode::RenderJson() { // We need to track these three json objects to build our object @@ -123,7 +122,7 @@ grpc_json* ChannelNode::RenderJson() { grpc_json_create_child(nullptr, json, "target", target_.get(), GRPC_JSON_STRING, false); // fill in the channel trace if applicable - grpc_json* trace_json = trace_->RenderJson(); + grpc_json* trace_json = trace_.RenderJson(); if (trace_json != nullptr) { trace_json->key = "trace"; // this object is named trace in channelz.proto grpc_json_link_child(json, trace_json, nullptr); diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 74b203af44..66753c96ee 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -133,12 +133,12 @@ class ChannelNode : public BaseNode { // proxy methods to composed classes. void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { - trace_->AddTraceEvent(severity, data); + trace_.AddTraceEvent(severity, data); } void AddTraceEventWithReference(ChannelTrace::Severity severity, grpc_slice data, RefCountedPtr referenced_channel) { - trace_->AddTraceEventWithReference(severity, data, referenced_channel); + trace_.AddTraceEventWithReference(severity, data, referenced_channel); } void RecordCallStarted() { call_counter_.RecordCallStarted(); } void RecordCallFailed() { call_counter_.RecordCallFailed(); } @@ -150,7 +150,7 @@ class ChannelNode : public BaseNode { // provides access to call_counter_ for child. CallCountingHelper* call_counter() { return &call_counter_; } // provides access to channel trace for child. - ChannelTrace* trace() { return trace_.get(); } + ChannelTrace* trace() { return &trace_; } private: // to allow the channel trace test to access trace(); @@ -158,7 +158,7 @@ class ChannelNode : public BaseNode { grpc_channel* channel_ = nullptr; UniquePtr target_; CallCountingHelper call_counter_; - ManualConstructor trace_; + ChannelTrace trace_; }; // Handles channelz bookkeeping for servers -- cgit v1.2.3 From 016a3354a5d9915dfd8a15822b0874eab6cbc7ba Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 30 Jul 2018 22:45:44 -0700 Subject: reviewer comments --- src/core/ext/filters/client_channel/client_channel.cc | 18 +++++++++++++----- .../filters/client_channel/client_channel_channelz.cc | 4 ++-- src/core/ext/filters/client_channel/subchannel.cc | 3 --- src/core/lib/channel/channelz.cc | 4 ++-- src/core/lib/channel/channelz.h | 2 +- 5 files changed, 18 insertions(+), 13 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 888a5efda3..b3c9268bd8 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -1942,11 +1942,14 @@ static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { grpc_mdelem* server_pushback_md = nullptr; get_call_status(batch_data, GRPC_ERROR_REF(error), &status, &server_pushback_md); - if (status == GRPC_STATUS_OK) { - calld->pick.connected_subchannel->channelz_subchannel() - ->RecordCallSucceeded(); - } else { - calld->pick.connected_subchannel->channelz_subchannel()->RecordCallFailed(); + grpc_core::channelz::SubchannelNode* channelz_subchannel = + calld->pick.connected_subchannel->channelz_subchannel(); + if (channelz_subchannel != nullptr) { + if (status == GRPC_STATUS_OK) { + channelz_subchannel->RecordCallSucceeded(); + } else { + channelz_subchannel->RecordCallFailed(); + } } if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: call finished, status=%s", chand, @@ -2581,6 +2584,11 @@ static void create_subchannel_call(grpc_call_element* elem, grpc_error* error) { new_error = grpc_error_add_child(new_error, error); pending_batches_fail(elem, new_error, true /* yield_call_combiner */); } else { + grpc_core::channelz::SubchannelNode* channelz_subchannel = + calld->pick.connected_subchannel->channelz_subchannel(); + if (channelz_subchannel != nullptr) { + channelz_subchannel->RecordCallStarted(); + } if (parent_data_size > 0) { subchannel_call_retry_state* retry_state = static_cast( 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 d904fc28b2..06b4d2ab95 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -130,7 +130,7 @@ grpc_json* ClientChannelNode::RenderJson() { grpc_json_link_child(json, trace_json, nullptr); } // ask CallCountingHelper to populate trace and call count data. - call_counter()->PopulateCallData(json); + call_counter()->PopulateCallCounts(json); // reset to the top level json = top_level_json; PopulateChildRefs(json); @@ -204,7 +204,7 @@ grpc_json* SubchannelNode::RenderJson() { grpc_json_link_child(json, trace_json, nullptr); } // ask CallCountingHelper to populate trace and call count data. - call_counter_.PopulateCallData(json); + call_counter_.PopulateCallCounts(json); return top_level_json; } diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 639a5fe9db..a7df2ee6cc 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -865,9 +865,6 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, gpr_log(GPR_ERROR, "error: %s", error_string); return error; } - if (channelz_subchannel_ != nullptr) { - channelz_subchannel_->RecordCallStarted(); - } grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); return GRPC_ERROR_NONE; } diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index b908363b1b..1ac7bd3976 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -66,7 +66,7 @@ void CallCountingHelper::RecordCallStarted() { (gpr_atm)ExecCtx::Get()->Now()); } -void CallCountingHelper::PopulateCallData(grpc_json* json) { +void CallCountingHelper::PopulateCallCounts(grpc_json* json) { grpc_json* json_iterator = nullptr; if (calls_started_ != 0) { json_iterator = grpc_json_add_number_string_child( @@ -128,7 +128,7 @@ grpc_json* ChannelNode::RenderJson() { grpc_json_link_child(json, trace_json, nullptr); } // ask CallCountingHelper to populate trace and call count data. - call_counter_.PopulateCallData(json); + call_counter_.PopulateCallCounts(json); return top_level_json; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 66753c96ee..14edc75123 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -99,7 +99,7 @@ class CallCountingHelper { } // Common rendering of the call count data and last_call_started_timestamp. - void PopulateCallData(grpc_json* json); + void PopulateCallCounts(grpc_json* json); private: // testing peer friend. -- cgit v1.2.3 From 97a5bca26164b0f2c5763018f710ee75a9b817b1 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 31 Jul 2018 10:13:58 -0700 Subject: reviewer feedback --- src/core/ext/filters/client_channel/client_channel.cc | 4 +--- src/core/ext/filters/client_channel/subchannel.cc | 1 - src/core/ext/filters/client_channel/subchannel.h | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index b3c9268bd8..3ea4b21ebd 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -892,7 +892,6 @@ typedef struct client_channel_call_data { grpc_millis deadline; gpr_arena* arena; grpc_call_stack* owning_call; - grpc_call* call; grpc_call_combiner* call_combiner; grpc_core::RefCountedPtr retry_throttle_data; @@ -2571,8 +2570,7 @@ static void create_subchannel_call(grpc_call_element* elem, grpc_error* error) { calld->arena, // arena calld->pick.subchannel_call_context, // context calld->call_combiner, // call_combiner - parent_data_size, // parent_data_size - calld->call // call + parent_data_size // parent_data_size }; grpc_error* new_error = calld->pick.connected_subchannel->CreateCall( call_args, &calld->subchannel_call); diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index a7df2ee6cc..abf3a039f3 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -46,7 +46,6 @@ #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel_init.h" #include "src/core/lib/transport/connectivity_state.h" diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index d62348488e..e3d9296c26 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -83,7 +83,6 @@ class ConnectedSubchannel : public RefCountedWithTracing { grpc_call_context_element* context; grpc_call_combiner* call_combiner; size_t parent_data_size; - grpc_call* call; }; explicit ConnectedSubchannel(grpc_channel_stack* channel_stack, -- cgit v1.2.3 From fde951db9c6f87597faa7ae1b3d0f521ff1adb51 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Thu, 2 Aug 2018 20:55:00 -0700 Subject: Intecept recv_trailing in client_channel for channelz --- .../ext/filters/client_channel/client_channel.cc | 87 +++++++++++++++++++--- src/core/lib/channel/connected_channel.cc | 12 +-- src/core/lib/surface/call.cc | 10 ++- test/core/end2end/tests/channelz.cc | 3 + 4 files changed, 94 insertions(+), 18 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index f4d5596270..c3669189f4 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -923,6 +923,10 @@ typedef struct client_channel_call_data { grpc_closure pick_closure; grpc_closure pick_cancel_closure; + grpc_closure recv_trailing_metadata_ready_channelz; + grpc_closure* original_recv_trailing_metadata; + // metadata_batch recv_trailing_metadata_channelz; + grpc_polling_entity* pollent; bool pollent_added_to_interested_parties; @@ -984,6 +988,14 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem); static void on_complete(void* arg, grpc_error* error); static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored); static void start_pick_locked(void* arg, grpc_error* ignored); +template +static pending_batch* pending_batch_find(grpc_call_element* elem, + const char* log_message, + Predicate predicate); +static void get_call_status(grpc_call_element* elem, + grpc_metadata_batch* md_batch, grpc_error* error, + grpc_status_code* status, + grpc_mdelem** server_pushback_md); // // send op data caching @@ -1258,6 +1270,59 @@ static void resume_pending_batch_in_call_combiner(void* arg, grpc_subchannel_call_process_op(subchannel_call, batch); } +static void recv_trailing_metadata_ready_channelz(void* arg, + grpc_error* error) { + grpc_call_element* elem = static_cast(arg); + channel_data* chand = static_cast(elem->channel_data); + call_data* calld = static_cast(elem->call_data); + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: got recv_trailing_metadata_ready_channelz, " + "error=%s", + chand, calld, grpc_error_string(error)); + } + // find the right pending batch. + pending_batch* pending = pending_batch_find( + elem, "invoking recv_trailing_metadata_channelz for", + [](grpc_transport_stream_op_batch* batch) { + return batch->recv_trailing_metadata && + batch->payload->recv_trailing_metadata + .recv_trailing_metadata_ready != nullptr; + }); + grpc_status_code status = GRPC_STATUS_OK; + grpc_metadata_batch* md_batch = + pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata; + get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, nullptr); + grpc_core::channelz::SubchannelNode* channelz_subchannel = + calld->pick.connected_subchannel->channelz_subchannel(); + GPR_ASSERT(channelz_subchannel != nullptr); + if (status == GRPC_STATUS_OK) { + channelz_subchannel->RecordCallSucceeded(); + } else { + channelz_subchannel->RecordCallFailed(); + } + pending->batch = nullptr; + GRPC_CLOSURE_SCHED(calld->original_recv_trailing_metadata, error); +} + +static bool maybe_intercept_recv_trailing_for_channelz( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { + call_data* calld = static_cast(elem->call_data); + // only add interceptor is channelz is enabled. + if (calld->pick.connected_subchannel->channelz_subchannel() != nullptr) { + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_channelz, + recv_trailing_metadata_ready_channelz, elem, + grpc_schedule_on_exec_ctx); + calld->original_recv_trailing_metadata = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready_channelz; + return true; + } else { + return false; + } +} + // This is called via the call combiner, so access to calld is synchronized. static void pending_batches_resume(grpc_call_element* elem) { channel_data* chand = static_cast(elem->channel_data); @@ -1282,13 +1347,17 @@ static void pending_batches_resume(grpc_call_element* elem) { pending_batch* pending = &calld->pending_batches[i]; grpc_transport_stream_op_batch* batch = pending->batch; if (batch != nullptr) { + bool intercepted = + maybe_intercept_recv_trailing_for_channelz(elem, batch); batch->handler_private.extra_arg = calld->subchannel_call; GRPC_CLOSURE_INIT(&batch->handler_private.closure, resume_pending_batch_in_call_combiner, batch, grpc_schedule_on_exec_ctx); closures.Add(&batch->handler_private.closure, GRPC_ERROR_NONE, "pending_batches_resume"); - pending_batch_clear(calld, pending); + if (!intercepted) { + pending_batch_clear(calld, pending); + } } } // Note: This will release the call combiner. @@ -1768,22 +1837,20 @@ static void recv_message_ready(void* arg, grpc_error* error) { // // Sets *status and *server_pushback_md based on batch_data and error. -static void get_call_status(subchannel_batch_data* batch_data, - grpc_error* error, grpc_status_code* status, +static void get_call_status(grpc_call_element* elem, + grpc_metadata_batch* md_batch, grpc_error* error, + grpc_status_code* status, grpc_mdelem** server_pushback_md) { - grpc_call_element* elem = batch_data->elem; call_data* calld = static_cast(elem->call_data); if (error != GRPC_ERROR_NONE) { grpc_error_get_status(error, calld->deadline, status, nullptr, nullptr, nullptr); } else { - grpc_metadata_batch* md_batch = - batch_data->batch.payload->recv_trailing_metadata - .recv_trailing_metadata; GPR_ASSERT(md_batch->idx.named.grpc_status != nullptr); *status = grpc_get_status_code_from_metadata(md_batch->idx.named.grpc_status->md); - if (md_batch->idx.named.grpc_retry_pushback_ms != nullptr) { + if (server_pushback_md != nullptr && + md_batch->idx.named.grpc_retry_pushback_ms != nullptr) { *server_pushback_md = &md_batch->idx.named.grpc_retry_pushback_ms->md; } } @@ -1956,7 +2023,9 @@ static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { // Get the call's status and check for server pushback metadata. grpc_status_code status = GRPC_STATUS_OK; grpc_mdelem* server_pushback_md = nullptr; - get_call_status(batch_data, GRPC_ERROR_REF(error), &status, + grpc_metadata_batch* md_batch = + batch_data->batch.payload->recv_trailing_metadata.recv_trailing_metadata; + get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, &server_pushback_md); grpc_core::channelz::SubchannelNode* channelz_subchannel = calld->pick.connected_subchannel->channelz_subchannel(); diff --git a/src/core/lib/channel/connected_channel.cc b/src/core/lib/channel/connected_channel.cc index e2ea334ded..90a0254663 100644 --- a/src/core/lib/channel/connected_channel.cc +++ b/src/core/lib/channel/connected_channel.cc @@ -104,18 +104,18 @@ static void con_start_transport_stream_op_batch( if (batch->recv_initial_metadata) { callback_state* state = &calld->recv_initial_metadata_ready; intercept_callback( - calld, state, false, "recv_initial_metadata_ready", + calld, state, false, "connected_recv_initial_metadata_ready", &batch->payload->recv_initial_metadata.recv_initial_metadata_ready); } if (batch->recv_message) { callback_state* state = &calld->recv_message_ready; - intercept_callback(calld, state, false, "recv_message_ready", + intercept_callback(calld, state, false, "connected_recv_message_ready", &batch->payload->recv_message.recv_message_ready); } if (batch->recv_trailing_metadata) { callback_state* state = &calld->recv_trailing_metadata_ready; intercept_callback( - calld, state, false, "recv_trailing_metadata_ready", + calld, state, false, "connected_recv_trailing_metadata_ready", &batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready); } if (batch->cancel_stream) { @@ -126,11 +126,13 @@ static void con_start_transport_stream_op_batch( // closure for each one. callback_state* state = static_cast(gpr_malloc(sizeof(*state))); - intercept_callback(calld, state, true, "on_complete (cancel_stream)", + intercept_callback(calld, state, true, + "connected_on_complete (cancel_stream)", &batch->on_complete); } else if (batch->on_complete != nullptr) { callback_state* state = get_state_for_batch(calld, batch); - intercept_callback(calld, state, false, "on_complete", &batch->on_complete); + intercept_callback(calld, state, false, "connected_on_complete", + &batch->on_complete); } grpc_transport_perform_stream_op( chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), batch); diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 26dd361e0d..859915affb 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -1422,7 +1422,7 @@ static void receiving_stream_ready_in_call_combiner(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_message_ready"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "call_recv_message_ready"); receiving_stream_ready(bctlp, error); } @@ -1507,7 +1507,8 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_initial_metadata_ready"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, + "call_recv_initial_metadata_ready"); add_batch_error(bctl, GRPC_ERROR_REF(error), false); if (error == GRPC_ERROR_NONE) { @@ -1558,7 +1559,8 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, + "call_recv_trailing_metadata_ready"); add_batch_error(bctl, GRPC_ERROR_REF(error), false); grpc_metadata_batch* md = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; @@ -1569,7 +1571,7 @@ static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) { static void finish_batch(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, "on_complete"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "call_on_complete"); add_batch_error(bctl, GRPC_ERROR_REF(error), false); finish_batch_step(bctl); } diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 754c3d3741..562822c537 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -243,6 +243,9 @@ static void test_channelz(grpc_end2end_test_config config) { json = grpc_channelz_get_subchannel(2); gpr_log(GPR_INFO, "%s", json); + GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); + GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\"")); + GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); gpr_free(json); end_test(&f); -- cgit v1.2.3 From 0db2b830eb95c12975cb69b945f837194f38d96c Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 3 Aug 2018 11:24:18 -0400 Subject: Refactor rendering to use template method pattern --- .../client_channel/client_channel_channelz.cc | 39 ---------------------- .../client_channel/client_channel_channelz.h | 9 +++-- src/core/lib/channel/channelz.cc | 7 ++++ src/core/lib/channel/channelz.h | 20 ++++++----- 4 files changed, 23 insertions(+), 52 deletions(-) (limited to 'src/core') 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 06b4d2ab95..7e8f59bcd3 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -98,45 +98,6 @@ 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", 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); - // fill in the channel trace if applicable - grpc_json* trace_json = trace()->RenderJson(); - if (trace_json != nullptr) { - trace_json->key = "trace"; // this object is named trace in channelz.proto - grpc_json_link_child(json, trace_json, nullptr); - } - // ask CallCountingHelper to populate trace and call count data. - call_counter()->PopulateCallCounts(json); - // reset to the top level - json = top_level_json; - PopulateChildRefs(json); - return top_level_json; -} - grpc_arg ClientChannelNode::CreateChannelArg() { return grpc_channel_arg_pointer_create( const_cast(GRPC_ARG_CHANNELZ_CHANNEL_NODE_CREATION_FUNC), 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 9a3fc1d6f1..a9e98deedb 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -50,7 +50,10 @@ class ClientChannelNode : public ChannelNode { bool is_top_level_channel); virtual ~ClientChannelNode() {} - grpc_json* RenderJson() override; + // Overriding template methods from ChannelNode to render information that + // only ClientChannelNode knows about. + void PopulateConnectivityState(grpc_json* json) override; + void PopulateChildRefs(grpc_json* json) override; // Helper to create a channel arg to ensure this type of ChannelNode is // created. @@ -58,10 +61,6 @@ class ClientChannelNode : public ChannelNode { private: grpc_channel_element* client_channel_; - - // helpers - void PopulateConnectivityState(grpc_json* json); - void PopulateChildRefs(grpc_json* json); }; // Handles channelz bookkeeping for sockets diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 1ac7bd3976..9f54850002 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -117,6 +117,9 @@ grpc_json* ChannelNode::RenderJson() { GRPC_JSON_OBJECT, false); json = data; json_iterator = nullptr; + // template method. Child classes may override this to add their specific + // functionality. + PopulateConnectivityState(json); // populate the target. GPR_ASSERT(target_.get() != nullptr); grpc_json_create_child(nullptr, json, "target", target_.get(), @@ -129,6 +132,10 @@ grpc_json* ChannelNode::RenderJson() { } // ask CallCountingHelper to populate trace and call count data. call_counter_.PopulateCallCounts(json); + json = top_level_json; + // template method. Child classes may override this to add their specific + // functionality. + PopulateChildRefs(json); return top_level_json; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 14edc75123..e2cef233e6 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -124,6 +124,18 @@ class ChannelNode : public BaseNode { grpc_json* RenderJson() override; + // template methods. RenderJSON uses these methods to render its JSON + // representation. These are virtual so that children classes may provide + // their specific mechanism for populating these parts of the channelz + // object. + // + // ChannelNode does not have a notion of connectivity state or child refs, + // so it leaves these implementations blank. + // + // This is utilizing the template method design pattern. + virtual void PopulateConnectivityState(grpc_json* json) {} + virtual void PopulateChildRefs(grpc_json* json) {} + void MarkChannelDestroyed() { GPR_ASSERT(channel_ != nullptr); channel_ = nullptr; @@ -144,14 +156,6 @@ class ChannelNode : public BaseNode { void RecordCallFailed() { call_counter_.RecordCallFailed(); } void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } - protected: - // provides view of target for child. - char* target_view() { return target_.get(); } - // provides access to call_counter_ for child. - CallCountingHelper* call_counter() { return &call_counter_; } - // provides access to channel trace for child. - ChannelTrace* trace() { return &trace_; } - private: // to allow the channel trace test to access trace(); friend class testing::ChannelNodePeer; -- cgit v1.2.3 From e2a87dac6975b3cbf6e434e1bb5112269043653e Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 3 Aug 2018 11:31:19 -0400 Subject: Add some comments --- src/core/ext/filters/client_channel/client_channel.cc | 8 ++++++-- src/core/ext/filters/client_channel/client_channel_channelz.h | 3 ++- src/core/lib/channel/channelz.h | 3 ++- test/core/end2end/tests/channelz.cc | 7 ------- 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index c3669189f4..4263e791c4 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -925,7 +925,6 @@ typedef struct client_channel_call_data { grpc_closure recv_trailing_metadata_ready_channelz; grpc_closure* original_recv_trailing_metadata; - // metadata_batch recv_trailing_metadata_channelz; grpc_polling_entity* pollent; bool pollent_added_to_interested_parties; @@ -1305,6 +1304,9 @@ static void recv_trailing_metadata_ready_channelz(void* arg, GRPC_CLOSURE_SCHED(calld->original_recv_trailing_metadata, error); } +// If channelz is enabled, intercept recv_trailing so that we may check the +// status and associate it to a subchannel. +// Returns true if callback was intercepted, false otherwise. static bool maybe_intercept_recv_trailing_for_channelz( grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { call_data* calld = static_cast(elem->call_data); @@ -1355,6 +1357,7 @@ static void pending_batches_resume(grpc_call_element* elem) { grpc_schedule_on_exec_ctx); closures.Add(&batch->handler_private.closure, GRPC_ERROR_NONE, "pending_batches_resume"); + // Only clear if we haven't intercepted anything. if (!intercepted) { pending_batch_clear(calld, pending); } @@ -1836,7 +1839,8 @@ static void recv_message_ready(void* arg, grpc_error* error) { // recv_trailing_metadata handling // -// Sets *status and *server_pushback_md based on batch_data and error. +// Sets *status and *server_pushback_md based on md_batch and error. +// Only sets *server_pushback_md if server_pushback_md != nullptr. static void get_call_status(grpc_call_element* elem, grpc_metadata_batch* md_batch, grpc_error* error, grpc_status_code* status, 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 a9e98deedb..8ce331e529 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -83,7 +83,8 @@ class SubchannelNode : public BaseNode { void AddTraceEventWithReference(ChannelTrace::Severity severity, grpc_slice data, RefCountedPtr referenced_channel) { - trace_.AddTraceEventWithReference(severity, data, referenced_channel); + trace_.AddTraceEventWithReference(severity, data, + std::move(referenced_channel)); } void RecordCallStarted() { call_counter_.RecordCallStarted(); } void RecordCallFailed() { call_counter_.RecordCallFailed(); } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index e2cef233e6..bd2735929c 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -150,7 +150,8 @@ class ChannelNode : public BaseNode { void AddTraceEventWithReference(ChannelTrace::Severity severity, grpc_slice data, RefCountedPtr referenced_channel) { - trace_.AddTraceEventWithReference(severity, data, referenced_channel); + trace_.AddTraceEventWithReference(severity, data, + std::move(referenced_channel)); } void RecordCallStarted() { call_counter_.RecordCallStarted(); } void RecordCallFailed() { call_counter_.RecordCallFailed(); } diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 562822c537..533703a2be 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -241,13 +241,6 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); - json = grpc_channelz_get_subchannel(2); - gpr_log(GPR_INFO, "%s", json); - GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); - GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\"")); - GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); - gpr_free(json); - end_test(&f); config.tear_down_data(&f); } -- cgit v1.2.3 From ccf04c45112ac43b880b7a28cb7c789fa47284fa Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 13 Aug 2018 07:28:54 -0700 Subject: WIP --- src/core/ext/filters/client_channel/client_channel.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 82c844a800..8b4f1b604c 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -1312,7 +1312,7 @@ static void recv_trailing_metadata_ready_channelz(void* arg, channelz_subchannel->RecordCallFailed(); } pending->batch = nullptr; - GRPC_CLOSURE_SCHED(calld->original_recv_trailing_metadata, error); + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata, error); } // If channelz is enabled, intercept recv_trailing so that we may check the -- cgit v1.2.3 From e0ae6c73ec97c5e62c82c99a603ac13730b23cff Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 13 Aug 2018 10:30:51 -0700 Subject: Fix bug with proxy end2end test --- .../ext/filters/client_channel/client_channel.cc | 58 +++++++++++----------- 1 file changed, 30 insertions(+), 28 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 8b4f1b604c..d3a4c49821 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -934,8 +934,10 @@ typedef struct client_channel_call_data { grpc_closure pick_closure; grpc_closure pick_cancel_closure; + // state needed to support channelz interception of recv trailing metadata. grpc_closure recv_trailing_metadata_ready_channelz; grpc_closure* original_recv_trailing_metadata; + grpc_transport_stream_op_batch* recv_trailing_metadata_batch; grpc_polling_entity* pollent; bool pollent_added_to_interested_parties; @@ -1291,17 +1293,11 @@ static void recv_trailing_metadata_ready_channelz(void* arg, "error=%s", chand, calld, grpc_error_string(error)); } - // find the right pending batch. - pending_batch* pending = pending_batch_find( - elem, "invoking recv_trailing_metadata_channelz for", - [](grpc_transport_stream_op_batch* batch) { - return batch->recv_trailing_metadata && - batch->payload->recv_trailing_metadata - .recv_trailing_metadata_ready != nullptr; - }); + GPR_ASSERT(calld->recv_trailing_metadata_batch != nullptr); grpc_status_code status = GRPC_STATUS_OK; grpc_metadata_batch* md_batch = - pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata; + calld->recv_trailing_metadata_batch->payload->recv_trailing_metadata + .recv_trailing_metadata; get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, nullptr); grpc_core::channelz::SubchannelNode* channelz_subchannel = calld->pick.connected_subchannel->channelz_subchannel(); @@ -1311,29 +1307,39 @@ static void recv_trailing_metadata_ready_channelz(void* arg, } else { channelz_subchannel->RecordCallFailed(); } - pending->batch = nullptr; + calld->recv_trailing_metadata_batch = nullptr; GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata, error); } // If channelz is enabled, intercept recv_trailing so that we may check the // status and associate it to a subchannel. // Returns true if callback was intercepted, false otherwise. -static bool maybe_intercept_recv_trailing_for_channelz( +static void maybe_intercept_recv_trailing_for_channelz( grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { call_data* calld = static_cast(elem->call_data); + // only intercept payloads with recv trailing. + if (!batch->recv_trailing_metadata) { + return; + } // only add interceptor is channelz is enabled. - if (calld->pick.connected_subchannel->channelz_subchannel() != nullptr) { - GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_channelz, - recv_trailing_metadata_ready_channelz, elem, - grpc_schedule_on_exec_ctx); - calld->original_recv_trailing_metadata = - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = - &calld->recv_trailing_metadata_ready_channelz; - return true; - } else { - return false; + if (calld->pick.connected_subchannel->channelz_subchannel() == nullptr) { + return; + } + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "calld=%p batch=%p: intercepting recv trailing for channelz", calld, + batch); } + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_channelz, + recv_trailing_metadata_ready_channelz, elem, + grpc_schedule_on_exec_ctx); + // save some state needed for the interception callback. + GPR_ASSERT(calld->recv_trailing_metadata_batch == nullptr); + calld->recv_trailing_metadata_batch = batch; + calld->original_recv_trailing_metadata = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready_channelz; } // This is called via the call combiner, so access to calld is synchronized. @@ -1360,18 +1366,14 @@ static void pending_batches_resume(grpc_call_element* elem) { pending_batch* pending = &calld->pending_batches[i]; grpc_transport_stream_op_batch* batch = pending->batch; if (batch != nullptr) { - bool intercepted = - maybe_intercept_recv_trailing_for_channelz(elem, batch); + maybe_intercept_recv_trailing_for_channelz(elem, batch); batch->handler_private.extra_arg = calld->subchannel_call; GRPC_CLOSURE_INIT(&batch->handler_private.closure, resume_pending_batch_in_call_combiner, batch, grpc_schedule_on_exec_ctx); closures.Add(&batch->handler_private.closure, GRPC_ERROR_NONE, "pending_batches_resume"); - // Only clear if we haven't intercepted anything. - if (!intercepted) { - pending_batch_clear(calld, pending); - } + pending_batch_clear(calld, pending); } } // Note: This will release the call combiner. -- cgit v1.2.3 From b8f030bc0b507903e9d156fb44d161015273d0c6 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 13 Aug 2018 13:55:44 -0700 Subject: reformat --- src/core/ext/filters/client_channel/subchannel.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 4a45ca081c..e94186da00 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -866,14 +866,14 @@ grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, connection.release(); // Ref is passed to the grpc_subchannel_call object. (*call)->connection = this; const grpc_call_element_args call_args = { - callstk, /* call_stack */ - nullptr, /* server_transport_data */ - args.context, /* context */ - args.path, /* path */ - args.start_time, /* start_time */ - args.deadline, /* deadline */ - args.arena, /* arena */ - args.call_combiner, /* call_combiner */ + callstk, /* call_stack */ + nullptr, /* server_transport_data */ + args.context, /* context */ + args.path, /* path */ + args.start_time, /* start_time */ + args.deadline, /* deadline */ + args.arena, /* arena */ + args.call_combiner /* call_combiner */ }; grpc_error* error = grpc_call_stack_init( channel_stack_, 1, subchannel_call_destroy, *call, &call_args); -- cgit v1.2.3 From 3aa987a29a02f59116f3e7d07cfa6a4835c211b4 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 13 Aug 2018 23:43:48 -0700 Subject: Add channelz server support --- include/grpc/grpc.h | 3 + src/core/lib/channel/channelz.cc | 41 +++++++++++++ src/core/lib/channel/channelz.h | 28 +++++++-- src/core/lib/channel/channelz_registry.cc | 40 +++++++++++++ src/core/lib/channel/channelz_registry.h | 7 +++ src/core/lib/surface/call.cc | 54 +++++++++++------ src/core/lib/surface/call.h | 1 + src/core/lib/surface/channel.cc | 7 ++- src/core/lib/surface/server.cc | 24 ++++++++ src/core/lib/surface/server.h | 4 ++ test/core/channel/channelz_test.cc | 90 ++++++++++++++++++++++++++++- test/core/end2end/tests/channelz.cc | 67 ++++++++++++++------- test/cpp/util/channel_trace_proto_helper.cc | 9 +++ test/cpp/util/channel_trace_proto_helper.h | 2 + 14 files changed, 331 insertions(+), 46 deletions(-) (limited to 'src/core') diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 412778f7f7..cb32808c56 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -483,6 +483,9 @@ GRPCAPI const grpc_arg_pointer_vtable* grpc_resource_quota_arg_vtable(void); The returned string is allocated and must be freed by the application. */ GRPCAPI char* grpc_channelz_get_top_channels(intptr_t start_channel_id); +/* Gets all servers that exist in the process. */ +GRPCAPI char* grpc_channelz_get_servers(intptr_t start_channel_id); + /* Returns a single Channel, or else a NOT_FOUND code. The returned string is allocated and must be freed by the application. */ GRPCAPI char* grpc_channelz_get_channel(intptr_t channel_id); diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 9f54850002..bb79005654 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -48,6 +48,7 @@ BaseNode::~BaseNode() { ChannelzRegistry::Unregister(uuid_); } char* BaseNode::RenderJsonString() { grpc_json* json = RenderJson(); + GPR_ASSERT(json != nullptr); char* json_str = grpc_json_dump_to_string(json, 0); grpc_json_destroy(json); return json_str; @@ -146,5 +147,45 @@ RefCountedPtr ChannelNode::MakeChannelNode( channel, channel_tracer_max_nodes, is_top_level_channel); } +ServerNode::ServerNode(size_t channel_tracer_max_nodes) + : BaseNode(EntityType::kServer), trace_(channel_tracer_max_nodes) {} + +ServerNode::~ServerNode() {} + +grpc_json* ServerNode::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, + "serverId", 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; + // fill in the channel trace if applicable + grpc_json* trace_json = trace_.RenderJson(); + if (trace_json != nullptr) { + trace_json->key = "trace"; // this object is named trace in channelz.proto + grpc_json_link_child(json, trace_json, nullptr); + } + // ask CallCountingHelper to populate trace and call count data. + call_counter_.PopulateCallCounts(json); + json = top_level_json; + // template method. Child classes may override this to add their specific + // functionality. + PopulateSockets(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 bd2735929c..9a448d3b38 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -167,12 +167,32 @@ class ChannelNode : public BaseNode { }; // Handles channelz bookkeeping for servers -// TODO(ncteisen): implement in subsequent PR. class ServerNode : public BaseNode { public: - explicit ServerNode(size_t channel_tracer_max_nodes) - : BaseNode(EntityType::kServer) {} - ~ServerNode() override {} + explicit ServerNode(size_t channel_tracer_max_nodes); + ~ServerNode() override; + + grpc_json* RenderJson() override; + + void PopulateSockets(grpc_json* json) {} + + // proxy methods to composed classes. + void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { + trace_.AddTraceEvent(severity, data); + } + void AddTraceEventWithReference(ChannelTrace::Severity severity, + grpc_slice data, + RefCountedPtr referenced_channel) { + trace_.AddTraceEventWithReference(severity, data, + std::move(referenced_channel)); + } + void RecordCallStarted() { call_counter_.RecordCallStarted(); } + void RecordCallFailed() { call_counter_.RecordCallFailed(); } + void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } + + private: + CallCountingHelper call_counter_; + ChannelTrace trace_; }; // Handles channelz bookkeeping for sockets diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index d2c403cc1b..285f641ba9 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -111,6 +111,42 @@ char* ChannelzRegistry::InternalGetTopChannels(intptr_t start_channel_id) { return json_str; } +char* ChannelzRegistry::InternalGetServers(intptr_t start_server_id) { + grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); + grpc_json* json = top_level_json; + grpc_json* json_iterator = nullptr; + InlinedVector servers; + // 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_server_id=0, which signifies "give me everything." + size_t start_idx = start_server_id == 0 ? 0 : start_server_id - 1; + for (size_t i = start_idx; i < entities_.size(); ++i) { + if (entities_[i] != nullptr && + entities_[i]->type() == + grpc_core::channelz::BaseNode::EntityType::kServer) { + servers.push_back(entities_[i]); + } + } + if (!servers.empty()) { + // create list of servers + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "server", nullptr, GRPC_JSON_ARRAY, false); + for (size_t i = 0; i < servers.size(); ++i) { + grpc_json* server_json = servers[i]->RenderJson(); + json_iterator = + grpc_json_link_child(array_parent, server_json, json_iterator); + } + } + // For now we do not have any pagination rules. In the future we could + // pick a constant for max_channels_sent for a GetServers request. + // Tracking: https://github.com/grpc/grpc/issues/16019. + json_iterator = grpc_json_create_child(nullptr, json, "end", nullptr, + GRPC_JSON_TRUE, false); + char* json_str = grpc_json_dump_to_string(top_level_json, 0); + grpc_json_destroy(top_level_json); + return json_str; +} + } // namespace channelz } // namespace grpc_core @@ -119,6 +155,10 @@ char* grpc_channelz_get_top_channels(intptr_t start_channel_id) { start_channel_id); } +char* grpc_channelz_get_servers(intptr_t start_server_id) { + return grpc_core::channelz::ChannelzRegistry::GetServers(start_server_id); +} + char* grpc_channelz_get_channel(intptr_t channel_id) { grpc_core::channelz::BaseNode* channel_node = grpc_core::channelz::ChannelzRegistry::Get(channel_id); diff --git a/src/core/lib/channel/channelz_registry.h b/src/core/lib/channel/channelz_registry.h index 142c039220..d0d660600d 100644 --- a/src/core/lib/channel/channelz_registry.h +++ b/src/core/lib/channel/channelz_registry.h @@ -52,6 +52,12 @@ class ChannelzRegistry { return Default()->InternalGetTopChannels(start_channel_id); } + // Returns the allocated JSON string that represents the proto + // GetServersResponse as per channelz.proto. + static char* GetServers(intptr_t start_server_id) { + return Default()->InternalGetServers(start_server_id); + } + private: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_NEW GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE @@ -74,6 +80,7 @@ class ChannelzRegistry { BaseNode* InternalGet(intptr_t uuid); char* InternalGetTopChannels(intptr_t start_channel_id); + char* InternalGetServers(intptr_t start_server_id); // protects entities_ and uuid_ gpr_mu mu_; diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index d81e33054a..d32281e076 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -48,6 +48,7 @@ #include "src/core/lib/surface/call_test_only.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/completion_queue.h" +#include "src/core/lib/surface/server.h" #include "src/core/lib/surface/validate_metadata.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/metadata.h" @@ -166,6 +167,8 @@ struct grpc_call { grpc_completion_queue* cq; grpc_polling_entity pollent; grpc_channel* channel; + // backpointer to owning server if this is a server side call. + grpc_server* server; gpr_timespec start_time; /* parent_call* */ gpr_atm parent_call_atm; child_call* child; @@ -362,14 +365,11 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, /* Always support no compression */ GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_MESSAGE_COMPRESS_NONE); call->is_client = args->server_transport_data == nullptr; - if (call->is_client) { - GRPC_STATS_INC_CLIENT_CALLS_CREATED(); - } else { - GRPC_STATS_INC_SERVER_CALLS_CREATED(); - } call->stream_op_payload.context = call->context; grpc_slice path = grpc_empty_slice(); if (call->is_client) { + GRPC_STATS_INC_CLIENT_CALLS_CREATED(); + call->server = nullptr; GPR_ASSERT(args->add_initial_metadata_count < MAX_SEND_EXTRA_METADATA_COUNT); for (i = 0; i < args->add_initial_metadata_count; i++) { @@ -383,6 +383,8 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, call->send_extra_metadata_count = static_cast(args->add_initial_metadata_count); } else { + GRPC_STATS_INC_SERVER_CALLS_CREATED(); + call->server = args->server; GPR_ASSERT(args->add_initial_metadata_count == 0); call->send_extra_metadata_count = 0; } @@ -486,10 +488,18 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, &call->pollent); } - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(call->channel); - if (channelz_channel != nullptr) { - channelz_channel->RecordCallStarted(); + if (call->is_client) { + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(call->channel); + if (channelz_channel != nullptr) { + channelz_channel->RecordCallStarted(); + } + } else { + grpc_core::channelz::ServerNode* channelz_server = + grpc_server_get_channelz_node(call->server); + if (channelz_server != nullptr) { + channelz_server->RecordCallStarted(); + } } grpc_slice_unref_internal(path); @@ -1263,18 +1273,26 @@ static void post_batch_completion(batch_control* bctl) { call->final_op.client.status, call->final_op.client.status_details, call->final_op.client.error_string); + grpc_core::channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(call->channel); + if (channelz_channel != nullptr) { + if (*call->final_op.client.status != GRPC_STATUS_OK) { + channelz_channel->RecordCallFailed(); + } else { + channelz_channel->RecordCallSucceeded(); + } + } } else { get_final_status(call, set_cancelled_value, call->final_op.server.cancelled, nullptr, nullptr); - } - // Record channelz data for the channel. - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(call->channel); - if (channelz_channel != nullptr) { - if (*call->final_op.client.status != GRPC_STATUS_OK) { - channelz_channel->RecordCallFailed(); - } else { - channelz_channel->RecordCallSucceeded(); + grpc_core::channelz::ServerNode* channelz_server = + grpc_server_get_channelz_node(call->server); + if (channelz_server != nullptr) { + if (*call->final_op.server.cancelled) { + channelz_server->RecordCallFailed(); + } else { + channelz_server->RecordCallSucceeded(); + } } } GRPC_ERROR_UNREF(error); diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h index b3b06059d4..b34260505a 100644 --- a/src/core/lib/surface/call.h +++ b/src/core/lib/surface/call.h @@ -33,6 +33,7 @@ typedef void (*grpc_ioreq_completion_func)(grpc_call* call, int success, typedef struct grpc_call_create_args { grpc_channel* channel; + grpc_server* server; grpc_call* parent; uint32_t propagation_mask; diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 10d90e1406..815d302577 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -166,10 +166,11 @@ grpc_channel* grpc_channel_create_with_builder( } grpc_channel_args_destroy(args); - if (channelz_enabled) { - bool is_top_level_channel = channel->is_client && !internal_channel; + // only track client channels since server channels are held in the + // grpc_server channel. + if (channelz_enabled && channel->is_client) { channel->channelz_channel = channel_node_create_func( - channel, channel_tracer_max_nodes, is_top_level_channel); + channel, channel_tracer_max_nodes, !internal_channel); channel->channelz_channel->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel created")); diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index cb34def740..8e9d8ec98c 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -219,6 +219,8 @@ struct grpc_server { /** when did we print the last shutdown progress message */ gpr_timespec last_shutdown_message_time; + + grpc_core::RefCountedPtr channelz_server; }; #define SERVER_FROM_CALL_ELEM(elem) \ @@ -364,6 +366,7 @@ static void server_ref(grpc_server* server) { static void server_delete(grpc_server* server) { registered_method* rm; size_t i; + server->channelz_server.reset(); grpc_channel_args_destroy(server->channel_args); gpr_mu_destroy(&server->mu_global); gpr_mu_destroy(&server->mu_call); @@ -779,6 +782,7 @@ static void accept_stream(void* cd, grpc_transport* transport, args.channel = chand->channel; args.server_transport_data = transport_server_data; args.send_deadline = GRPC_MILLIS_INF_FUTURE; + args.server = chand->server; grpc_call* call; grpc_error* error = grpc_call_create(&args, &call); grpc_call_element* elem = @@ -941,6 +945,7 @@ void grpc_server_register_completion_queue(grpc_server* server, } grpc_server* grpc_server_create(const grpc_channel_args* args, void* reserved) { + grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_server_create(%p, %p)", 2, (args, reserved)); grpc_server* server = @@ -957,6 +962,20 @@ grpc_server* grpc_server_create(const grpc_channel_args* args, void* reserved) { server->channel_args = grpc_channel_args_copy(args); + const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_ENABLE_CHANNELZ); + if (grpc_channel_arg_get_bool(arg, false)) { + arg = grpc_channel_args_find(args, + GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE); + size_t trace_events_per_node = + grpc_channel_arg_get_integer(arg, {0, 0, INT_MAX}); + server->channelz_server = + grpc_core::MakeRefCounted( + trace_events_per_node); + server->channelz_server->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Server created")); + } + return server; } @@ -1459,3 +1478,8 @@ int grpc_server_has_open_connections(grpc_server* server) { gpr_mu_unlock(&server->mu_global); return r; } + +grpc_core::channelz::ServerNode* grpc_server_get_channelz_node( + grpc_server* server) { + return server->channelz_server.get(); +} diff --git a/src/core/lib/surface/server.h b/src/core/lib/surface/server.h index c617cc223e..0196743ff9 100644 --- a/src/core/lib/surface/server.h +++ b/src/core/lib/surface/server.h @@ -23,6 +23,7 @@ #include #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/transport/transport.h" @@ -46,6 +47,9 @@ void grpc_server_setup_transport(grpc_server* server, grpc_transport* transport, grpc_pollset* accepting_pollset, const grpc_channel_args* args); +grpc_core::channelz::ServerNode* grpc_server_get_channelz_node( + grpc_server* server); + const grpc_channel_args* grpc_server_get_channel_args(grpc_server* server); int grpc_server_has_open_connections(grpc_server* server); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index 8fa46a18da..f947617d0f 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -31,6 +31,7 @@ #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/json/json.h" #include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.h" #include "test/core/util/test_config.h" #include "test/cpp/util/channel_trace_proto_helper.h" @@ -102,6 +103,25 @@ void ValidateGetTopChannels(size_t expected_channels) { gpr_free(core_api_json_str); } +void ValidateGetServers(size_t expected_servers) { + char* json_str = ChannelzRegistry::GetServers(0); + grpc::testing::ValidateGetServersResponseProtoJsonTranslation(json_str); + grpc_json* parsed_json = grpc_json_parse_string(json_str); + // This check will naturally have to change when we support pagination. + // tracked: https://github.com/grpc/grpc/issues/16019. + ValidateJsonArraySize(parsed_json, "server", expected_servers); + grpc_json* end = GetJsonChild(parsed_json, "end"); + ASSERT_NE(end, nullptr); + EXPECT_EQ(end->type, GRPC_JSON_TRUE); + grpc_json_destroy(parsed_json); + gpr_free(json_str); + // also check that the core API formats this correctly + char* core_api_json_str = grpc_channelz_get_servers(0); + grpc::testing::ValidateGetServersResponseProtoJsonTranslation( + core_api_json_str); + gpr_free(core_api_json_str); +} + class ChannelFixture { public: ChannelFixture(int max_trace_nodes = 0) { @@ -124,6 +144,27 @@ class ChannelFixture { grpc_channel* channel_; }; +class ServerFixture { + public: + ServerFixture(int max_trace_nodes = 0) { + grpc_arg server_a[2]; + server_a[0] = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE), + max_trace_nodes); + server_a[1] = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_CHANNELZ), true); + grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; + server_ = grpc_server_create(&server_args, nullptr); + } + + ~ServerFixture() { grpc_server_destroy(server_); } + + grpc_server* server() { return server_; } + + private: + grpc_server* server_; +}; + struct validate_channel_data_args { int64_t calls_started; int64_t calls_failed; @@ -163,6 +204,13 @@ void ValidateChannel(ChannelNode* channel, validate_channel_data_args args) { gpr_free(core_api_json_str); } +void ValidateServer(ServerNode* server, validate_channel_data_args args) { + char* json_str = server->RenderJsonString(); + grpc::testing::ValidateServerProtoJsonTranslation(json_str); + ValidateCounters(json_str, args); + gpr_free(json_str); +} + grpc_millis GetLastCallStartedMillis(CallCountingHelper* channel) { CallCountingHelperPeer peer(channel); return peer.last_call_started_millis(); @@ -237,7 +285,7 @@ TEST_P(ChannelzChannelTest, LastCallStartedMillis) { EXPECT_NE(millis1, millis4); } -TEST(ChannelzGetTopChannelsTest, BasicTest) { +TEST(ChannelzGetTopChannelsTest, BasicGetTopChannelsTest) { grpc_core::ExecCtx exec_ctx; ChannelFixture channel; ValidateGetTopChannels(1); @@ -273,9 +321,49 @@ TEST(ChannelzGetTopChannelsTest, InternalChannelTest) { grpc_channel_destroy(internal_channel); } +class ChannelzServerTest : public ::testing::TestWithParam {}; + +TEST_P(ChannelzServerTest, BasicServerAPIFunctionality) { + grpc_core::ExecCtx exec_ctx; + ServerFixture server(10); + ServerNode* channelz_server = grpc_server_get_channelz_node(server.server()); + channelz_server->RecordCallStarted(); + channelz_server->RecordCallFailed(); + channelz_server->RecordCallSucceeded(); + ValidateServer(channelz_server, {1, 1, 1}); + channelz_server->RecordCallStarted(); + channelz_server->RecordCallFailed(); + channelz_server->RecordCallSucceeded(); + channelz_server->RecordCallStarted(); + channelz_server->RecordCallFailed(); + channelz_server->RecordCallSucceeded(); + ValidateServer(channelz_server, {3, 3, 3}); +} + +TEST(ChannelzGetServersTest, BasicGetServersTest) { + grpc_core::ExecCtx exec_ctx; + ServerFixture server; + ValidateGetServers(1); +} + +TEST(ChannelzGetServersTest, NoServersTest) { + grpc_core::ExecCtx exec_ctx; + ValidateGetServers(0); +} + +TEST(ChannelzGetServersTest, ManyServersTest) { + grpc_core::ExecCtx exec_ctx; + ServerFixture servers[10]; + (void)servers; // suppress unused variable error + ValidateGetServers(10); +} + INSTANTIATE_TEST_CASE_P(ChannelzChannelTestSweep, ChannelzChannelTest, ::testing::Values(0, 1, 2, 6, 10, 15)); +INSTANTIATE_TEST_CASE_P(ChannelzServerTestSweep, ChannelzServerTest, + ::testing::Values(0, 1, 2, 6, 10, 15)); + } // namespace testing } // namespace channelz } // namespace grpc_core diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 533703a2be..f96c430b69 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -22,6 +22,7 @@ #include #include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/server.h" #include #include @@ -198,17 +199,21 @@ static void run_one_request(grpc_end2end_test_config config, static void test_channelz(grpc_end2end_test_config config) { grpc_end2end_test_fixture f; - grpc_arg client_a; - client_a.type = GRPC_ARG_INTEGER; - client_a.key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); - client_a.value.integer = true; - grpc_channel_args client_args = {1, &client_a}; + grpc_arg arg; + arg.type = GRPC_ARG_INTEGER; + arg.key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); + arg.value.integer = true; + grpc_channel_args args = {1, &arg}; - f = begin_test(config, "test_channelz", &client_args, nullptr); + f = begin_test(config, "test_channelz", &args, &args); grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(f.client); - GPR_ASSERT(channelz_channel != nullptr); + + grpc_core::channelz::ServerNode* channelz_server = + grpc_server_get_channelz_node(f.server); + GPR_ASSERT(channelz_server != nullptr); + char* json = channelz_channel->RenderJsonString(); GPR_ASSERT(json != nullptr); // nothing is present yet @@ -241,6 +246,18 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); + json = channelz_server->RenderJsonString(); + GPR_ASSERT(json != nullptr); + gpr_log(GPR_INFO, "%s", json); + GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); + GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\"")); + GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); + // channel tracing is not enables, so these should not be preset. + GPR_ASSERT(nullptr == strstr(json, "\"trace\"")); + GPR_ASSERT(nullptr == strstr(json, "\"description\":\"Channel created\"")); + GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); + gpr_free(json); + end_test(&f); config.tear_down_data(&f); } @@ -248,22 +265,24 @@ static void test_channelz(grpc_end2end_test_config config) { static void test_channelz_with_channel_trace(grpc_end2end_test_config config) { grpc_end2end_test_fixture f; - grpc_arg client_a[2]; - client_a[0].type = GRPC_ARG_INTEGER; - client_a[0].key = - const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE); - client_a[0].value.integer = 5; - client_a[1].type = GRPC_ARG_INTEGER; - client_a[1].key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); - client_a[1].value.integer = true; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; - - f = begin_test(config, "test_channelz_with_channel_trace", &client_args, - nullptr); + grpc_arg arg[2]; + arg[0].type = GRPC_ARG_INTEGER; + arg[0].key = const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE); + arg[0].value.integer = 5; + arg[1].type = GRPC_ARG_INTEGER; + arg[1].key = const_cast(GRPC_ARG_ENABLE_CHANNELZ); + arg[1].value.integer = true; + grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; + + f = begin_test(config, "test_channelz_with_channel_trace", &args, &args); grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(f.client); - GPR_ASSERT(channelz_channel != nullptr); + + grpc_core::channelz::ServerNode* channelz_server = + grpc_server_get_channelz_node(f.server); + GPR_ASSERT(channelz_server != nullptr); + char* json = channelz_channel->RenderJsonString(); GPR_ASSERT(json != nullptr); gpr_log(GPR_INFO, "%s", json); @@ -272,6 +291,14 @@ static void test_channelz_with_channel_trace(grpc_end2end_test_config config) { GPR_ASSERT(nullptr != strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); + json = channelz_server->RenderJsonString(); + GPR_ASSERT(json != nullptr); + gpr_log(GPR_INFO, "%s", json); + GPR_ASSERT(nullptr != strstr(json, "\"trace\"")); + GPR_ASSERT(nullptr != strstr(json, "\"description\":\"Server created\"")); + GPR_ASSERT(nullptr != strstr(json, "\"severity\":\"CT_INFO\"")); + gpr_free(json); + end_test(&f); config.tear_down_data(&f); } diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index e416a0375f..42a436d49b 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -86,5 +86,14 @@ void ValidateSubchannelProtoJsonTranslation(char* json_c_str) { VaidateProtoJsonTranslation(json_c_str); } +void ValidateServerProtoJsonTranslation(char* json_c_str) { + VaidateProtoJsonTranslation(json_c_str); +} + +void ValidateGetServersResponseProtoJsonTranslation(char* json_c_str) { + VaidateProtoJsonTranslation( + json_c_str); +} + } // namespace testing } // namespace grpc diff --git a/test/cpp/util/channel_trace_proto_helper.h b/test/cpp/util/channel_trace_proto_helper.h index a1ebbcd110..67c363e89b 100644 --- a/test/cpp/util/channel_trace_proto_helper.h +++ b/test/cpp/util/channel_trace_proto_helper.h @@ -27,6 +27,8 @@ void ValidateChannelProtoJsonTranslation(char* json_c_str); void ValidateGetTopChannelsResponseProtoJsonTranslation(char* json_c_str); void ValidateGetChannelResponseProtoJsonTranslation(char* json_c_str); void ValidateSubchannelProtoJsonTranslation(char* json_c_str); +void ValidateServerProtoJsonTranslation(char* json_c_str); +void ValidateGetServersResponseProtoJsonTranslation(char* json_c_str); } // namespace testing } // namespace grpc -- cgit v1.2.3 From 2f8e60a7737293a3e44f555ac9de92267785e91f Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 21 Aug 2018 11:59:24 -0700 Subject: Set TCP_USER_TIMEOUT socket option --- src/core/lib/iomgr/socket_utils_common_posix.cc | 24 ++++++++++++++++++++++ src/core/lib/iomgr/socket_utils_posix.h | 3 +++ src/core/lib/iomgr/tcp_client_posix.cc | 3 +++ .../lib/iomgr/tcp_server_utils_posix_common.cc | 2 ++ 4 files changed, 32 insertions(+) (limited to 'src/core') diff --git a/src/core/lib/iomgr/socket_utils_common_posix.cc b/src/core/lib/iomgr/socket_utils_common_posix.cc index c4b991c94d..8b8e303ef7 100644 --- a/src/core/lib/iomgr/socket_utils_common_posix.cc +++ b/src/core/lib/iomgr/socket_utils_common_posix.cc @@ -222,6 +222,30 @@ grpc_error* grpc_set_socket_low_latency(int fd, int low_latency) { return GRPC_ERROR_NONE; } +#define DEFAULT_TCP_USER_TIMEOUT 20000 /* 20 seconds */ + +/* Set TCP_USER_TIMEOUT */ +grpc_error* grpc_set_socket_tcp_user_timeout(int fd, int val) { +#ifdef GPR_LINUX + int newval; + socklen_t len; + if (val == 0) { + val = DEFAULT_TCP_USER_TIMEOUT; + } + if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &val, sizeof(val))) { + return GRPC_OS_ERROR(errno, "setsockopt(TCP_USER_TIMEOUT)"); + } + if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) { + return GRPC_OS_ERROR(errno, "getsockopt(TCP_USER_TIMEOUT)"); + } + if (newval != val) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Failed to set TCP_USER_TIMEOUT"); + } +#endif /* GPR_LINUX */ + return GRPC_ERROR_NONE; +} + /* set a socket using a grpc_socket_mutator */ grpc_error* grpc_set_socket_with_mutator(int fd, grpc_socket_mutator* mutator) { GPR_ASSERT(mutator); diff --git a/src/core/lib/iomgr/socket_utils_posix.h b/src/core/lib/iomgr/socket_utils_posix.h index b3fd58a530..8550bd1324 100644 --- a/src/core/lib/iomgr/socket_utils_posix.h +++ b/src/core/lib/iomgr/socket_utils_posix.h @@ -53,6 +53,9 @@ grpc_error* grpc_set_socket_low_latency(int fd, int low_latency); /* set SO_REUSEPORT */ grpc_error* grpc_set_socket_reuse_port(int fd, int reuse); +/* Set TCP_USER_TIMEOUT to val, or the default value if val is 0. */ +grpc_error* grpc_set_socket_tcp_user_timeout(int fd, int val); + /* Returns true if this system can create AF_INET6 sockets bound to ::1. The value is probed once, and cached for the life of the process. diff --git a/src/core/lib/iomgr/tcp_client_posix.cc b/src/core/lib/iomgr/tcp_client_posix.cc index 296ee74311..518b0b2b3b 100644 --- a/src/core/lib/iomgr/tcp_client_posix.cc +++ b/src/core/lib/iomgr/tcp_client_posix.cc @@ -76,8 +76,11 @@ static grpc_error* prepare_socket(const grpc_resolved_address* addr, int fd, if (!grpc_is_unix_socket(addr)) { err = grpc_set_socket_low_latency(fd, 1); if (err != GRPC_ERROR_NONE) goto error; + err = grpc_set_socket_tcp_user_timeout(fd, 0 /* set to gRPC default */); + if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_no_sigpipe_if_possible(fd); + if (err != GRPC_ERROR_NONE) goto error; if (channel_args) { for (size_t i = 0; i < channel_args->num_args; i++) { diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc index b9f8145572..2cb28f2e03 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc @@ -166,6 +166,8 @@ grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server* s, int fd, if (err != GRPC_ERROR_NONE) goto error; err = grpc_set_socket_reuse_addr(fd, 1); if (err != GRPC_ERROR_NONE) goto error; + err = grpc_set_socket_tcp_user_timeout(fd, 0); + if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_no_sigpipe_if_possible(fd); if (err != GRPC_ERROR_NONE) goto error; -- cgit v1.2.3 From ecee4ac703e909b4edd789e137e3b0b736dfe37a Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 21 Aug 2018 17:07:33 -0700 Subject: Use linux kernel version 2.6.37 to decide whether to use TCP_USER_TIMEOUT or not --- src/core/lib/iomgr/port.h | 6 ++++++ src/core/lib/iomgr/socket_utils_common_posix.cc | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index 066417b93c..bc58ed13c0 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -77,6 +77,12 @@ #define GRPC_LINUX_SOCKETUTILS 1 #endif #endif +#include +#ifdef LINUX_VERSION_CODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) +#define GRPC_HAVE_TCP_USER_TIMEOUT +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) */ +#endif /* LINUX_VERSION_CODE */ #ifndef __GLIBC__ #define GRPC_LINUX_EPOLL 1 #define GRPC_LINUX_EPOLL_CREATE1 1 diff --git a/src/core/lib/iomgr/socket_utils_common_posix.cc b/src/core/lib/iomgr/socket_utils_common_posix.cc index 8b8e303ef7..5dc8fcb427 100644 --- a/src/core/lib/iomgr/socket_utils_common_posix.cc +++ b/src/core/lib/iomgr/socket_utils_common_posix.cc @@ -226,7 +226,7 @@ grpc_error* grpc_set_socket_low_latency(int fd, int low_latency) { /* Set TCP_USER_TIMEOUT */ grpc_error* grpc_set_socket_tcp_user_timeout(int fd, int val) { -#ifdef GPR_LINUX +#ifdef GRPC_HAVE_TCP_USER_TIMEOUT int newval; socklen_t len; if (val == 0) { @@ -242,7 +242,7 @@ grpc_error* grpc_set_socket_tcp_user_timeout(int fd, int val) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Failed to set TCP_USER_TIMEOUT"); } -#endif /* GPR_LINUX */ +#endif /* GRPC_HAVE_TCP_USER_TIMEOUT */ return GRPC_ERROR_NONE; } -- cgit v1.2.3 From dfe377eddc38faae3e4f604c7e27cec0c9a7d31c Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 21 Aug 2018 17:16:28 -0700 Subject: Did not initialize len earlier --- src/core/lib/iomgr/socket_utils_common_posix.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/lib/iomgr/socket_utils_common_posix.cc b/src/core/lib/iomgr/socket_utils_common_posix.cc index 5dc8fcb427..9b32089a92 100644 --- a/src/core/lib/iomgr/socket_utils_common_posix.cc +++ b/src/core/lib/iomgr/socket_utils_common_posix.cc @@ -228,7 +228,7 @@ grpc_error* grpc_set_socket_low_latency(int fd, int low_latency) { grpc_error* grpc_set_socket_tcp_user_timeout(int fd, int val) { #ifdef GRPC_HAVE_TCP_USER_TIMEOUT int newval; - socklen_t len; + socklen_t len = sizeof(newval); if (val == 0) { val = DEFAULT_TCP_USER_TIMEOUT; } -- cgit v1.2.3 From 2c37c51dd9518b74444ed2c93f521849169f7694 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 22 Aug 2018 10:19:43 -0700 Subject: Add logging for tcp_user_timeout not supported --- src/core/lib/iomgr/socket_utils_common_posix.cc | 2 ++ src/core/lib/iomgr/tcp_server_utils_posix_common.cc | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/lib/iomgr/socket_utils_common_posix.cc b/src/core/lib/iomgr/socket_utils_common_posix.cc index 9b32089a92..b7fc833608 100644 --- a/src/core/lib/iomgr/socket_utils_common_posix.cc +++ b/src/core/lib/iomgr/socket_utils_common_posix.cc @@ -242,6 +242,8 @@ grpc_error* grpc_set_socket_tcp_user_timeout(int fd, int val) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Failed to set TCP_USER_TIMEOUT"); } +#else + gpr_log(GPR_INFO, "TCP_USER_TIMEOUT not supported for this platform"); #endif /* GRPC_HAVE_TCP_USER_TIMEOUT */ return GRPC_ERROR_NONE; } diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc index 2cb28f2e03..20b9037c68 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc @@ -166,7 +166,7 @@ grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server* s, int fd, if (err != GRPC_ERROR_NONE) goto error; err = grpc_set_socket_reuse_addr(fd, 1); if (err != GRPC_ERROR_NONE) goto error; - err = grpc_set_socket_tcp_user_timeout(fd, 0); + err = grpc_set_socket_tcp_user_timeout(fd, 0 /* set to gRPC default */); if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_no_sigpipe_if_possible(fd); -- cgit v1.2.3 From 39e53c13bf1f62fdfe7e05fbfe5427f5ad3b1a90 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 22 Aug 2018 10:20:59 -0700 Subject: remove extra blank line --- src/core/lib/iomgr/tcp_client_posix.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'src/core') diff --git a/src/core/lib/iomgr/tcp_client_posix.cc b/src/core/lib/iomgr/tcp_client_posix.cc index 518b0b2b3b..c2a0892211 100644 --- a/src/core/lib/iomgr/tcp_client_posix.cc +++ b/src/core/lib/iomgr/tcp_client_posix.cc @@ -80,7 +80,6 @@ static grpc_error* prepare_socket(const grpc_resolved_address* addr, int fd, if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_no_sigpipe_if_possible(fd); - if (err != GRPC_ERROR_NONE) goto error; if (channel_args) { for (size_t i = 0; i < channel_args->num_args; i++) { -- cgit v1.2.3 From 7269fd47eb12f9383535c657b855286cd4570d9f Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Thu, 30 Aug 2018 11:37:34 -0700 Subject: Fix ipv6 address parsing issue --- src/core/ext/filters/client_channel/parse_address.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/parse_address.cc b/src/core/ext/filters/client_channel/parse_address.cc index b3900114ad..5eeea1b148 100644 --- a/src/core/ext/filters/client_channel/parse_address.cc +++ b/src/core/ext/filters/client_channel/parse_address.cc @@ -128,6 +128,13 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr, char host_without_scope[GRPC_INET6_ADDRSTRLEN]; size_t host_without_scope_len = static_cast(host_end - host); uint32_t sin6_scope_id = 0; + if (host_without_scope_len > GRPC_INET6_ADDRSTRLEN) { + gpr_log(GPR_ERROR, + "invalid ipv6 address length %d. Length cannot be greater than " + "GRPC_INET6_ADDRSTRLEN i.e %d)", + host_without_scope_len, GRPC_INET6_ADDRSTRLEN); + goto done; + } strncpy(host_without_scope, host, host_without_scope_len); host_without_scope[host_without_scope_len] = '\0'; if (grpc_inet_pton(GRPC_AF_INET6, host_without_scope, &in6->sin6_addr) == -- cgit v1.2.3 From 0a7363ffcbbb578a7dc94f2bcffbe7b8ba78e1d2 Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Thu, 30 Aug 2018 13:13:48 -0700 Subject: Add a test to parse invalid addresses --- src/core/ext/filters/client_channel/parse_address.cc | 2 +- test/core/client_channel/parse_address_test.cc | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/parse_address.cc b/src/core/ext/filters/client_channel/parse_address.cc index 5eeea1b148..c1dc0bc2ce 100644 --- a/src/core/ext/filters/client_channel/parse_address.cc +++ b/src/core/ext/filters/client_channel/parse_address.cc @@ -125,7 +125,7 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr, char* host_end = static_cast(gpr_memrchr(host, '%', strlen(host))); if (host_end != nullptr) { GPR_ASSERT(host_end >= host); - char host_without_scope[GRPC_INET6_ADDRSTRLEN]; + char host_without_scope[GRPC_INET6_ADDRSTRLEN + 1]; size_t host_without_scope_len = static_cast(host_end - host); uint32_t sin6_scope_id = 0; if (host_without_scope_len > GRPC_INET6_ADDRSTRLEN) { diff --git a/test/core/client_channel/parse_address_test.cc b/test/core/client_channel/parse_address_test.cc index ae157fbb8b..798600293b 100644 --- a/test/core/client_channel/parse_address_test.cc +++ b/test/core/client_channel/parse_address_test.cc @@ -91,6 +91,14 @@ static void test_grpc_parse_ipv6(const char* uri_text, const char* host, grpc_uri_destroy(uri); } +/* Test parsing invalid ipv6 addresses (valid uri_text but invalid ipv6 addr) */ +static void test_grpc_parse_ipv6_invalid(const char* uri_text) { + grpc_core::ExecCtx exec_ctx; + grpc_uri* uri = grpc_uri_parse(uri_text, 0); + grpc_resolved_address addr; + GPR_ASSERT(!grpc_parse_ipv6(uri, &addr)); +} + int main(int argc, char** argv) { grpc_test_init(argc, argv); grpc_init(); @@ -100,5 +108,10 @@ int main(int argc, char** argv) { test_grpc_parse_ipv6("ipv6:[2001:db8::1]:12345", "2001:db8::1", 12345, 0); test_grpc_parse_ipv6("ipv6:[2001:db8::1%252]:12345", "2001:db8::1", 12345, 2); - grpc_shutdown(); + /* Address length greater than GRPC_INET6_ADDRSTRLEN */ + test_grpc_parse_ipv6_invalid( + "ipv6:WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW45%" + "v6:45%x$1*"); + + test_grpc_parse grpc_shutdown(); } -- cgit v1.2.3 From 50419a04ae9c1012a4eb6e159fdb225175e99bf6 Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Thu, 30 Aug 2018 13:23:27 -0700 Subject: fix format specifier for size_t and and a typo in test --- src/core/ext/filters/client_channel/parse_address.cc | 2 +- test/core/client_channel/parse_address_test.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/parse_address.cc b/src/core/ext/filters/client_channel/parse_address.cc index c1dc0bc2ce..7e726dd562 100644 --- a/src/core/ext/filters/client_channel/parse_address.cc +++ b/src/core/ext/filters/client_channel/parse_address.cc @@ -130,7 +130,7 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr, uint32_t sin6_scope_id = 0; if (host_without_scope_len > GRPC_INET6_ADDRSTRLEN) { gpr_log(GPR_ERROR, - "invalid ipv6 address length %d. Length cannot be greater than " + "invalid ipv6 address length %zu. Length cannot be greater than " "GRPC_INET6_ADDRSTRLEN i.e %d)", host_without_scope_len, GRPC_INET6_ADDRSTRLEN); goto done; diff --git a/test/core/client_channel/parse_address_test.cc b/test/core/client_channel/parse_address_test.cc index 798600293b..d51c6178f8 100644 --- a/test/core/client_channel/parse_address_test.cc +++ b/test/core/client_channel/parse_address_test.cc @@ -113,5 +113,5 @@ int main(int argc, char** argv) { "ipv6:WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW45%" "v6:45%x$1*"); - test_grpc_parse grpc_shutdown(); + grpc_shutdown(); } -- cgit v1.2.3 From 8bf52535d1008a3f38e70d1387846f0e942761b5 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Tue, 21 Aug 2018 14:32:13 -0700 Subject: Provide a generic client-side unary callback API --- BUILD | 4 + CMakeLists.txt | 57 ++++++++++ Makefile | 64 +++++++++++ build.yaml | 18 +++ gRPC-C++.podspec | 4 + grpc.gyp | 2 + include/grpcpp/channel.h | 5 + include/grpcpp/generic/generic_stub.h | 23 ++++ include/grpcpp/impl/codegen/call.h | 10 +- include/grpcpp/impl/codegen/callback_common.h | 79 +++++++++++++ include/grpcpp/impl/codegen/channel_interface.h | 14 +++ include/grpcpp/impl/codegen/client_callback.h | 92 +++++++++++++++ include/grpcpp/impl/codegen/client_context.h | 4 + include/grpcpp/impl/codegen/completion_queue.h | 3 + include/grpcpp/support/client_callback.h | 24 ++++ src/core/lib/surface/completion_queue.cc | 4 +- src/cpp/client/channel_cc.cc | 41 ++++++- src/cpp/client/generic_stub.cc | 14 ++- src/cpp/common/callback_common.cc | 109 ++++++++++++++++++ src/cpp/server/server_cc.cc | 3 +- src/cpp/server/server_context.cc | 3 + test/cpp/end2end/BUILD | 19 ++++ test/cpp/end2end/client_callback_end2end_test.cc | 126 +++++++++++++++++++++ tools/doxygen/Doxyfile.c++ | 3 + tools/doxygen/Doxyfile.c++.internal | 4 + tools/run_tests/generated/sources_and_headers.json | 26 +++++ tools/run_tests/generated/tests.json | 24 ++++ 27 files changed, 772 insertions(+), 7 deletions(-) create mode 100644 include/grpcpp/impl/codegen/callback_common.h create mode 100644 include/grpcpp/impl/codegen/client_callback.h create mode 100644 include/grpcpp/support/client_callback.h create mode 100644 src/cpp/common/callback_common.cc create mode 100644 test/cpp/end2end/client_callback_end2end_test.cc (limited to 'src/core') diff --git a/BUILD b/BUILD index 925e277cf7..271e57e36c 100644 --- a/BUILD +++ b/BUILD @@ -119,6 +119,7 @@ GRPCXX_SRCS = [ "src/cpp/client/credentials_cc.cc", "src/cpp/client/generic_stub.cc", "src/cpp/common/alarm.cc", + "src/cpp/common/callback_common.cc", "src/cpp/common/channel_arguments.cc", "src/cpp/common/channel_filter.cc", "src/cpp/common/completion_queue_cc.cc", @@ -243,6 +244,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/support/async_unary_call.h", "include/grpcpp/support/byte_buffer.h", "include/grpcpp/support/channel_arguments.h", + "include/grpcpp/support/client_callback.h", "include/grpcpp/support/config.h", "include/grpcpp/support/proto_buffer_reader.h", "include/grpcpp/support/proto_buffer_writer.h", @@ -1979,7 +1981,9 @@ grpc_cc_library( "include/grpcpp/impl/codegen/byte_buffer.h", "include/grpcpp/impl/codegen/call.h", "include/grpcpp/impl/codegen/call_hook.h", + "include/grpcpp/impl/codegen/callback_common.h", "include/grpcpp/impl/codegen/channel_interface.h", + "include/grpcpp/impl/codegen/client_callback.h", "include/grpcpp/impl/codegen/client_context.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index a21bb8b5fa..8679c5b4e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -564,6 +564,7 @@ add_dependencies(buildtests_cxx check_gcp_environment_linux_test) add_dependencies(buildtests_cxx check_gcp_environment_windows_test) add_dependencies(buildtests_cxx chttp2_settings_timeout_test) add_dependencies(buildtests_cxx cli_call_test) +add_dependencies(buildtests_cxx client_callback_end2end_test) add_dependencies(buildtests_cxx client_channel_stress_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx client_crash_test) @@ -2771,6 +2772,7 @@ add_library(grpc++ src/cpp/client/credentials_cc.cc src/cpp/client/generic_stub.cc src/cpp/common/alarm.cc + src/cpp/common/callback_common.cc src/cpp/common/channel_arguments.cc src/cpp/common/channel_filter.cc src/cpp/common/completion_queue_cc.cc @@ -2917,6 +2919,7 @@ foreach(_hdr include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h include/grpcpp/support/channel_arguments.h + include/grpcpp/support/client_callback.h include/grpcpp/support/config.h include/grpcpp/support/proto_buffer_reader.h include/grpcpp/support/proto_buffer_writer.h @@ -3014,7 +3017,9 @@ foreach(_hdr include/grpcpp/impl/codegen/byte_buffer.h include/grpcpp/impl/codegen/call.h include/grpcpp/impl/codegen/call_hook.h + include/grpcpp/impl/codegen/callback_common.h include/grpcpp/impl/codegen/channel_interface.h + include/grpcpp/impl/codegen/client_callback.h include/grpcpp/impl/codegen/client_context.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h @@ -3129,6 +3134,7 @@ add_library(grpc++_cronet src/cpp/client/credentials_cc.cc src/cpp/client/generic_stub.cc src/cpp/common/alarm.cc + src/cpp/common/callback_common.cc src/cpp/common/channel_arguments.cc src/cpp/common/channel_filter.cc src/cpp/common/completion_queue_cc.cc @@ -3486,6 +3492,7 @@ foreach(_hdr include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h include/grpcpp/support/channel_arguments.h + include/grpcpp/support/client_callback.h include/grpcpp/support/config.h include/grpcpp/support/proto_buffer_reader.h include/grpcpp/support/proto_buffer_writer.h @@ -3583,7 +3590,9 @@ foreach(_hdr include/grpcpp/impl/codegen/byte_buffer.h include/grpcpp/impl/codegen/call.h include/grpcpp/impl/codegen/call_hook.h + include/grpcpp/impl/codegen/callback_common.h include/grpcpp/impl/codegen/channel_interface.h + include/grpcpp/impl/codegen/client_callback.h include/grpcpp/impl/codegen/client_context.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h @@ -3993,7 +4002,9 @@ foreach(_hdr include/grpcpp/impl/codegen/byte_buffer.h include/grpcpp/impl/codegen/call.h include/grpcpp/impl/codegen/call_hook.h + include/grpcpp/impl/codegen/callback_common.h include/grpcpp/impl/codegen/channel_interface.h + include/grpcpp/impl/codegen/client_callback.h include/grpcpp/impl/codegen/client_context.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h @@ -4171,7 +4182,9 @@ foreach(_hdr include/grpcpp/impl/codegen/byte_buffer.h include/grpcpp/impl/codegen/call.h include/grpcpp/impl/codegen/call_hook.h + include/grpcpp/impl/codegen/callback_common.h include/grpcpp/impl/codegen/channel_interface.h + include/grpcpp/impl/codegen/client_callback.h include/grpcpp/impl/codegen/client_context.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h @@ -4247,6 +4260,7 @@ add_library(grpc++_unsecure src/cpp/client/credentials_cc.cc src/cpp/client/generic_stub.cc src/cpp/common/alarm.cc + src/cpp/common/callback_common.cc src/cpp/common/channel_arguments.cc src/cpp/common/channel_filter.cc src/cpp/common/completion_queue_cc.cc @@ -4392,6 +4406,7 @@ foreach(_hdr include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h include/grpcpp/support/channel_arguments.h + include/grpcpp/support/client_callback.h include/grpcpp/support/config.h include/grpcpp/support/proto_buffer_reader.h include/grpcpp/support/proto_buffer_writer.h @@ -4489,7 +4504,9 @@ foreach(_hdr include/grpcpp/impl/codegen/byte_buffer.h include/grpcpp/impl/codegen/call.h include/grpcpp/impl/codegen/call_hook.h + include/grpcpp/impl/codegen/callback_common.h include/grpcpp/impl/codegen/channel_interface.h + include/grpcpp/impl/codegen/client_callback.h include/grpcpp/impl/codegen/client_context.h include/grpcpp/impl/codegen/client_unary_call.h include/grpcpp/impl/codegen/completion_queue.h @@ -11297,6 +11314,46 @@ target_link_libraries(cli_call_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +add_executable(client_callback_end2end_test + test/cpp/end2end/client_callback_end2end_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(client_callback_end2end_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(client_callback_end2end_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++_test_util + grpc_test_util + grpc++ + grpc + gpr_test_util + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + add_executable(client_channel_stress_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc diff --git a/Makefile b/Makefile index 96ea890bcb..33ec3d93e7 100644 --- a/Makefile +++ b/Makefile @@ -1160,6 +1160,7 @@ check_gcp_environment_linux_test: $(BINDIR)/$(CONFIG)/check_gcp_environment_linu check_gcp_environment_windows_test: $(BINDIR)/$(CONFIG)/check_gcp_environment_windows_test chttp2_settings_timeout_test: $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test +client_callback_end2end_test: $(BINDIR)/$(CONFIG)/client_callback_end2end_test client_channel_stress_test: $(BINDIR)/$(CONFIG)/client_channel_stress_test client_crash_test: $(BINDIR)/$(CONFIG)/client_crash_test client_crash_test_server: $(BINDIR)/$(CONFIG)/client_crash_test_server @@ -1665,6 +1666,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/check_gcp_environment_windows_test \ $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test \ $(BINDIR)/$(CONFIG)/cli_call_test \ + $(BINDIR)/$(CONFIG)/client_callback_end2end_test \ $(BINDIR)/$(CONFIG)/client_channel_stress_test \ $(BINDIR)/$(CONFIG)/client_crash_test \ $(BINDIR)/$(CONFIG)/client_crash_test_server \ @@ -1845,6 +1847,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/check_gcp_environment_windows_test \ $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test \ $(BINDIR)/$(CONFIG)/cli_call_test \ + $(BINDIR)/$(CONFIG)/client_callback_end2end_test \ $(BINDIR)/$(CONFIG)/client_channel_stress_test \ $(BINDIR)/$(CONFIG)/client_crash_test \ $(BINDIR)/$(CONFIG)/client_crash_test_server \ @@ -2302,6 +2305,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test || ( echo test chttp2_settings_timeout_test failed ; exit 1 ) $(E) "[RUN] Testing cli_call_test" $(Q) $(BINDIR)/$(CONFIG)/cli_call_test || ( echo test cli_call_test failed ; exit 1 ) + $(E) "[RUN] Testing client_callback_end2end_test" + $(Q) $(BINDIR)/$(CONFIG)/client_callback_end2end_test || ( echo test client_callback_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing client_channel_stress_test" $(Q) $(BINDIR)/$(CONFIG)/client_channel_stress_test || ( echo test client_channel_stress_test failed ; exit 1 ) $(E) "[RUN] Testing client_crash_test" @@ -5219,6 +5224,7 @@ LIBGRPC++_SRC = \ src/cpp/client/credentials_cc.cc \ src/cpp/client/generic_stub.cc \ src/cpp/common/alarm.cc \ + src/cpp/common/callback_common.cc \ src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_filter.cc \ src/cpp/common/completion_queue_cc.cc \ @@ -5329,6 +5335,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ + include/grpcpp/support/client_callback.h \ include/grpcpp/support/config.h \ include/grpcpp/support/proto_buffer_reader.h \ include/grpcpp/support/proto_buffer_writer.h \ @@ -5426,7 +5433,9 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ + include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ + include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -5585,6 +5594,7 @@ LIBGRPC++_CRONET_SRC = \ src/cpp/client/credentials_cc.cc \ src/cpp/client/generic_stub.cc \ src/cpp/common/alarm.cc \ + src/cpp/common/callback_common.cc \ src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_filter.cc \ src/cpp/common/completion_queue_cc.cc \ @@ -5905,6 +5915,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ + include/grpcpp/support/client_callback.h \ include/grpcpp/support/config.h \ include/grpcpp/support/proto_buffer_reader.h \ include/grpcpp/support/proto_buffer_writer.h \ @@ -6002,7 +6013,9 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ + include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ + include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -6392,7 +6405,9 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ + include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ + include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -6546,7 +6561,9 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ + include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ + include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -6661,6 +6678,7 @@ LIBGRPC++_UNSECURE_SRC = \ src/cpp/client/credentials_cc.cc \ src/cpp/client/generic_stub.cc \ src/cpp/common/alarm.cc \ + src/cpp/common/callback_common.cc \ src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_filter.cc \ src/cpp/common/completion_queue_cc.cc \ @@ -6771,6 +6789,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ + include/grpcpp/support/client_callback.h \ include/grpcpp/support/config.h \ include/grpcpp/support/proto_buffer_reader.h \ include/grpcpp/support/proto_buffer_writer.h \ @@ -6868,7 +6887,9 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ + include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ + include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -17076,6 +17097,49 @@ endif endif +CLIENT_CALLBACK_END2END_TEST_SRC = \ + test/cpp/end2end/client_callback_end2end_test.cc \ + +CLIENT_CALLBACK_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLIENT_CALLBACK_END2END_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/client_callback_end2end_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/client_callback_end2end_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/client_callback_end2end_test: $(PROTOBUF_DEP) $(CLIENT_CALLBACK_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(CLIENT_CALLBACK_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/client_callback_end2end_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/cpp/end2end/client_callback_end2end_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_client_callback_end2end_test: $(CLIENT_CALLBACK_END2END_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CLIENT_CALLBACK_END2END_TEST_OBJS:.o=.dep) +endif +endif + + CLIENT_CHANNEL_STRESS_TEST_SRC = \ $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc \ test/cpp/client/client_channel_stress_test.cc \ diff --git a/build.yaml b/build.yaml index a50a0a4ab6..b775773e42 100644 --- a/build.yaml +++ b/build.yaml @@ -1169,7 +1169,9 @@ filegroups: - include/grpcpp/impl/codegen/byte_buffer.h - include/grpcpp/impl/codegen/call.h - include/grpcpp/impl/codegen/call_hook.h + - include/grpcpp/impl/codegen/callback_common.h - include/grpcpp/impl/codegen/channel_interface.h + - include/grpcpp/impl/codegen/client_callback.h - include/grpcpp/impl/codegen/client_context.h - include/grpcpp/impl/codegen/client_unary_call.h - include/grpcpp/impl/codegen/completion_queue.h @@ -1297,6 +1299,7 @@ filegroups: - include/grpcpp/support/async_unary_call.h - include/grpcpp/support/byte_buffer.h - include/grpcpp/support/channel_arguments.h + - include/grpcpp/support/client_callback.h - include/grpcpp/support/config.h - include/grpcpp/support/proto_buffer_reader.h - include/grpcpp/support/proto_buffer_writer.h @@ -1324,6 +1327,7 @@ filegroups: - src/cpp/client/credentials_cc.cc - src/cpp/client/generic_stub.cc - src/cpp/common/alarm.cc + - src/cpp/common/callback_common.cc - src/cpp/common/channel_arguments.cc - src/cpp/common/channel_filter.cc - src/cpp/common/completion_queue_cc.cc @@ -4465,6 +4469,20 @@ targets: - grpc - gpr_test_util - gpr +- name: client_callback_end2end_test + gtest: true + cpu_cost: 0.5 + build: test + language: c++ + src: + - test/cpp/end2end/client_callback_end2end_test.cc + deps: + - grpc++_test_util + - grpc_test_util + - grpc++ + - grpc + - gpr_test_util + - gpr - name: client_channel_stress_test gtest: false build: test diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 581b9246bc..03ec223279 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -111,6 +111,7 @@ Pod::Spec.new do |s| 'include/grpcpp/support/async_unary_call.h', 'include/grpcpp/support/byte_buffer.h', 'include/grpcpp/support/channel_arguments.h', + 'include/grpcpp/support/client_callback.h', 'include/grpcpp/support/config.h', 'include/grpcpp/support/proto_buffer_reader.h', 'include/grpcpp/support/proto_buffer_writer.h', @@ -127,7 +128,9 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/codegen/byte_buffer.h', 'include/grpcpp/impl/codegen/call.h', 'include/grpcpp/impl/codegen/call_hook.h', + 'include/grpcpp/impl/codegen/callback_common.h', 'include/grpcpp/impl/codegen/channel_interface.h', + 'include/grpcpp/impl/codegen/client_callback.h', 'include/grpcpp/impl/codegen/client_context.h', 'include/grpcpp/impl/codegen/client_unary_call.h', 'include/grpcpp/impl/codegen/completion_queue.h', @@ -187,6 +190,7 @@ Pod::Spec.new do |s| 'src/cpp/client/credentials_cc.cc', 'src/cpp/client/generic_stub.cc', 'src/cpp/common/alarm.cc', + 'src/cpp/common/callback_common.cc', 'src/cpp/common/channel_arguments.cc', 'src/cpp/common/channel_filter.cc', 'src/cpp/common/completion_queue_cc.cc', diff --git a/grpc.gyp b/grpc.gyp index 654a531092..b8aae44de3 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -1381,6 +1381,7 @@ 'src/cpp/client/credentials_cc.cc', 'src/cpp/client/generic_stub.cc', 'src/cpp/common/alarm.cc', + 'src/cpp/common/callback_common.cc', 'src/cpp/common/channel_arguments.cc', 'src/cpp/common/channel_filter.cc', 'src/cpp/common/completion_queue_cc.cc', @@ -1528,6 +1529,7 @@ 'src/cpp/client/credentials_cc.cc', 'src/cpp/client/generic_stub.cc', 'src/cpp/common/alarm.cc', + 'src/cpp/common/callback_common.cc', 'src/cpp/common/channel_arguments.cc', 'src/cpp/common/channel_filter.cc', 'src/cpp/common/completion_queue_cc.cc', diff --git a/include/grpcpp/channel.h b/include/grpcpp/channel.h index fed02bf7bc..58a6f51664 100644 --- a/include/grpcpp/channel.h +++ b/include/grpcpp/channel.h @@ -78,8 +78,13 @@ class Channel final : public ChannelInterface, bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) override; + CompletionQueue* CallbackCQ() override; + const grpc::string host_; grpc_channel* const c_channel_; // owned + + CompletionQueue* callback_cq_ = nullptr; + std::mutex mu_; }; } // namespace grpc diff --git a/include/grpcpp/generic/generic_stub.h b/include/grpcpp/generic/generic_stub.h index 92405a43fa..d509d9a520 100644 --- a/include/grpcpp/generic/generic_stub.h +++ b/include/grpcpp/generic/generic_stub.h @@ -19,9 +19,12 @@ #ifndef GRPCPP_GENERIC_GENERIC_STUB_H #define GRPCPP_GENERIC_GENERIC_STUB_H +#include + #include #include #include +#include namespace grpc { @@ -62,6 +65,26 @@ class GenericStub final { ClientContext* context, const grpc::string& method, CompletionQueue* cq, void* tag); + /// NOTE: class experimental_type is not part of the public API of this class + /// TODO(vjpai): Move these contents to the public API of GenericStub when + /// they are no longer experimental + class experimental_type { + public: + explicit experimental_type(GenericStub* stub) : stub_(stub) {} + + void UnaryCall(ClientContext* context, const grpc::string& method, + const ByteBuffer* request, ByteBuffer* response, + std::function on_completion); + + private: + GenericStub* stub_; + }; + + /// NOTE: The function experimental() is not stable public API. It is a view + /// to the experimental components of this class. It may be changed or removed + /// at any time. + experimental_type experimental() { return experimental_type(this); } + private: std::shared_ptr channel_; }; diff --git a/include/grpcpp/impl/codegen/call.h b/include/grpcpp/impl/codegen/call.h index a5e930aaa5..7bd03b6b1b 100644 --- a/include/grpcpp/impl/codegen/call.h +++ b/include/grpcpp/impl/codegen/call.h @@ -608,6 +608,9 @@ class CallOpSetInterface : public CompletionQueueTag { /// Fills in grpc_op, starting from ops[*nops] and moving /// upwards. virtual void FillOps(grpc_call* call, grpc_op* ops, size_t* nops) = 0; + + /// Get the tag to be used at the CQ + virtual void* cq_tag() = 0; }; /// Primary implementation of CallOpSetInterface. @@ -627,7 +630,7 @@ class CallOpSet : public CallOpSetInterface, public Op5, public Op6 { public: - CallOpSet() : return_tag_(this), call_(nullptr) {} + CallOpSet() : cq_tag_(this), return_tag_(this), call_(nullptr) {} void FillOps(grpc_call* call, grpc_op* ops, size_t* nops) override { this->Op1::AddOp(ops, nops); this->Op2::AddOp(ops, nops); @@ -654,7 +657,12 @@ class CallOpSet : public CallOpSetInterface, void set_output_tag(void* return_tag) { return_tag_ = return_tag; } + void* cq_tag() override { return cq_tag_; } + + void set_cq_tag(void* cq_tag) { cq_tag_ = cq_tag; } + private: + void* cq_tag_; void* return_tag_; grpc_call* call_; }; diff --git a/include/grpcpp/impl/codegen/callback_common.h b/include/grpcpp/impl/codegen/callback_common.h new file mode 100644 index 0000000000..5e1530a310 --- /dev/null +++ b/include/grpcpp/impl/codegen/callback_common.h @@ -0,0 +1,79 @@ +/* + * + * 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 GRPCPP_IMPL_CODEGEN_CALLBACK_COMMON_H +#define GRPCPP_IMPL_CODEGEN_CALLBACK_COMMON_H + +#include + +#include +#include +#include +#include +#include + +// Forward declarations +namespace grpc_core { +class CQCallbackInterface; +}; + +namespace grpc { +namespace internal { + +class CallbackWithStatusTag { + public: + // TODO(vjpai): make impl and ops part of this structure to avoid allocation, + // ownership transfer, and delete + CallbackWithStatusTag(std::function f, bool self_delete, + CompletionQueueTag* ops); + ~CallbackWithStatusTag() { delete ops_; } + void* tag() { return static_cast(impl_); } + Status* status_ptr() { return status_; } + CompletionQueueTag* ops() { return ops_; } + + // force_run can only be performed on a tag before it can ever be active + void force_run(Status s); + + private: + grpc_core::CQCallbackInterface* impl_; + Status* status_; + CompletionQueueTag* ops_; +}; + +class CallbackWithSuccessTag { + public: + // TODO(vjpai): make impl and ops part of this structure to avoid allocation, + // ownership transfer, and delete + CallbackWithSuccessTag(std::function f, bool self_delete, + CompletionQueueTag* ops); + ~CallbackWithSuccessTag() { delete ops_; } + void* tag() { return static_cast(impl_); } + CompletionQueueTag* ops() { return ops_; } + + // force_run can only be performed on a tag before it can ever be active + void force_run(bool ok); + + private: + grpc_core::CQCallbackInterface* impl_; + CompletionQueueTag* ops_; +}; + +} // namespace internal +} // namespace grpc + +#endif // GRPCPP_IMPL_CODEGEN_CLIENT_CALLBACK_H diff --git a/include/grpcpp/impl/codegen/channel_interface.h b/include/grpcpp/impl/codegen/channel_interface.h index ec1c6c25d8..b257acc1ab 100644 --- a/include/grpcpp/impl/codegen/channel_interface.h +++ b/include/grpcpp/impl/codegen/channel_interface.h @@ -41,6 +41,8 @@ class CallOpSetInterface; class RpcMethod; template class BlockingUnaryCallImpl; +template +class CallbackUnaryCallImpl; template class ClientAsyncReaderFactory; template @@ -103,6 +105,8 @@ class ChannelInterface { friend class ::grpc::internal::ClientAsyncResponseReaderFactory; template friend class ::grpc::internal::BlockingUnaryCallImpl; + template + friend class ::grpc::internal::CallbackUnaryCallImpl; friend class ::grpc::internal::RpcMethod; virtual internal::Call CreateCall(const internal::RpcMethod& method, ClientContext* context, @@ -115,6 +119,16 @@ class ChannelInterface { CompletionQueue* cq, void* tag) = 0; virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed, gpr_timespec deadline) = 0; + + // EXPERIMENTAL + // A method to get the callbackable completion queue associated with this + // channel. If the return value is nullptr, this channel doesn't support + // callback operations. + // TODO(vjpai): Consider a better default like using a global CQ + // Returns nullptr (rather than being pure) since this is a new method + // and adding a new pure method to an interface would be a breaking change + // (even though this is private and non-API) + virtual CompletionQueue* CallbackCQ() { return nullptr; } }; } // namespace grpc diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h new file mode 100644 index 0000000000..419933f85c --- /dev/null +++ b/include/grpcpp/impl/codegen/client_callback.h @@ -0,0 +1,92 @@ +/* + * + * 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 GRPCPP_IMPL_CODEGEN_CLIENT_CALLBACK_H +#define GRPCPP_IMPL_CODEGEN_CLIENT_CALLBACK_H + +#include + +#include +#include +#include +#include +#include +#include + +namespace grpc { + +class Channel; +class ClientContext; +class CompletionQueue; + +namespace internal { +class RpcMethod; + +/// Perform a callback-based unary call +/// TODO(vjpai): Combine as much as possible with the blocking unary call code +template +void CallbackUnaryCall(ChannelInterface* channel, const RpcMethod& method, + ClientContext* context, const InputMessage* request, + OutputMessage* result, + std::function on_completion) { + CallbackUnaryCallImpl x( + channel, method, context, request, result, on_completion); +} + +template +class CallbackUnaryCallImpl { + public: + CallbackUnaryCallImpl(ChannelInterface* channel, const RpcMethod& method, + ClientContext* context, const InputMessage* request, + OutputMessage* result, + std::function on_completion) { + CompletionQueue* cq = channel->CallbackCQ(); + GPR_CODEGEN_ASSERT(cq != nullptr); + + // TODO(vjpai): Allocate this as part of the tag's arena + auto* ops = new CallOpSet, + CallOpClientSendClose, CallOpClientRecvStatus>; + + // TODO(vjpai): Move to using pre-allocated tags rather than new/self-delete + auto* tag = new CallbackWithStatusTag(on_completion, true, ops); + + // TODO(vjpai): Unify code with sync API as much as possible + Call call(channel->CreateCall(method, context, cq)); + Status s = ops->SendMessage(*request); + if (!s.ok()) { + tag->force_run(s); + return; + } + ops->SendInitialMetadata(context->send_initial_metadata_, + context->initial_metadata_flags()); + ops->RecvInitialMetadata(context); + ops->RecvMessage(result); + ops->AllowNoMessage(); + ops->ClientSendClose(); + ops->ClientRecvStatus(context, tag->status_ptr()); + ops->set_cq_tag(tag->tag()); + call.PerformOps(ops); + } +}; + +} // namespace internal +} // namespace grpc + +#endif // GRPCPP_IMPL_CODEGEN_CLIENT_CALLBACK_H diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index 9dda4c7fac..7db31fcbcf 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -68,6 +68,8 @@ class CallOpClientRecvStatus; class CallOpRecvInitialMetadata; template class BlockingUnaryCallImpl; +template +class CallbackUnaryCallImpl; } // namespace internal template @@ -389,6 +391,8 @@ class ClientContext { friend class ::grpc::ClientAsyncResponseReader; template friend class ::grpc::internal::BlockingUnaryCallImpl; + template + friend class ::grpc::internal::CallbackUnaryCallImpl; // Used by friend class CallOpClientRecvStatus void set_debug_error_string(const grpc::string& debug_error_string) { diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index 3f7d4fb765..f52f9a53be 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -274,6 +274,9 @@ class CompletionQueue : private GrpcLibraryCodegen { template friend class ::grpc::internal::BlockingUnaryCallImpl; + // Friends that need access to constructor for callback CQ + friend class ::grpc::Channel; + /// EXPERIMENTAL /// Creates a Thread Local cache to store the first event /// On this completion queue queued from this thread. Once diff --git a/include/grpcpp/support/client_callback.h b/include/grpcpp/support/client_callback.h new file mode 100644 index 0000000000..03a7e1400c --- /dev/null +++ b/include/grpcpp/support/client_callback.h @@ -0,0 +1,24 @@ +/* + * + * Copyright 2015 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 GRPCPP_SUPPORT_CLIENT_CALLBACK_H +#define GRPCPP_SUPPORT_CLIENT_CALLBACK_H + +#include + +#endif // GRPCPP_SUPPORT_CLIENT_CALLBACK_H diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc index 0769d9e4f6..c2cf450e94 100644 --- a/src/core/lib/surface/completion_queue.cc +++ b/src/core/lib/surface/completion_queue.cc @@ -1364,9 +1364,11 @@ static void cq_shutdown_callback(grpc_completion_queue* cq) { } cqd->shutdown_called = true; if (gpr_atm_full_fetch_add(&cqd->pending_events, -1) == 1) { + gpr_mu_unlock(cq->mu); cq_finish_shutdown_callback(cq); + } else { + gpr_mu_unlock(cq->mu); } - gpr_mu_unlock(cq->mu); GRPC_CQ_INTERNAL_UNREF(cq, "shutting_down (callback cq)"); } diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index 39b891c2e1..2a961e6e27 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -42,8 +42,10 @@ #include #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/thd.h" #include "src/core/lib/profiling/timers.h" +#include "src/core/lib/surface/completion_queue.h" namespace grpc { @@ -53,7 +55,12 @@ Channel::Channel(const grpc::string& host, grpc_channel* channel) g_gli_initializer.summon(); } -Channel::~Channel() { grpc_channel_destroy(c_channel_); } +Channel::~Channel() { + grpc_channel_destroy(c_channel_); + if (callback_cq_ != nullptr) { + callback_cq_->Shutdown(); + } +} namespace { @@ -135,8 +142,8 @@ void Channel::PerformOpsOnCall(internal::CallOpSetInterface* ops, size_t nops = 0; grpc_op cops[MAX_OPS]; ops->FillOps(call->call(), cops, &nops); - GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_batch(call->call(), cops, nops, ops, nullptr)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call->call(), cops, nops, + ops->cq_tag(), nullptr)); } void* Channel::RegisterMethod(const char* method) { @@ -185,4 +192,32 @@ bool Channel::WaitForStateChangeImpl(grpc_connectivity_state last_observed, return ok; } +namespace { +class ShutdownCallback : public grpc_core::CQCallbackInterface { + public: + void TakeCQ(CompletionQueue* cq) { cq_ = cq; } + void Run(bool) override { + delete cq_; + grpc_core::Delete(this); + } + + private: + CompletionQueue* cq_ = nullptr; +}; +} // namespace + +CompletionQueue* Channel::CallbackCQ() { + // TODO(vjpai): Consider using a single global CQ for the default CQ + // if there is no explicit per-channel CQ registered + std::lock_guard l(mu_); + if (callback_cq_ == nullptr) { + auto* shutdown_callback = grpc_core::New(); + callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{ + GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING, + shutdown_callback}); + shutdown_callback->TakeCQ(callback_cq_); + } + return callback_cq_; +} + } // namespace grpc diff --git a/src/cpp/client/generic_stub.cc b/src/cpp/client/generic_stub.cc index 67ef46bebe..07c34c8878 100644 --- a/src/cpp/client/generic_stub.cc +++ b/src/cpp/client/generic_stub.cc @@ -16,9 +16,11 @@ * */ -#include +#include +#include #include +#include namespace grpc { @@ -60,4 +62,14 @@ std::unique_ptr GenericStub::PrepareUnaryCall( context, request, false)); } +void GenericStub::experimental_type::UnaryCall( + ClientContext* context, const grpc::string& method, + const ByteBuffer* request, ByteBuffer* response, + std::function on_completion) { + internal::CallbackUnaryCall( + stub_->channel_.get(), + internal::RpcMethod(method.c_str(), internal::RpcMethod::NORMAL_RPC), + context, request, response, on_completion); +} + } // namespace grpc diff --git a/src/cpp/common/callback_common.cc b/src/cpp/common/callback_common.cc new file mode 100644 index 0000000000..2598d37e27 --- /dev/null +++ b/src/cpp/common/callback_common.cc @@ -0,0 +1,109 @@ +/* + * + * 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 + +#include +#include + +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/surface/completion_queue.h" + +namespace grpc { +namespace internal { + +namespace { +class CallbackWithSuccessImpl : public grpc_core::CQCallbackInterface { + public: + CallbackWithSuccessImpl(CallbackWithSuccessTag* parent, + std::function f, bool self_delete) + : parent_(parent), func_(f), self_delete_(self_delete) {} + + void Run(bool ok) override { + void* ignored = parent_->ops(); + bool new_ok = ok; + GPR_ASSERT(parent_->ops()->FinalizeResult(&ignored, &new_ok)); + GPR_ASSERT(ignored == parent_->ops()); + func_(ok); + if (self_delete_) { + delete parent_; + // Must use grpc_core::Delete since base is GRPC_ABSTRACT + grpc_core::Delete(this); + } + } + + private: + CallbackWithSuccessTag* parent_; + std::function func_; + bool self_delete_; +}; + +class CallbackWithStatusImpl : public grpc_core::CQCallbackInterface { + public: + CallbackWithStatusImpl(CallbackWithStatusTag* parent, + std::function f, bool self_delete) + : parent_(parent), func_(f), status_(), self_delete_(self_delete) {} + + void Run(bool ok) override { + void* ignored = parent_->ops(); + + GPR_ASSERT(parent_->ops()->FinalizeResult(&ignored, &ok)); + GPR_ASSERT(ignored == parent_->ops()); + + func_(status_); + if (self_delete_) { + delete parent_; + // Must use grpc_core::Delete since base is GRPC_ABSTRACT + grpc_core::Delete(this); + } + } + Status* status_ptr() { return &status_; } + + private: + CallbackWithStatusTag* parent_; + std::function func_; + Status status_; + bool self_delete_; +}; + +} // namespace + +CallbackWithSuccessTag::CallbackWithSuccessTag(std::function f, + bool self_delete, + CompletionQueueTag* ops) + : impl_(grpc_core::New(this, f, self_delete)), + ops_(ops) {} + +void CallbackWithSuccessTag::force_run(bool ok) { impl_->Run(ok); } + +CallbackWithStatusTag::CallbackWithStatusTag(std::function f, + bool self_delete, + CompletionQueueTag* ops) + : ops_(ops) { + auto* impl = grpc_core::New(this, f, self_delete); + impl_ = impl; + status_ = impl->status_ptr(); +} + +void CallbackWithStatusTag::force_run(Status s) { + *status_ = s; + impl_->Run(true); +} + +} // namespace internal +} // namespace grpc diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 36c709eb45..f271825cba 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -657,7 +657,8 @@ void Server::PerformOpsOnCall(internal::CallOpSetInterface* ops, size_t nops = 0; grpc_op cops[MAX_OPS]; ops->FillOps(call->call(), cops, &nops); - auto result = grpc_call_start_batch(call->call(), cops, nops, ops, nullptr); + auto result = + grpc_call_start_batch(call->call(), cops, nops, ops->cq_tag(), nullptr); if (result != GRPC_CALL_OK) { gpr_log(GPR_ERROR, "Fatal: grpc_call_start_batch returned %d", result); grpc_call_log_batch(__FILE__, __LINE__, GPR_LOG_SEVERITY_ERROR, diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc index 6f5bde0d9f..f76f64e3da 100644 --- a/src/cpp/server/server_context.cc +++ b/src/cpp/server/server_context.cc @@ -61,6 +61,9 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { tag_ = tag; } + /// TODO(vjpai): Allow override of cq_tag if appropriate for callback API + void* cq_tag() override { return this; } + void Unref(); private: diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index 75dec56a60..0415efc1ef 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -98,6 +98,25 @@ grpc_cc_binary( ], ) +grpc_cc_test( + name = "client_callback_end2end_test", + srcs = ["client_callback_end2end_test.cc"], + external_deps = [ + "gtest", + ], + deps = [ + ":test_service_impl", + "//:gpr", + "//:grpc", + "//:grpc++", + "//src/proto/grpc/testing:echo_messages_proto", + "//src/proto/grpc/testing:echo_proto", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], +) + grpc_cc_library( name = "end2end_test_lib", testonly = True, diff --git a/test/cpp/end2end/client_callback_end2end_test.cc b/test/cpp/end2end/client_callback_end2end_test.cc new file mode 100644 index 0000000000..be732a0ca6 --- /dev/null +++ b/test/cpp/end2end/client_callback_end2end_test.cc @@ -0,0 +1,126 @@ +/* + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/byte_buffer_proto_helper.h" + +#include + +namespace grpc { +namespace testing { +namespace { + +class ClientCallbackEnd2endTest : public ::testing::Test { + protected: + ClientCallbackEnd2endTest() {} + + void SetUp() override { + ServerBuilder builder; + builder.RegisterService(&service_); + + server_ = builder.BuildAndStart(); + is_server_started_ = true; + } + + void ResetStub() { + ChannelArguments args; + channel_ = server_->InProcessChannel(args); + stub_.reset(new GenericStub(channel_)); + } + + void TearDown() override { + if (is_server_started_) { + server_->Shutdown(); + } + } + + void SendRpcs(int num_rpcs) { + const grpc::string kMethodName("/grpc.testing.EchoTestService/Echo"); + grpc::string test_string(""); + for (int i = 0; i < num_rpcs; i++) { + EchoRequest request; + std::unique_ptr send_buf; + ByteBuffer recv_buf; + ClientContext cli_ctx; + + test_string += "Hello world. "; + request.set_message(test_string); + send_buf = SerializeToByteBuffer(&request); + + std::mutex mu; + std::condition_variable cv; + bool done; + stub_->experimental().UnaryCall( + &cli_ctx, kMethodName, send_buf.get(), &recv_buf, + [&request, &recv_buf, &done, &mu, &cv](Status s) { + GPR_ASSERT(s.ok()); + + EchoResponse response; + EXPECT_TRUE(ParseFromByteBuffer(&recv_buf, &response)); + EXPECT_EQ(request.message(), response.message()); + std::lock_guard l(mu); + done = true; + cv.notify_one(); + }); + std::unique_lock l(mu); + while (!done) { + cv.wait(l); + } + } + } + bool is_server_started_; + std::shared_ptr channel_; + std::unique_ptr stub_; + TestServiceImpl service_; + std::unique_ptr server_; +}; + +TEST_F(ClientCallbackEnd2endTest, SimpleRpc) { + ResetStub(); + SendRpcs(1); +} + +TEST_F(ClientCallbackEnd2endTest, SequentialRpcs) { + ResetStub(); + SendRpcs(10); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9a97ee84f2..3b7fd1fa8e 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -945,7 +945,9 @@ include/grpcpp/impl/codegen/async_unary_call.h \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ +include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ +include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -997,6 +999,7 @@ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ +include/grpcpp/support/client_callback.h \ include/grpcpp/support/config.h \ include/grpcpp/support/proto_buffer_reader.h \ include/grpcpp/support/proto_buffer_writer.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 0cd4cfd647..a72390d9f8 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -946,7 +946,9 @@ include/grpcpp/impl/codegen/async_unary_call.h \ include/grpcpp/impl/codegen/byte_buffer.h \ include/grpcpp/impl/codegen/call.h \ include/grpcpp/impl/codegen/call_hook.h \ +include/grpcpp/impl/codegen/callback_common.h \ include/grpcpp/impl/codegen/channel_interface.h \ +include/grpcpp/impl/codegen/client_callback.h \ include/grpcpp/impl/codegen/client_context.h \ include/grpcpp/impl/codegen/client_unary_call.h \ include/grpcpp/impl/codegen/completion_queue.h \ @@ -999,6 +1001,7 @@ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ +include/grpcpp/support/client_callback.h \ include/grpcpp/support/config.h \ include/grpcpp/support/proto_buffer_reader.h \ include/grpcpp/support/proto_buffer_writer.h \ @@ -1187,6 +1190,7 @@ src/cpp/client/secure_credentials.h \ src/cpp/codegen/codegen_init.cc \ src/cpp/common/alarm.cc \ src/cpp/common/auth_property_iterator.cc \ +src/cpp/common/callback_common.cc \ src/cpp/common/channel_arguments.cc \ src/cpp/common/channel_filter.cc \ src/cpp/common/channel_filter.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8ea5126fde..9637fa8787 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -3302,6 +3302,25 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc++", + "grpc++_test_util", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "client_callback_end2end_test", + "src": [ + "test/cpp/end2end/client_callback_end2end_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -11081,7 +11100,9 @@ "include/grpcpp/impl/codegen/byte_buffer.h", "include/grpcpp/impl/codegen/call.h", "include/grpcpp/impl/codegen/call_hook.h", + "include/grpcpp/impl/codegen/callback_common.h", "include/grpcpp/impl/codegen/channel_interface.h", + "include/grpcpp/impl/codegen/client_callback.h", "include/grpcpp/impl/codegen/client_context.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", @@ -11147,7 +11168,9 @@ "include/grpcpp/impl/codegen/byte_buffer.h", "include/grpcpp/impl/codegen/call.h", "include/grpcpp/impl/codegen/call_hook.h", + "include/grpcpp/impl/codegen/callback_common.h", "include/grpcpp/impl/codegen/channel_interface.h", + "include/grpcpp/impl/codegen/client_callback.h", "include/grpcpp/impl/codegen/client_context.h", "include/grpcpp/impl/codegen/client_unary_call.h", "include/grpcpp/impl/codegen/completion_queue.h", @@ -11305,6 +11328,7 @@ "include/grpcpp/support/async_unary_call.h", "include/grpcpp/support/byte_buffer.h", "include/grpcpp/support/channel_arguments.h", + "include/grpcpp/support/client_callback.h", "include/grpcpp/support/config.h", "include/grpcpp/support/proto_buffer_reader.h", "include/grpcpp/support/proto_buffer_writer.h", @@ -11409,6 +11433,7 @@ "include/grpcpp/support/async_unary_call.h", "include/grpcpp/support/byte_buffer.h", "include/grpcpp/support/channel_arguments.h", + "include/grpcpp/support/client_callback.h", "include/grpcpp/support/config.h", "include/grpcpp/support/proto_buffer_reader.h", "include/grpcpp/support/proto_buffer_writer.h", @@ -11428,6 +11453,7 @@ "src/cpp/client/credentials_cc.cc", "src/cpp/client/generic_stub.cc", "src/cpp/common/alarm.cc", + "src/cpp/common/callback_common.cc", "src/cpp/common/channel_arguments.cc", "src/cpp/common/channel_filter.cc", "src/cpp/common/channel_filter.h", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index fba76d69d1..a48b9c60da 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -3945,6 +3945,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 0.5, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "client_callback_end2end_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, -- cgit v1.2.3 From 0b59c106d7d225995c2adb59c5c945f7b5319613 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 31 Aug 2018 14:51:39 -0700 Subject: use grpc_slice_unref_internal inside grpc --- src/core/tsi/alts/handshaker/alts_handshaker_client.cc | 9 +++++---- .../tsi/alts/handshaker/alts_handshaker_service_api_util.cc | 4 +++- src/core/tsi/alts/handshaker/alts_tsi_event.cc | 6 ++++-- src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc | 11 ++++++----- src/core/tsi/alts/handshaker/alts_tsi_utils.cc | 4 +++- .../alts_grpc_privacy_integrity_record_protocol.cc | 4 ++-- src/core/tsi/ssl/session_cache/ssl_session_cache.cc | 3 ++- 7 files changed, 25 insertions(+), 16 deletions(-) (limited to 'src/core') diff --git a/src/core/tsi/alts/handshaker/alts_handshaker_client.cc b/src/core/tsi/alts/handshaker/alts_handshaker_client.cc index b5268add0d..17e8026096 100644 --- a/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +++ b/src/core/tsi/alts/handshaker/alts_handshaker_client.cc @@ -24,6 +24,7 @@ #include #include +#include "src/core/lib/slice/slice_internal.h" #include "src/core/tsi/alts/handshaker/alts_handshaker_service_api.h" const int kHandshakerClientOpNum = 4; @@ -109,7 +110,7 @@ static grpc_byte_buffer* get_serialized_start_client(alts_tsi_event* event) { if (ok) { buffer = grpc_raw_byte_buffer_create(&slice, 1 /* number of slices */); } - grpc_slice_unref(slice); + grpc_slice_unref_internal(slice); gpr_free(target_name); grpc_gcp_handshaker_req_destroy(req); return buffer; @@ -157,7 +158,7 @@ static grpc_byte_buffer* get_serialized_start_server( if (ok) { buffer = grpc_raw_byte_buffer_create(&req_slice, 1 /* number of slices */); } - grpc_slice_unref(req_slice); + grpc_slice_unref_internal(req_slice); grpc_gcp_handshaker_req_destroy(req); return buffer; } @@ -195,7 +196,7 @@ static grpc_byte_buffer* get_serialized_next(grpc_slice* bytes_received) { if (ok) { buffer = grpc_raw_byte_buffer_create(&req_slice, 1 /* number of slices */); } - grpc_slice_unref(req_slice); + grpc_slice_unref_internal(req_slice); grpc_gcp_handshaker_req_destroy(req); return buffer; } @@ -258,7 +259,7 @@ alts_handshaker_client* alts_grpc_handshaker_client_create( grpc_slice_from_static_string(ALTS_SERVICE_METHOD), &slice, gpr_inf_future(GPR_CLOCK_REALTIME), nullptr); client->base.vtable = &vtable; - grpc_slice_unref(slice); + grpc_slice_unref_internal(slice); return &client->base; } diff --git a/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc b/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc index e0e4184686..d63d3538c5 100644 --- a/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc +++ b/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc @@ -20,6 +20,8 @@ #include "src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h" +#include "src/core/lib/slice/slice_internal.h" + void add_repeated_field(repeated_field** head, const void* data) { repeated_field* field = static_cast(gpr_zalloc(sizeof(*field))); @@ -67,7 +69,7 @@ grpc_slice* create_slice(const char* data, size_t size) { void destroy_slice(grpc_slice* slice) { if (slice != nullptr) { - grpc_slice_unref(*slice); + grpc_slice_unref_internal(*slice); gpr_free(slice); } } diff --git a/src/core/tsi/alts/handshaker/alts_tsi_event.cc b/src/core/tsi/alts/handshaker/alts_tsi_event.cc index ec0bf12b95..cb36d5ebd1 100644 --- a/src/core/tsi/alts/handshaker/alts_tsi_event.cc +++ b/src/core/tsi/alts/handshaker/alts_tsi_event.cc @@ -24,6 +24,8 @@ #include #include +#include "src/core/lib/slice/slice_internal.h" + tsi_result alts_tsi_event_create(alts_tsi_handshaker* handshaker, tsi_handshaker_on_next_done_cb cb, void* user_data, @@ -66,8 +68,8 @@ void alts_tsi_event_destroy(alts_tsi_event* event) { grpc_byte_buffer_destroy(event->recv_buffer); grpc_metadata_array_destroy(&event->initial_metadata); grpc_metadata_array_destroy(&event->trailing_metadata); - grpc_slice_unref(event->details); - grpc_slice_unref(event->target_name); + grpc_slice_unref_internal(event->details); + grpc_slice_unref_internal(event->target_name); grpc_alts_credentials_options_destroy(event->options); gpr_free(event); } diff --git a/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc b/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc index 1df1021bb1..34608a3de1 100644 --- a/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +++ b/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc @@ -31,6 +31,7 @@ #include "src/core/lib/gpr/host_port.h" #include "src/core/lib/gprpp/thd.h" +#include "src/core/lib/slice/slice_internal.h" #include "src/core/tsi/alts/frame_protector/alts_frame_protector.h" #include "src/core/tsi/alts/handshaker/alts_handshaker_client.h" #include "src/core/tsi/alts/handshaker/alts_tsi_utils.h" @@ -182,7 +183,7 @@ static void handshaker_result_destroy(tsi_handshaker_result* self) { gpr_free(result->peer_identity); gpr_free(result->key_data); gpr_free(result->unused_bytes); - grpc_slice_unref(result->rpc_versions); + grpc_slice_unref_internal(result->rpc_versions); gpr_free(result); } @@ -269,12 +270,12 @@ static tsi_result handshaker_next( handshaker->has_sent_start_message = true; } else { if (!GRPC_SLICE_IS_EMPTY(handshaker->recv_bytes)) { - grpc_slice_unref(handshaker->recv_bytes); + grpc_slice_unref_internal(handshaker->recv_bytes); } handshaker->recv_bytes = grpc_slice_ref(slice); ok = alts_handshaker_client_next(handshaker->client, event, &slice); } - grpc_slice_unref(slice); + grpc_slice_unref_internal(slice); if (ok != TSI_OK) { gpr_log(GPR_ERROR, "Failed to schedule ALTS handshaker requests"); return ok; @@ -299,8 +300,8 @@ static void handshaker_destroy(tsi_handshaker* self) { alts_tsi_handshaker* handshaker = reinterpret_cast(self); alts_handshaker_client_destroy(handshaker->client); - grpc_slice_unref(handshaker->recv_bytes); - grpc_slice_unref(handshaker->target_name); + grpc_slice_unref_internal(handshaker->recv_bytes); + grpc_slice_unref_internal(handshaker->target_name); grpc_alts_credentials_options_destroy(handshaker->options); gpr_free(handshaker->buffer); gpr_free(handshaker); diff --git a/src/core/tsi/alts/handshaker/alts_tsi_utils.cc b/src/core/tsi/alts/handshaker/alts_tsi_utils.cc index d9b5e6c945..1747f1ad04 100644 --- a/src/core/tsi/alts/handshaker/alts_tsi_utils.cc +++ b/src/core/tsi/alts/handshaker/alts_tsi_utils.cc @@ -22,6 +22,8 @@ #include +#include "src/core/lib/slice/slice_internal.h" + tsi_result alts_tsi_utils_convert_to_tsi_result(grpc_status_code code) { switch (code) { case GRPC_STATUS_OK: @@ -47,7 +49,7 @@ grpc_gcp_handshaker_resp* alts_tsi_utils_deserialize_response( grpc_slice slice = grpc_byte_buffer_reader_readall(&bbr); grpc_gcp_handshaker_resp* resp = grpc_gcp_handshaker_resp_create(); bool ok = grpc_gcp_handshaker_resp_decode(slice, resp); - grpc_slice_unref(slice); + grpc_slice_unref_internal(slice); grpc_byte_buffer_reader_destroy(&bbr); if (!ok) { grpc_gcp_handshaker_resp_destroy(resp); diff --git a/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc b/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc index d4fd88d1e2..e7890903d5 100644 --- a/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc +++ b/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc @@ -61,7 +61,7 @@ static tsi_result alts_grpc_privacy_integrity_protect( if (status != GRPC_STATUS_OK) { gpr_log(GPR_ERROR, "Failed to protect, %s", error_details); gpr_free(error_details); - grpc_slice_unref(protected_slice); + grpc_slice_unref_internal(protected_slice); return TSI_INTERNAL_ERROR; } grpc_slice_buffer_add(protected_slices, protected_slice); @@ -106,7 +106,7 @@ static tsi_result alts_grpc_privacy_integrity_unprotect( if (status != GRPC_STATUS_OK) { gpr_log(GPR_ERROR, "Failed to unprotect, %s", error_details); gpr_free(error_details); - grpc_slice_unref(unprotected_slice); + grpc_slice_unref_internal(unprotected_slice); return TSI_INTERNAL_ERROR; } grpc_slice_buffer_reset_and_unref_internal(&rp->header_sb); diff --git a/src/core/tsi/ssl/session_cache/ssl_session_cache.cc b/src/core/tsi/ssl/session_cache/ssl_session_cache.cc index ce74fde343..f9184bcc34 100644 --- a/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +++ b/src/core/tsi/ssl/session_cache/ssl_session_cache.cc @@ -19,6 +19,7 @@ #include #include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/slice/slice_internal.h" #include "src/core/tsi/ssl/session_cache/ssl_session.h" #include "src/core/tsi/ssl/session_cache/ssl_session_cache.h" @@ -53,7 +54,7 @@ class SslSessionLRUCache::Node { SetSession(std::move(session)); } - ~Node() { grpc_slice_unref(key_); } + ~Node() { grpc_slice_unref_internal(key_); } // Not copyable nor movable. Node(const Node&) = delete; -- cgit v1.2.3 From 5e054bf11e58049d988746cb76238f8099ac1faa Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 4 Sep 2018 13:01:34 -0700 Subject: Stop unconditionally surfacing user agent to server --- src/core/ext/filters/http/server/http_server_filter.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/core') diff --git a/src/core/ext/filters/http/server/http_server_filter.cc b/src/core/ext/filters/http/server/http_server_filter.cc index 926afeec84..a238d5f989 100644 --- a/src/core/ext/filters/http/server/http_server_filter.cc +++ b/src/core/ext/filters/http/server/http_server_filter.cc @@ -262,6 +262,10 @@ static grpc_error* hs_filter_incoming_metadata(grpc_call_element* elem, GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":authority"))); } + if (b->idx.named.user_agent != nullptr) { + grpc_metadata_batch_remove(b, b->idx.named.user_agent); + } + return error; } -- cgit v1.2.3 From c9e300d5b044351c6e09221b09ba49e53d211643 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 5 Sep 2018 17:08:01 -0700 Subject: Add channel arg control for user agent --- include/grpc/impl/codegen/grpc_types.h | 2 ++ src/core/ext/filters/http/server/http_server_filter.cc | 15 +++++++++++++-- test/core/end2end/tests/workaround_cronet_compression.cc | 9 +++++++++ test/cpp/end2end/end2end_test.cc | 13 ++++++++++--- 4 files changed, 34 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index b5353c1dea..9097984a96 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -342,6 +342,8 @@ typedef struct { "grpc.disable_client_authority_filter" /** If set to zero, disables use of http proxies. Enabled by default. */ #define GRPC_ARG_ENABLE_HTTP_PROXY "grpc.enable_http_proxy" +/** If set to non zero, surfaces the user agent string to the server. */ +#define GRPC_ARG_SURFACE_USER_AGENT "grpc.surface_user_agent" /** \} */ /** Result of a grpc call. If the caller satisfies the prerequisites of a diff --git a/src/core/ext/filters/http/server/http_server_filter.cc b/src/core/ext/filters/http/server/http_server_filter.cc index a238d5f989..53cd059aa8 100644 --- a/src/core/ext/filters/http/server/http_server_filter.cc +++ b/src/core/ext/filters/http/server/http_server_filter.cc @@ -23,6 +23,7 @@ #include #include #include +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/b64.h" @@ -66,6 +67,10 @@ struct call_data { grpc_closure* original_recv_trailing_metadata_ready; }; +struct channel_data { + bool surface_user_agent; +}; + } // namespace static grpc_error* hs_filter_outgoing_metadata(grpc_call_element* elem, @@ -262,7 +267,8 @@ static grpc_error* hs_filter_incoming_metadata(grpc_call_element* elem, GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":authority"))); } - if (b->idx.named.user_agent != nullptr) { + channel_data* chand = static_cast(elem->channel_data); + if (!chand->surface_user_agent && b->idx.named.user_agent != nullptr) { grpc_metadata_batch_remove(b, b->idx.named.user_agent); } @@ -434,7 +440,12 @@ static void hs_destroy_call_elem(grpc_call_element* elem, /* Constructor for channel_data */ static grpc_error* hs_init_channel_elem(grpc_channel_element* elem, grpc_channel_element_args* args) { + channel_data* chand = static_cast(elem->channel_data); GPR_ASSERT(!args->is_last); + chand->surface_user_agent = grpc_channel_arg_get_bool( + grpc_channel_args_find(args->channel_args, + const_cast(GRPC_ARG_SURFACE_USER_AGENT)), + false); return GRPC_ERROR_NONE; } @@ -448,7 +459,7 @@ const grpc_channel_filter grpc_http_server_filter = { hs_init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, hs_destroy_call_elem, - 0, + sizeof(channel_data), hs_init_channel_elem, hs_destroy_channel_elem, grpc_channel_next_get_info, diff --git a/test/core/end2end/tests/workaround_cronet_compression.cc b/test/core/end2end/tests/workaround_cronet_compression.cc index f44ddca3b1..e1bce603fa 100644 --- a/test/core/end2end/tests/workaround_cronet_compression.cc +++ b/test/core/end2end/tests/workaround_cronet_compression.cc @@ -149,6 +149,15 @@ static void request_with_payload_template( arg.value.string = user_agent_override; client_args = grpc_channel_args_copy_and_add(client_args_old, &arg, 1); grpc_channel_args_destroy(client_args_old); + // force grpc lib to pass the user agent back up to server. + grpc_channel_args* server_args_old = server_args; + grpc_arg server_arg; + server_arg.key = const_cast(GRPC_ARG_SURFACE_USER_AGENT); + server_arg.type = GRPC_ARG_INTEGER; + server_arg.value.integer = 1; + server_args = + grpc_channel_args_copy_and_add(server_args_old, &server_arg, 1); + grpc_channel_args_destroy(server_args_old); } f = begin_test(config, test_name, client_args, server_args); diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index fc07681535..e835f55738 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -244,15 +244,17 @@ class End2endTest : public ::testing::TestWithParam { BuildAndStartServer(processor); } - void RestartServer(const std::shared_ptr& processor) { + void RestartServer(const std::shared_ptr& processor, + bool surface_user_agent = false) { if (is_server_started_) { server_->Shutdown(); - BuildAndStartServer(processor); + BuildAndStartServer(processor, surface_user_agent); } } void BuildAndStartServer( - const std::shared_ptr& processor) { + const std::shared_ptr& processor, + bool surface_user_agent = false) { ServerBuilder builder; ConfigureServerBuilder(&builder); auto server_creds = GetCredentialsProvider()->GetServerCredentials( @@ -268,6 +270,9 @@ class End2endTest : public ::testing::TestWithParam { builder.SetSyncServerOption(ServerBuilder::SyncServerOption::NUM_CQS, 4); builder.SetSyncServerOption( ServerBuilder::SyncServerOption::CQ_TIMEOUT_MSEC, 10); + if (surface_user_agent) { + builder.AddChannelArgument(GRPC_ARG_SURFACE_USER_AGENT, 1); + } server_ = builder.BuildAndStart(); is_server_started_ = true; @@ -664,6 +669,8 @@ TEST_P(End2endTest, SimpleRpcWithCustomUserAgentPrefix) { } user_agent_prefix_ = "custom_prefix"; ResetStub(); + RestartServer(std::shared_ptr(), true); + ResetChannel(); EchoRequest request; EchoResponse response; request.set_message("Hello hello hello hello"); -- cgit v1.2.3 From 16f53ff583c23b3b2a260ba0935fd0c30b479acf Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 5 Sep 2018 18:16:13 -0700 Subject: Surface user agent by default --- include/grpc/impl/codegen/grpc_types.h | 3 ++- src/core/ext/filters/http/server/http_server_filter.cc | 2 +- test/core/end2end/tests/workaround_cronet_compression.cc | 9 --------- test/cpp/end2end/end2end_test.cc | 13 +++---------- 4 files changed, 6 insertions(+), 21 deletions(-) (limited to 'src/core') diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index 9097984a96..5f3b96f40b 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -342,7 +342,8 @@ typedef struct { "grpc.disable_client_authority_filter" /** If set to zero, disables use of http proxies. Enabled by default. */ #define GRPC_ARG_ENABLE_HTTP_PROXY "grpc.enable_http_proxy" -/** If set to non zero, surfaces the user agent string to the server. */ +/** If set to non zero, surfaces the user agent string to the server. User + agent is surfaced by default. */ #define GRPC_ARG_SURFACE_USER_AGENT "grpc.surface_user_agent" /** \} */ diff --git a/src/core/ext/filters/http/server/http_server_filter.cc b/src/core/ext/filters/http/server/http_server_filter.cc index 53cd059aa8..1b3426b120 100644 --- a/src/core/ext/filters/http/server/http_server_filter.cc +++ b/src/core/ext/filters/http/server/http_server_filter.cc @@ -445,7 +445,7 @@ static grpc_error* hs_init_channel_elem(grpc_channel_element* elem, chand->surface_user_agent = grpc_channel_arg_get_bool( grpc_channel_args_find(args->channel_args, const_cast(GRPC_ARG_SURFACE_USER_AGENT)), - false); + true); return GRPC_ERROR_NONE; } diff --git a/test/core/end2end/tests/workaround_cronet_compression.cc b/test/core/end2end/tests/workaround_cronet_compression.cc index e1bce603fa..f44ddca3b1 100644 --- a/test/core/end2end/tests/workaround_cronet_compression.cc +++ b/test/core/end2end/tests/workaround_cronet_compression.cc @@ -149,15 +149,6 @@ static void request_with_payload_template( arg.value.string = user_agent_override; client_args = grpc_channel_args_copy_and_add(client_args_old, &arg, 1); grpc_channel_args_destroy(client_args_old); - // force grpc lib to pass the user agent back up to server. - grpc_channel_args* server_args_old = server_args; - grpc_arg server_arg; - server_arg.key = const_cast(GRPC_ARG_SURFACE_USER_AGENT); - server_arg.type = GRPC_ARG_INTEGER; - server_arg.value.integer = 1; - server_args = - grpc_channel_args_copy_and_add(server_args_old, &server_arg, 1); - grpc_channel_args_destroy(server_args_old); } f = begin_test(config, test_name, client_args, server_args); diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index e835f55738..fc07681535 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -244,17 +244,15 @@ class End2endTest : public ::testing::TestWithParam { BuildAndStartServer(processor); } - void RestartServer(const std::shared_ptr& processor, - bool surface_user_agent = false) { + void RestartServer(const std::shared_ptr& processor) { if (is_server_started_) { server_->Shutdown(); - BuildAndStartServer(processor, surface_user_agent); + BuildAndStartServer(processor); } } void BuildAndStartServer( - const std::shared_ptr& processor, - bool surface_user_agent = false) { + const std::shared_ptr& processor) { ServerBuilder builder; ConfigureServerBuilder(&builder); auto server_creds = GetCredentialsProvider()->GetServerCredentials( @@ -270,9 +268,6 @@ class End2endTest : public ::testing::TestWithParam { builder.SetSyncServerOption(ServerBuilder::SyncServerOption::NUM_CQS, 4); builder.SetSyncServerOption( ServerBuilder::SyncServerOption::CQ_TIMEOUT_MSEC, 10); - if (surface_user_agent) { - builder.AddChannelArgument(GRPC_ARG_SURFACE_USER_AGENT, 1); - } server_ = builder.BuildAndStart(); is_server_started_ = true; @@ -669,8 +664,6 @@ TEST_P(End2endTest, SimpleRpcWithCustomUserAgentPrefix) { } user_agent_prefix_ = "custom_prefix"; ResetStub(); - RestartServer(std::shared_ptr(), true); - ResetChannel(); EchoRequest request; EchoResponse response; request.set_message("Hello hello hello hello"); -- cgit v1.2.3 From 3c1a3d9f1b4c8ac573c0234f71534fd74cf2ec4b Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Thu, 6 Sep 2018 15:06:17 -0700 Subject: Fix subchannel key comparison if forcing creation --- src/core/ext/filters/client_channel/subchannel_index.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/subchannel_index.cc b/src/core/ext/filters/client_channel/subchannel_index.cc index cb02b1a748..4e155a2830 100644 --- a/src/core/ext/filters/client_channel/subchannel_index.cc +++ b/src/core/ext/filters/client_channel/subchannel_index.cc @@ -73,7 +73,8 @@ static grpc_subchannel_key* subchannel_key_copy(grpc_subchannel_key* k) { int grpc_subchannel_key_compare(const grpc_subchannel_key* a, const grpc_subchannel_key* b) { - if (g_force_creation) return false; + // To pretend the keys are different, return a non-zero value. + if (g_force_creation) return 1; int c = GPR_ICMP(a->args.filter_count, b->args.filter_count); if (c != 0) return c; if (a->args.filter_count > 0) { -- cgit v1.2.3 From b91da3f4bf4ab30428e50a0c6734fcb931e3d85e Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 6 Sep 2018 15:26:36 -0700 Subject: Add support for reading channel args --- src/core/lib/iomgr/port.h | 1 - src/core/lib/iomgr/socket_utils_common_posix.cc | 87 ++++++++++++++++++---- src/core/lib/iomgr/socket_utils_posix.h | 8 +- src/core/lib/iomgr/tcp_client_posix.cc | 3 +- .../lib/iomgr/tcp_server_utils_posix_common.cc | 3 +- 5 files changed, 83 insertions(+), 19 deletions(-) (limited to 'src/core') diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index bc58ed13c0..807b9bf85a 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -77,7 +77,6 @@ #define GRPC_LINUX_SOCKETUTILS 1 #endif #endif -#include #ifdef LINUX_VERSION_CODE #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) #define GRPC_HAVE_TCP_USER_TIMEOUT diff --git a/src/core/lib/iomgr/socket_utils_common_posix.cc b/src/core/lib/iomgr/socket_utils_common_posix.cc index b7fc833608..4ef3d8319f 100644 --- a/src/core/lib/iomgr/socket_utils_common_posix.cc +++ b/src/core/lib/iomgr/socket_utils_common_posix.cc @@ -41,6 +41,7 @@ #include #include +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/host_port.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/sockaddr.h" @@ -222,25 +223,83 @@ grpc_error* grpc_set_socket_low_latency(int fd, int low_latency) { return GRPC_ERROR_NONE; } -#define DEFAULT_TCP_USER_TIMEOUT 20000 /* 20 seconds */ +/* The default values for TCP_USER_TIMEOUT are currently configured to be in + * line with the default values of KEEPALIVE_TIMEOUT as proposed in + * https://github.com/grpc/proposal/blob/master/A18-tcp-user-timeout.md */ +#define DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS 20000 /* 20 seconds */ +#define DEFAULT_SERVER_TCP_USER_TIMEOUT_MS 20000 /* 20 seconds */ + +static int g_default_client_tcp_user_timeout_ms = + DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS; +static int g_default_server_tcp_user_timeout_ms = + DEFAULT_SERVER_TCP_USER_TIMEOUT_MS; +static bool g_default_client_tcp_user_timeout_enabled = false; +static bool g_default_server_tcp_user_timeout_enabled = true; + +void config_default_tcp_user_timeout(bool enable, int timeout, bool is_client) { + if (is_client) { + g_default_client_tcp_user_timeout_enabled = enable; + if (timeout > 0) { + g_default_client_tcp_user_timeout_ms = timeout; + } + } else { + g_default_server_tcp_user_timeout_enabled = enable; + if (timeout > 0) { + g_default_server_tcp_user_timeout_ms = timeout; + } + } +} /* Set TCP_USER_TIMEOUT */ -grpc_error* grpc_set_socket_tcp_user_timeout(int fd, int val) { +grpc_error* grpc_set_socket_tcp_user_timeout( + int fd, const grpc_channel_args* channel_args, bool is_client) { #ifdef GRPC_HAVE_TCP_USER_TIMEOUT - int newval; - socklen_t len = sizeof(newval); - if (val == 0) { - val = DEFAULT_TCP_USER_TIMEOUT; - } - if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &val, sizeof(val))) { - return GRPC_OS_ERROR(errno, "setsockopt(TCP_USER_TIMEOUT)"); + bool enable; + int timeout; + if (is_client) { + enable = g_default_client_tcp_user_timeout_enabled; + timeout = g_default_client_tcp_user_timeout_ms; + } else { + enable = g_default_server_tcp_user_timeout_enabled; + timeout = g_default_server_tcp_user_timeout_ms; } - if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) { - return GRPC_OS_ERROR(errno, "getsockopt(TCP_USER_TIMEOUT)"); + if (channel_args) { + for (unsigned int i = 0; i < channel_args->num_args; i++) { + if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_KEEPALIVE_TIME_MS)) { + const int value = grpc_channel_arg_get_integer( + &channel_args->args[i], grpc_integer_options{0, 1, INT_MAX}); + /* Continue using default if value is 0 */ + if (value == 0) { + continue; + } + /* Disable if value is INT_MAX */ + enable = value != INT_MAX; + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) { + const int value = grpc_channel_arg_get_integer( + &channel_args->args[i], grpc_integer_options{0, 1, INT_MAX}); + /* Continue using default if value is 0 */ + if (value == 0) { + continue; + } + timeout = value; + } + } } - if (newval != val) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Failed to set TCP_USER_TIMEOUT"); + if (enable) { + int newval; + socklen_t len = sizeof(newval); + if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, + sizeof(timeout))) { + return GRPC_OS_ERROR(errno, "setsockopt(TCP_USER_TIMEOUT)"); + } + if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) { + return GRPC_OS_ERROR(errno, "getsockopt(TCP_USER_TIMEOUT)"); + } + if (newval != timeout) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Failed to set TCP_USER_TIMEOUT"); + } } #else gpr_log(GPR_INFO, "TCP_USER_TIMEOUT not supported for this platform"); diff --git a/src/core/lib/iomgr/socket_utils_posix.h b/src/core/lib/iomgr/socket_utils_posix.h index 8550bd1324..71a304dc4e 100644 --- a/src/core/lib/iomgr/socket_utils_posix.h +++ b/src/core/lib/iomgr/socket_utils_posix.h @@ -53,8 +53,12 @@ grpc_error* grpc_set_socket_low_latency(int fd, int low_latency); /* set SO_REUSEPORT */ grpc_error* grpc_set_socket_reuse_port(int fd, int reuse); -/* Set TCP_USER_TIMEOUT to val, or the default value if val is 0. */ -grpc_error* grpc_set_socket_tcp_user_timeout(int fd, int val); +/* Configure the default values for TCP_USER_TIMEOUT */ +void config_default_tcp_user_timeout(bool enable, int timeout, bool is_client); + +/* Set TCP_USER_TIMEOUT */ +grpc_error* grpc_set_socket_tcp_user_timeout( + int fd, const grpc_channel_args* channel_args, bool is_client); /* Returns true if this system can create AF_INET6 sockets bound to ::1. The value is probed once, and cached for the life of the process. diff --git a/src/core/lib/iomgr/tcp_client_posix.cc b/src/core/lib/iomgr/tcp_client_posix.cc index c2a0892211..b71f557094 100644 --- a/src/core/lib/iomgr/tcp_client_posix.cc +++ b/src/core/lib/iomgr/tcp_client_posix.cc @@ -76,7 +76,8 @@ static grpc_error* prepare_socket(const grpc_resolved_address* addr, int fd, if (!grpc_is_unix_socket(addr)) { err = grpc_set_socket_low_latency(fd, 1); if (err != GRPC_ERROR_NONE) goto error; - err = grpc_set_socket_tcp_user_timeout(fd, 0 /* set to gRPC default */); + err = grpc_set_socket_tcp_user_timeout(fd, channel_args, + true /* is_client */); if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_no_sigpipe_if_possible(fd); diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc index 20b9037c68..6cebc84024 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc @@ -166,7 +166,8 @@ grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server* s, int fd, if (err != GRPC_ERROR_NONE) goto error; err = grpc_set_socket_reuse_addr(fd, 1); if (err != GRPC_ERROR_NONE) goto error; - err = grpc_set_socket_tcp_user_timeout(fd, 0 /* set to gRPC default */); + err = grpc_set_socket_tcp_user_timeout(fd, s->channel_args, + false /* is_client */); if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_no_sigpipe_if_possible(fd); -- cgit v1.2.3 From bf53d1c8803b2b43bfb1756ce1c7f85326342418 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Fri, 7 Sep 2018 14:21:41 -0700 Subject: Fix subchannel key comparison --- src/core/ext/filters/client_channel/subchannel_index.cc | 6 +++--- src/core/ext/filters/client_channel/subchannel_index.h | 5 +---- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/subchannel_index.cc b/src/core/ext/filters/client_channel/subchannel_index.cc index 4e155a2830..f2b6c24e8e 100644 --- a/src/core/ext/filters/client_channel/subchannel_index.cc +++ b/src/core/ext/filters/client_channel/subchannel_index.cc @@ -42,7 +42,7 @@ struct grpc_subchannel_key { grpc_subchannel_args args; }; -static bool g_force_creation = false; +static gpr_atm g_force_creation = false; static grpc_subchannel_key* create_key( const grpc_subchannel_args* args, @@ -74,7 +74,7 @@ static grpc_subchannel_key* subchannel_key_copy(grpc_subchannel_key* k) { int grpc_subchannel_key_compare(const grpc_subchannel_key* a, const grpc_subchannel_key* b) { // To pretend the keys are different, return a non-zero value. - if (g_force_creation) return 1; + if (GPR_UNLIKELY(gpr_atm_no_barrier_load(&g_force_creation))) return 1; int c = GPR_ICMP(a->args.filter_count, b->args.filter_count); if (c != 0) return c; if (a->args.filter_count > 0) { @@ -251,5 +251,5 @@ void grpc_subchannel_index_unregister(grpc_subchannel_key* key, } void grpc_subchannel_index_test_only_set_force_creation(bool force_creation) { - g_force_creation = force_creation; + gpr_atm_no_barrier_store(&g_force_creation, force_creation); } diff --git a/src/core/ext/filters/client_channel/subchannel_index.h b/src/core/ext/filters/client_channel/subchannel_index.h index a7dae9d47d..c135613d26 100644 --- a/src/core/ext/filters/client_channel/subchannel_index.h +++ b/src/core/ext/filters/client_channel/subchannel_index.h @@ -65,13 +65,10 @@ void grpc_subchannel_index_ref(void); void grpc_subchannel_index_unref(void); /** \em TEST ONLY. - * If \a force_creation is true, all key comparisons will be false, resulting in + * If \a force_creation is true, all keys are regarded different, resulting in * new subchannels always being created. Otherwise, the keys will be compared as * usual. * - * This function is *not* threadsafe on purpose: it should *only* be used in - * test code. - * * Tests using this function \em MUST run tests with and without \a * force_creation set. */ void grpc_subchannel_index_test_only_set_force_creation(bool force_creation); -- cgit v1.2.3 From be8844bcdb704cff6a70507f5093e4bb26320ea3 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 7 Sep 2018 15:44:59 -0700 Subject: reviewer feedback --- .../ext/filters/client_channel/client_channel.cc | 133 ++++++++++----------- src/core/lib/channel/channelz.h | 7 +- src/core/lib/channel/connected_channel.cc | 6 +- src/core/lib/surface/call.cc | 8 +- test/core/channel/channel_trace_test.cc | 4 +- test/core/channel/channelz_test.cc | 4 +- 6 files changed, 78 insertions(+), 84 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index d015ceb335..000cf82c6c 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -937,7 +937,7 @@ typedef struct client_channel_call_data { // state needed to support channelz interception of recv trailing metadata. grpc_closure recv_trailing_metadata_ready_channelz; grpc_closure* original_recv_trailing_metadata; - grpc_transport_stream_op_batch* recv_trailing_metadata_batch; + grpc_metadata_batch* recv_trailing_metadata_batch; grpc_polling_entity* pollent; bool pollent_added_to_interested_parties; @@ -1000,14 +1000,8 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem); static void on_complete(void* arg, grpc_error* error); static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored); static void start_pick_locked(void* arg, grpc_error* ignored); -template -static pending_batch* pending_batch_find(grpc_call_element* elem, - const char* log_message, - Predicate predicate); -static void get_call_status(grpc_call_element* elem, - grpc_metadata_batch* md_batch, grpc_error* error, - grpc_status_code* status, - grpc_mdelem** server_pushback_md); +static void maybe_intercept_metadata_for_channelz( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch); // // send op data caching @@ -1282,66 +1276,6 @@ static void resume_pending_batch_in_call_combiner(void* arg, grpc_subchannel_call_process_op(subchannel_call, batch); } -static void recv_trailing_metadata_ready_channelz(void* arg, - grpc_error* error) { - grpc_call_element* elem = static_cast(arg); - channel_data* chand = static_cast(elem->channel_data); - call_data* calld = static_cast(elem->call_data); - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: got recv_trailing_metadata_ready_channelz, " - "error=%s", - chand, calld, grpc_error_string(error)); - } - GPR_ASSERT(calld->recv_trailing_metadata_batch != nullptr); - grpc_status_code status = GRPC_STATUS_OK; - grpc_metadata_batch* md_batch = - calld->recv_trailing_metadata_batch->payload->recv_trailing_metadata - .recv_trailing_metadata; - get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, nullptr); - grpc_core::channelz::SubchannelNode* channelz_subchannel = - calld->pick.connected_subchannel->channelz_subchannel(); - GPR_ASSERT(channelz_subchannel != nullptr); - if (status == GRPC_STATUS_OK) { - channelz_subchannel->RecordCallSucceeded(); - } else { - channelz_subchannel->RecordCallFailed(); - } - calld->recv_trailing_metadata_batch = nullptr; - GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata, error); -} - -// If channelz is enabled, intercept recv_trailing so that we may check the -// status and associate it to a subchannel. -// Returns true if callback was intercepted, false otherwise. -static void maybe_intercept_recv_trailing_for_channelz( - grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { - call_data* calld = static_cast(elem->call_data); - // only intercept payloads with recv trailing. - if (!batch->recv_trailing_metadata) { - return; - } - // only add interceptor is channelz is enabled. - if (calld->pick.connected_subchannel->channelz_subchannel() == nullptr) { - return; - } - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "calld=%p batch=%p: intercepting recv trailing for channelz", calld, - batch); - } - GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_channelz, - recv_trailing_metadata_ready_channelz, elem, - grpc_schedule_on_exec_ctx); - // save some state needed for the interception callback. - GPR_ASSERT(calld->recv_trailing_metadata_batch == nullptr); - calld->recv_trailing_metadata_batch = batch; - calld->original_recv_trailing_metadata = - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = - &calld->recv_trailing_metadata_ready_channelz; -} - // This is called via the call combiner, so access to calld is synchronized. static void pending_batches_resume(grpc_call_element* elem) { channel_data* chand = static_cast(elem->channel_data); @@ -1366,7 +1300,7 @@ static void pending_batches_resume(grpc_call_element* elem) { pending_batch* pending = &calld->pending_batches[i]; grpc_transport_stream_op_batch* batch = pending->batch; if (batch != nullptr) { - maybe_intercept_recv_trailing_for_channelz(elem, batch); + maybe_intercept_metadata_for_channelz(elem, batch); batch->handler_private.extra_arg = calld->subchannel_call; GRPC_CLOSURE_INIT(&batch->handler_private.closure, resume_pending_batch_in_call_combiner, batch, @@ -2736,6 +2670,65 @@ static void pick_done(void* arg, grpc_error* error) { } } +static void recv_trailing_metadata_ready_channelz(void* arg, + grpc_error* error) { + grpc_call_element* elem = static_cast(arg); + channel_data* chand = static_cast(elem->channel_data); + call_data* calld = static_cast(elem->call_data); + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: got recv_trailing_metadata_ready_channelz, " + "error=%s", + chand, calld, grpc_error_string(error)); + } + GPR_ASSERT(calld->recv_trailing_metadata_batch != nullptr); + grpc_status_code status = GRPC_STATUS_OK; + grpc_metadata_batch* md_batch = calld->recv_trailing_metadata_batch; + get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, nullptr); + grpc_core::channelz::SubchannelNode* channelz_subchannel = + calld->pick.connected_subchannel->channelz_subchannel(); + GPR_ASSERT(channelz_subchannel != nullptr); + if (status == GRPC_STATUS_OK) { + channelz_subchannel->RecordCallSucceeded(); + } else { + channelz_subchannel->RecordCallFailed(); + } + calld->recv_trailing_metadata_batch = nullptr; + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata, error); +} + +// If channelz is enabled, intercept recv_trailing so that we may check the +// status and associate it to a subchannel. +// Returns true if callback was intercepted, false otherwise. +static void maybe_intercept_metadata_for_channelz( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { + call_data* calld = static_cast(elem->call_data); + // only intercept payloads with recv trailing. + if (!batch->recv_trailing_metadata) { + return; + } + // only add interceptor is channelz is enabled. + if (calld->pick.connected_subchannel->channelz_subchannel() == nullptr) { + return; + } + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "calld=%p batch=%p: intercepting recv trailing for channelz", calld, + batch); + } + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_channelz, + recv_trailing_metadata_ready_channelz, elem, + grpc_schedule_on_exec_ctx); + // save some state needed for the interception callback. + GPR_ASSERT(calld->recv_trailing_metadata_batch == nullptr); + calld->recv_trailing_metadata_batch = + batch->payload->recv_trailing_metadata.recv_trailing_metadata; + calld->original_recv_trailing_metadata = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready_channelz; +} + static void maybe_add_call_to_channel_interested_parties_locked( grpc_call_element* elem) { channel_data* chand = static_cast(elem->channel_data); diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index bd2735929c..db5d05140d 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -79,7 +79,7 @@ class BaseNode : public RefCounted { const intptr_t uuid_; }; -// This class is a helper class for channelz entities that deal with Channels +// This class is a helper class for channelz entities that deal with Channels, // Subchannels, and Servers, since those have similar proto definitions. // This class has the ability to: // - track calls_{started,succeeded,failed} @@ -133,6 +133,9 @@ class ChannelNode : public BaseNode { // so it leaves these implementations blank. // // This is utilizing the template method design pattern. + // + // TODO(ncteisen): remove these template methods in favor of manual traversal + // and mutation of the grpc_json object. virtual void PopulateConnectivityState(grpc_json* json) {} virtual void PopulateChildRefs(grpc_json* json) {} @@ -158,7 +161,7 @@ class ChannelNode : public BaseNode { void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } private: - // to allow the channel trace test to access trace(); + // to allow the channel trace test to access trace_. friend class testing::ChannelNodePeer; grpc_channel* channel_ = nullptr; UniquePtr target_; diff --git a/src/core/lib/channel/connected_channel.cc b/src/core/lib/channel/connected_channel.cc index 90a0254663..4a4f0e49d0 100644 --- a/src/core/lib/channel/connected_channel.cc +++ b/src/core/lib/channel/connected_channel.cc @@ -104,18 +104,18 @@ static void con_start_transport_stream_op_batch( if (batch->recv_initial_metadata) { callback_state* state = &calld->recv_initial_metadata_ready; intercept_callback( - calld, state, false, "connected_recv_initial_metadata_ready", + calld, state, false, "recv_initial_metadata_ready", &batch->payload->recv_initial_metadata.recv_initial_metadata_ready); } if (batch->recv_message) { callback_state* state = &calld->recv_message_ready; - intercept_callback(calld, state, false, "connected_recv_message_ready", + intercept_callback(calld, state, false, "recv_message_ready", &batch->payload->recv_message.recv_message_ready); } if (batch->recv_trailing_metadata) { callback_state* state = &calld->recv_trailing_metadata_ready; intercept_callback( - calld, state, false, "connected_recv_trailing_metadata_ready", + calld, state, false, "recv_trailing_metadata_ready", &batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready); } if (batch->cancel_stream) { diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 3d69db4f83..eb7e67233b 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -1425,7 +1425,7 @@ static void receiving_stream_ready_in_call_combiner(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, "call_recv_message_ready"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_message_ready"); receiving_stream_ready(bctlp, error); } @@ -1510,8 +1510,7 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, - "call_recv_initial_metadata_ready"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_initial_metadata_ready"); add_batch_error(bctl, GRPC_ERROR_REF(error), false); if (error == GRPC_ERROR_NONE) { @@ -1562,8 +1561,7 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; - GRPC_CALL_COMBINER_STOP(&call->call_combiner, - "call_recv_trailing_metadata_ready"); + GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready"); add_batch_error(bctl, GRPC_ERROR_REF(error), false); grpc_metadata_batch* md = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; diff --git a/test/core/channel/channel_trace_test.cc b/test/core/channel/channel_trace_test.cc index e33277753b..d594445bfb 100644 --- a/test/core/channel/channel_trace_test.cc +++ b/test/core/channel/channel_trace_test.cc @@ -44,8 +44,8 @@ namespace testing { // testing peer to access channel internals class ChannelNodePeer { public: - ChannelNodePeer(ChannelNode* node) : node_(node) {} - ChannelTrace* trace() { return &node_->trace_; } + explicit ChannelNodePeer(ChannelNode* node) : node_(node) {} + ChannelTrace* trace() const { return &node_->trace_; } private: ChannelNode* node_; diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index 8fa46a18da..09189fa36d 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -46,8 +46,8 @@ namespace testing { // testing peer to access channel internals class CallCountingHelperPeer { public: - CallCountingHelperPeer(CallCountingHelper* node) : node_(node) {} - grpc_millis last_call_started_millis() { + explicit CallCountingHelperPeer(CallCountingHelper* node) : node_(node) {} + grpc_millis last_call_started_millis() const { return (grpc_millis)gpr_atm_no_barrier_load( &node_->last_call_started_millis_); } -- cgit v1.2.3 From fe1f7f58139a3ccafb7b8e8ca92d5d209880a3e5 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 7 Sep 2018 15:58:22 -0700 Subject: reviewer feedback --- src/core/lib/channel/channelz.cc | 3 --- src/core/lib/channel/channelz.h | 2 -- src/core/lib/surface/call.cc | 11 +++++------ src/core/lib/surface/channel.cc | 4 ++-- test/core/channel/channelz_test.cc | 17 +++++++++-------- test/core/end2end/tests/channelz.cc | 4 ++-- 6 files changed, 18 insertions(+), 23 deletions(-) (limited to 'src/core') diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index bb79005654..375cf25cc6 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -181,9 +181,6 @@ grpc_json* ServerNode::RenderJson() { // ask CallCountingHelper to populate trace and call count data. call_counter_.PopulateCallCounts(json); json = top_level_json; - // template method. Child classes may override this to add their specific - // functionality. - PopulateSockets(json); return top_level_json; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 9a448d3b38..603ec0b473 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -174,8 +174,6 @@ class ServerNode : public BaseNode { grpc_json* RenderJson() override; - void PopulateSockets(grpc_json* json) {} - // proxy methods to composed classes. void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { trace_.AddTraceEvent(severity, data); diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 826c0fb834..bff3ec379f 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -167,8 +167,6 @@ struct grpc_call { grpc_completion_queue* cq; grpc_polling_entity pollent; grpc_channel* channel; - // backpointer to owning server if this is a server side call. - grpc_server* server; gpr_timespec start_time; /* parent_call* */ gpr_atm parent_call_atm; child_call* child; @@ -250,6 +248,8 @@ struct grpc_call { } client; struct { int* cancelled; + // backpointer to owning server if this is a server side call. + grpc_server* server; } server; } final_op; @@ -369,7 +369,6 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, grpc_slice path = grpc_empty_slice(); if (call->is_client) { GRPC_STATS_INC_CLIENT_CALLS_CREATED(); - call->server = nullptr; GPR_ASSERT(args->add_initial_metadata_count < MAX_SEND_EXTRA_METADATA_COUNT); for (i = 0; i < args->add_initial_metadata_count; i++) { @@ -384,7 +383,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, static_cast(args->add_initial_metadata_count); } else { GRPC_STATS_INC_SERVER_CALLS_CREATED(); - call->server = args->server; + call->final_op.server.server = args->server; GPR_ASSERT(args->add_initial_metadata_count == 0); call->send_extra_metadata_count = 0; } @@ -496,7 +495,7 @@ grpc_error* grpc_call_create(const grpc_call_create_args* args, } } else { grpc_core::channelz::ServerNode* channelz_server = - grpc_server_get_channelz_node(call->server); + grpc_server_get_channelz_node(call->final_op.server.server); if (channelz_server != nullptr) { channelz_server->RecordCallStarted(); } @@ -1286,7 +1285,7 @@ static void post_batch_completion(batch_control* bctl) { get_final_status(call, set_cancelled_value, call->final_op.server.cancelled, nullptr, nullptr); grpc_core::channelz::ServerNode* channelz_server = - grpc_server_get_channelz_node(call->server); + grpc_server_get_channelz_node(call->final_op.server.server); if (channelz_server != nullptr) { if (*call->final_op.server.cancelled) { channelz_server->RecordCallFailed(); diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 815d302577..52056b8671 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -166,8 +166,8 @@ grpc_channel* grpc_channel_create_with_builder( } grpc_channel_args_destroy(args); - // only track client channels since server channels are held in the - // grpc_server channel. + // we only need to do the channelz bookkeeping for clients here. The channelz + // bookkeeping for server channels occurs in src/core/lib/surface/server.cc if (channelz_enabled && channel->is_client) { channel->channelz_channel = channel_node_create_func( channel, channel_tracer_max_nodes, !internal_channel); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index f947617d0f..4bfab4e2ee 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -146,20 +146,21 @@ class ChannelFixture { class ServerFixture { public: - ServerFixture(int max_trace_nodes = 0) { - grpc_arg server_a[2]; - server_a[0] = grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE), - max_trace_nodes); - server_a[1] = grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ENABLE_CHANNELZ), true); + explicit ServerFixture(int max_trace_nodes = 0) { + grpc_arg server_a[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENTS_PER_NODE), + max_trace_nodes), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_CHANNELZ), true), + }; grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; server_ = grpc_server_create(&server_args, nullptr); } ~ServerFixture() { grpc_server_destroy(server_); } - grpc_server* server() { return server_; } + grpc_server* server() const { return server_; } private: grpc_server* server_; diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index f96c430b69..40a0370f0e 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -240,7 +240,7 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); - // channel tracing is not enables, so these should not be preset. + // channel tracing is not enabled, so these should not be preset. GPR_ASSERT(nullptr == strstr(json, "\"trace\"")); GPR_ASSERT(nullptr == strstr(json, "\"description\":\"Channel created\"")); GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); @@ -252,7 +252,7 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr != strstr(json, "\"callsStarted\":\"2\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsFailed\":\"1\"")); GPR_ASSERT(nullptr != strstr(json, "\"callsSucceeded\":\"1\"")); - // channel tracing is not enables, so these should not be preset. + // channel tracing is not enabled, so these should not be preset. GPR_ASSERT(nullptr == strstr(json, "\"trace\"")); GPR_ASSERT(nullptr == strstr(json, "\"description\":\"Channel created\"")); GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); -- cgit v1.2.3 From 2ff5be8c08c75a2c2c0152694788aa1e5ed3d50d Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 10 Sep 2018 10:14:05 -0700 Subject: reveiwer comments --- .../ext/filters/client_channel/client_channel.cc | 128 +++++++++++---------- src/core/lib/channel/connected_channel.cc | 6 +- 2 files changed, 68 insertions(+), 66 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 4691aa1c97..388736b60a 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -936,7 +936,7 @@ typedef struct client_channel_call_data { // state needed to support channelz interception of recv trailing metadata. grpc_closure recv_trailing_metadata_ready_channelz; grpc_closure* original_recv_trailing_metadata; - grpc_metadata_batch* recv_trailing_metadata_batch; + grpc_metadata_batch* recv_trailing_metadata; grpc_polling_entity* pollent; bool pollent_added_to_interested_parties; @@ -999,7 +999,7 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem); static void on_complete(void* arg, grpc_error* error); static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored); static void start_pick_locked(void* arg, grpc_error* ignored); -static void maybe_intercept_metadata_for_channelz( +static void maybe_intercept_recv_trailing_metadata_for_channelz( grpc_call_element* elem, grpc_transport_stream_op_batch* batch); // @@ -1299,7 +1299,7 @@ static void pending_batches_resume(grpc_call_element* elem) { pending_batch* pending = &calld->pending_batches[i]; grpc_transport_stream_op_batch* batch = pending->batch; if (batch != nullptr) { - maybe_intercept_metadata_for_channelz(elem, batch); + maybe_intercept_recv_trailing_metadata_for_channelz(elem, batch); batch->handler_private.extra_arg = calld->subchannel_call; GRPC_CLOSURE_INIT(&batch->handler_private.closure, resume_pending_batch_in_call_combiner, batch, @@ -2589,6 +2589,69 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) { closures.RunClosures(calld->call_combiner); } +// +// Channelz +// + +static void recv_trailing_metadata_ready_channelz(void* arg, + grpc_error* error) { + grpc_call_element* elem = static_cast(arg); + channel_data* chand = static_cast(elem->channel_data); + call_data* calld = static_cast(elem->call_data); + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: got recv_trailing_metadata_ready_channelz, " + "error=%s", + chand, calld, grpc_error_string(error)); + } + GPR_ASSERT(calld->recv_trailing_metadata != nullptr); + grpc_status_code status = GRPC_STATUS_OK; + grpc_metadata_batch* md_batch = calld->recv_trailing_metadata; + get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, nullptr); + grpc_core::channelz::SubchannelNode* channelz_subchannel = + calld->pick.connected_subchannel->channelz_subchannel(); + GPR_ASSERT(channelz_subchannel != nullptr); + if (status == GRPC_STATUS_OK) { + channelz_subchannel->RecordCallSucceeded(); + } else { + channelz_subchannel->RecordCallFailed(); + } + calld->recv_trailing_metadata = nullptr; + GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata, error); +} + +// If channelz is enabled, intercept recv_trailing so that we may check the +// status and associate it to a subchannel. +// Returns true if callback was intercepted, false otherwise. +static void maybe_intercept_recv_trailing_metadata_for_channelz( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { + call_data* calld = static_cast(elem->call_data); + // only intercept payloads with recv trailing. + if (!batch->recv_trailing_metadata) { + return; + } + // only add interceptor is channelz is enabled. + if (calld->pick.connected_subchannel->channelz_subchannel() == nullptr) { + return; + } + if (grpc_client_channel_trace.enabled()) { + gpr_log(GPR_INFO, + "calld=%p batch=%p: intercepting recv trailing for channelz", calld, + batch); + } + GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_channelz, + recv_trailing_metadata_ready_channelz, elem, + grpc_schedule_on_exec_ctx); + // save some state needed for the interception callback. + GPR_ASSERT(calld->recv_trailing_metadata == nullptr); + calld->recv_trailing_metadata = + batch->payload->recv_trailing_metadata.recv_trailing_metadata; + calld->original_recv_trailing_metadata = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready_channelz; +} + // // LB pick // @@ -2669,65 +2732,6 @@ static void pick_done(void* arg, grpc_error* error) { } } -static void recv_trailing_metadata_ready_channelz(void* arg, - grpc_error* error) { - grpc_call_element* elem = static_cast(arg); - channel_data* chand = static_cast(elem->channel_data); - call_data* calld = static_cast(elem->call_data); - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: got recv_trailing_metadata_ready_channelz, " - "error=%s", - chand, calld, grpc_error_string(error)); - } - GPR_ASSERT(calld->recv_trailing_metadata_batch != nullptr); - grpc_status_code status = GRPC_STATUS_OK; - grpc_metadata_batch* md_batch = calld->recv_trailing_metadata_batch; - get_call_status(elem, md_batch, GRPC_ERROR_REF(error), &status, nullptr); - grpc_core::channelz::SubchannelNode* channelz_subchannel = - calld->pick.connected_subchannel->channelz_subchannel(); - GPR_ASSERT(channelz_subchannel != nullptr); - if (status == GRPC_STATUS_OK) { - channelz_subchannel->RecordCallSucceeded(); - } else { - channelz_subchannel->RecordCallFailed(); - } - calld->recv_trailing_metadata_batch = nullptr; - GRPC_CLOSURE_RUN(calld->original_recv_trailing_metadata, error); -} - -// If channelz is enabled, intercept recv_trailing so that we may check the -// status and associate it to a subchannel. -// Returns true if callback was intercepted, false otherwise. -static void maybe_intercept_metadata_for_channelz( - grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { - call_data* calld = static_cast(elem->call_data); - // only intercept payloads with recv trailing. - if (!batch->recv_trailing_metadata) { - return; - } - // only add interceptor is channelz is enabled. - if (calld->pick.connected_subchannel->channelz_subchannel() == nullptr) { - return; - } - if (grpc_client_channel_trace.enabled()) { - gpr_log(GPR_INFO, - "calld=%p batch=%p: intercepting recv trailing for channelz", calld, - batch); - } - GRPC_CLOSURE_INIT(&calld->recv_trailing_metadata_ready_channelz, - recv_trailing_metadata_ready_channelz, elem, - grpc_schedule_on_exec_ctx); - // save some state needed for the interception callback. - GPR_ASSERT(calld->recv_trailing_metadata_batch == nullptr); - calld->recv_trailing_metadata_batch = - batch->payload->recv_trailing_metadata.recv_trailing_metadata; - calld->original_recv_trailing_metadata = - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = - &calld->recv_trailing_metadata_ready_channelz; -} - static void maybe_add_call_to_channel_interested_parties_locked( grpc_call_element* elem) { channel_data* chand = static_cast(elem->channel_data); diff --git a/src/core/lib/channel/connected_channel.cc b/src/core/lib/channel/connected_channel.cc index 4a4f0e49d0..e2ea334ded 100644 --- a/src/core/lib/channel/connected_channel.cc +++ b/src/core/lib/channel/connected_channel.cc @@ -126,13 +126,11 @@ static void con_start_transport_stream_op_batch( // closure for each one. callback_state* state = static_cast(gpr_malloc(sizeof(*state))); - intercept_callback(calld, state, true, - "connected_on_complete (cancel_stream)", + intercept_callback(calld, state, true, "on_complete (cancel_stream)", &batch->on_complete); } else if (batch->on_complete != nullptr) { callback_state* state = get_state_for_batch(calld, batch); - intercept_callback(calld, state, false, "connected_on_complete", - &batch->on_complete); + intercept_callback(calld, state, false, "on_complete", &batch->on_complete); } grpc_transport_perform_stream_op( chand->transport, TRANSPORT_STREAM_FROM_CALL_DATA(calld), batch); -- cgit v1.2.3 From 11d3309130c7ed657fecf77b981a57cc48173753 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 10 Sep 2018 11:53:18 -0700 Subject: Make batch_error an atomic to avoid data races --- src/core/lib/surface/call.cc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'src/core') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index b07c4d6c10..90d812dad6 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -95,7 +95,7 @@ typedef struct batch_control { grpc_closure start_batch; grpc_closure finish_batch; gpr_refcount steps_to_complete; - grpc_error* batch_error; + gpr_atm batch_error; grpc_transport_stream_op_batch op; } batch_control; @@ -1106,14 +1106,16 @@ static void finish_batch_completion(void* user_data, } static void reset_batch_errors(batch_control* bctl) { - GRPC_ERROR_UNREF(bctl->batch_error); - bctl->batch_error = GRPC_ERROR_NONE; + GRPC_ERROR_UNREF( + reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error))); + gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_NONE); } static void post_batch_completion(batch_control* bctl) { grpc_call* next_child_call; grpc_call* call = bctl->call; - grpc_error* error = GRPC_ERROR_REF(bctl->batch_error); + grpc_error* error = GRPC_ERROR_REF( + reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error))); if (bctl->op.send_initial_metadata) { grpc_metadata_batch_destroy( @@ -1277,8 +1279,9 @@ static void receiving_stream_ready(void* bctlp, grpc_error* error) { grpc_call* call = bctl->call; if (error != GRPC_ERROR_NONE) { call->receiving_stream.reset(); - if (bctl->batch_error == GRPC_ERROR_NONE) { - bctl->batch_error = GRPC_ERROR_REF(error); + if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == + GRPC_ERROR_NONE) { + gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_REF(error)); } cancel_with_error(call, GRPC_ERROR_REF(error)); } @@ -1384,8 +1387,9 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { call->send_deadline = md->deadline; } } else { - if (bctl->batch_error == GRPC_ERROR_NONE) { - bctl->batch_error = GRPC_ERROR_REF(error); + if (reinterpret_cast gpr_atm_acq_load(&bctl->batch_error) == + GRPC_ERROR_NONE) { + gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_REF(error)); } cancel_with_error(call, GRPC_ERROR_REF(error)); } @@ -1435,8 +1439,9 @@ static void finish_batch(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; GRPC_CALL_COMBINER_STOP(&call->call_combiner, "on_complete"); - if (bctl->batch_error == GRPC_ERROR_NONE) { - bctl->batch_error = GRPC_ERROR_REF(error); + if (reinterpret_cast gpr_atm_acq_load(&bctl->batch_error) == + GRPC_ERROR_NONE) { + gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_REF(error)); } if (error != GRPC_ERROR_NONE) { cancel_with_error(call, GRPC_ERROR_REF(error)); -- cgit v1.2.3 From 796509b66d8245b2051f3c5dde642ff177f7b155 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Mon, 10 Sep 2018 13:11:34 -0700 Subject: Fix ubsan error in subchannel_list code. --- .../lb_policy/pick_first/pick_first.cc | 11 +++++----- .../lb_policy/round_robin/round_robin.cc | 11 +++++----- .../client_channel/lb_policy/subchannel_list.h | 24 ++++++++++++++-------- 3 files changed, 27 insertions(+), 19 deletions(-) (limited to 'src/core') diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index 602d6e92f9..ed8cc60ea1 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -71,11 +71,12 @@ class PickFirst : public LoadBalancingPolicy { : public SubchannelData { public: - PickFirstSubchannelData(PickFirstSubchannelList* subchannel_list, - const grpc_lb_user_data_vtable* user_data_vtable, - const grpc_lb_address& address, - grpc_subchannel* subchannel, - grpc_combiner* combiner) + PickFirstSubchannelData( + SubchannelList* + subchannel_list, + const grpc_lb_user_data_vtable* user_data_vtable, + const grpc_lb_address& address, grpc_subchannel* subchannel, + grpc_combiner* combiner) : SubchannelData(subchannel_list, user_data_vtable, address, subchannel, combiner) {} diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index 4195c1e9d1..8dd5820bae 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -89,11 +89,12 @@ class RoundRobin : public LoadBalancingPolicy { : public SubchannelData { public: - RoundRobinSubchannelData(RoundRobinSubchannelList* subchannel_list, - const grpc_lb_user_data_vtable* user_data_vtable, - const grpc_lb_address& address, - grpc_subchannel* subchannel, - grpc_combiner* combiner) + RoundRobinSubchannelData( + SubchannelList* + subchannel_list, + const grpc_lb_user_data_vtable* user_data_vtable, + const grpc_lb_address& address, grpc_subchannel* subchannel, + grpc_combiner* combiner) : SubchannelData(subchannel_list, user_data_vtable, address, subchannel, combiner), user_data_vtable_(user_data_vtable), diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h index d87de51082..5e8682e056 100644 --- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h @@ -65,6 +65,10 @@ class MySubchannelList namespace grpc_core { +// Forward declaration. +template +class SubchannelList; + // Stores data for a particular subchannel in a subchannel list. // Callers must create a subclass that implements the // ProcessConnectivityChangeLocked() method. @@ -72,7 +76,9 @@ template class SubchannelData { public: // Returns a pointer to the subchannel list containing this object. - SubchannelListType* subchannel_list() const { return subchannel_list_; } + SubchannelListType* subchannel_list() const { + return static_cast(subchannel_list_); + } // Returns the index into the subchannel list of this object. size_t Index() const { @@ -133,10 +139,11 @@ class SubchannelData { GRPC_ABSTRACT_BASE_CLASS protected: - SubchannelData(SubchannelListType* subchannel_list, - const grpc_lb_user_data_vtable* user_data_vtable, - const grpc_lb_address& address, grpc_subchannel* subchannel, - grpc_combiner* combiner); + SubchannelData( + SubchannelList* subchannel_list, + const grpc_lb_user_data_vtable* user_data_vtable, + const grpc_lb_address& address, grpc_subchannel* subchannel, + grpc_combiner* combiner); virtual ~SubchannelData(); @@ -161,7 +168,7 @@ class SubchannelData { static void OnConnectivityChangedLocked(void* arg, grpc_error* error); // Backpointer to owning subchannel list. Not owned. - SubchannelListType* subchannel_list_; + SubchannelList* subchannel_list_; // The subchannel and connected subchannel. grpc_subchannel* subchannel_; @@ -268,7 +275,7 @@ class SubchannelList template SubchannelData::SubchannelData( - SubchannelListType* subchannel_list, + SubchannelList* subchannel_list, const grpc_lb_user_data_vtable* user_data_vtable, const grpc_lb_address& address, grpc_subchannel* subchannel, grpc_combiner* combiner) @@ -532,8 +539,7 @@ SubchannelList::SubchannelList( address_uri); gpr_free(address_uri); } - subchannels_.emplace_back(static_cast(this), - addresses->user_data_vtable, + subchannels_.emplace_back(this, addresses->user_data_vtable, addresses->addresses[i], subchannel, combiner); } } -- cgit v1.2.3 From b6bb49dbf73805e4998ad6f4ac7adc94550e8d97 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 10 Sep 2018 14:20:01 -0700 Subject: reinterpret casts for compiler checks --- src/core/lib/surface/call.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 90d812dad6..ee7c15381a 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -1108,7 +1108,8 @@ static void finish_batch_completion(void* user_data, static void reset_batch_errors(batch_control* bctl) { GRPC_ERROR_UNREF( reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error))); - gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_NONE); + gpr_atm_rel_store(&bctl->batch_error, + reinterpret_cast(GRPC_ERROR_NONE)); } static void post_batch_completion(batch_control* bctl) { @@ -1281,7 +1282,8 @@ static void receiving_stream_ready(void* bctlp, grpc_error* error) { call->receiving_stream.reset(); if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == GRPC_ERROR_NONE) { - gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_REF(error)); + gpr_atm_rel_store(&bctl->batch_error, + reinterpret_cast(GRPC_ERROR_REF(error))); } cancel_with_error(call, GRPC_ERROR_REF(error)); } @@ -1387,9 +1389,10 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { call->send_deadline = md->deadline; } } else { - if (reinterpret_cast gpr_atm_acq_load(&bctl->batch_error) == + if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == GRPC_ERROR_NONE) { - gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_REF(error)); + gpr_atm_rel_store(&bctl->batch_error, + reinterpret_cast(GRPC_ERROR_REF(error))); } cancel_with_error(call, GRPC_ERROR_REF(error)); } @@ -1439,9 +1442,10 @@ static void finish_batch(void* bctlp, grpc_error* error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; GRPC_CALL_COMBINER_STOP(&call->call_combiner, "on_complete"); - if (reinterpret_cast gpr_atm_acq_load(&bctl->batch_error) == + if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == GRPC_ERROR_NONE) { - gpr_atm_rel_store(&bctl->batch_error, GRPC_ERROR_REF(error)); + gpr_atm_rel_store(&bctl->batch_error, + reinterpret_cast(GRPC_ERROR_REF(error))); } if (error != GRPC_ERROR_NONE) { cancel_with_error(call, GRPC_ERROR_REF(error)); -- cgit v1.2.3 From b9a174ab1507306fed5fa4ee70416e2489ef8fcb Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 11 Sep 2018 12:42:01 -0700 Subject: Add check on server for channelz accessor --- src/core/lib/surface/server.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/core') diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index c0fae0f140..5fa58ffdec 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -1500,5 +1500,8 @@ int grpc_server_has_open_connections(grpc_server* server) { grpc_core::channelz::ServerNode* grpc_server_get_channelz_node( grpc_server* server) { + if (server == nullptr) { + return nullptr; + } return server->channelz_server.get(); } -- cgit v1.2.3 From 964d679edc32b0f7316cacdb0652477d607f6de5 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Tue, 21 Aug 2018 08:00:49 -0700 Subject: Resolve ip literals and Windows localhost manually when using c-ares --- CMakeLists.txt | 38 ++++++++- Makefile | 58 ++++++++++--- build.yaml | 16 +++- .../ext/filters/client_channel/parse_address.cc | 9 ++ .../ext/filters/client_channel/parse_address.h | 3 + .../resolver/dns/c_ares/grpc_ares_wrapper.cc | 99 +++++++++++++++++----- .../resolver/dns/c_ares/grpc_ares_wrapper.h | 12 ++- .../resolver/dns/c_ares/grpc_ares_wrapper_posix.cc | 5 ++ .../dns/c_ares/grpc_ares_wrapper_windows.cc | 70 +++++++++++++++ test/core/iomgr/BUILD | 20 ++++- test/core/iomgr/resolve_address_test.cc | 40 ++++++++- test/cpp/naming/address_sorting_test.cc | 52 ++++++------ tools/run_tests/generated/sources_and_headers.json | 19 ++++- tools/run_tests/generated/tests.json | 32 ++++++- 14 files changed, 403 insertions(+), 70 deletions(-) (limited to 'src/core') diff --git a/CMakeLists.txt b/CMakeLists.txt index a21bb8b5fa..4cbc7597ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -361,7 +361,8 @@ endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c resolve_address_posix_test) endif() -add_dependencies(buildtests_c resolve_address_test) +add_dependencies(buildtests_c resolve_address_using_ares_resolver_test) +add_dependencies(buildtests_c resolve_address_using_native_resolver_test) add_dependencies(buildtests_c resource_quota_test) add_dependencies(buildtests_c secure_channel_create_test) add_dependencies(buildtests_c secure_endpoint_test) @@ -8553,12 +8554,12 @@ endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) -add_executable(resolve_address_test +add_executable(resolve_address_using_ares_resolver_test test/core/iomgr/resolve_address_test.cc ) -target_include_directories(resolve_address_test +target_include_directories(resolve_address_using_ares_resolver_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${_gRPC_SSL_INCLUDE_DIR} @@ -8571,7 +8572,36 @@ target_include_directories(resolve_address_test PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} ) -target_link_libraries(resolve_address_test +target_link_libraries(resolve_address_using_ares_resolver_test + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr_test_util + gpr +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + +add_executable(resolve_address_using_native_resolver_test + test/core/iomgr/resolve_address_test.cc +) + + +target_include_directories(resolve_address_using_native_resolver_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} +) + +target_link_libraries(resolve_address_using_native_resolver_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc diff --git a/Makefile b/Makefile index 96ea890bcb..85de7b67c5 100644 --- a/Makefile +++ b/Makefile @@ -1081,7 +1081,8 @@ percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer percent_encoding_test: $(BINDIR)/$(CONFIG)/percent_encoding_test pollset_set_test: $(BINDIR)/$(CONFIG)/pollset_set_test resolve_address_posix_test: $(BINDIR)/$(CONFIG)/resolve_address_posix_test -resolve_address_test: $(BINDIR)/$(CONFIG)/resolve_address_test +resolve_address_using_ares_resolver_test: $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test +resolve_address_using_native_resolver_test: $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test resource_quota_test: $(BINDIR)/$(CONFIG)/resource_quota_test secure_channel_create_test: $(BINDIR)/$(CONFIG)/secure_channel_create_test secure_endpoint_test: $(BINDIR)/$(CONFIG)/secure_endpoint_test @@ -1524,7 +1525,8 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/percent_encoding_test \ $(BINDIR)/$(CONFIG)/pollset_set_test \ $(BINDIR)/$(CONFIG)/resolve_address_posix_test \ - $(BINDIR)/$(CONFIG)/resolve_address_test \ + $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test \ + $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test \ $(BINDIR)/$(CONFIG)/resource_quota_test \ $(BINDIR)/$(CONFIG)/secure_channel_create_test \ $(BINDIR)/$(CONFIG)/secure_endpoint_test \ @@ -2118,8 +2120,10 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/pollset_set_test || ( echo test pollset_set_test failed ; exit 1 ) $(E) "[RUN] Testing resolve_address_posix_test" $(Q) $(BINDIR)/$(CONFIG)/resolve_address_posix_test || ( echo test resolve_address_posix_test failed ; exit 1 ) - $(E) "[RUN] Testing resolve_address_test" - $(Q) $(BINDIR)/$(CONFIG)/resolve_address_test || ( echo test resolve_address_test failed ; exit 1 ) + $(E) "[RUN] Testing resolve_address_using_ares_resolver_test" + $(Q) $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test || ( echo test resolve_address_using_ares_resolver_test failed ; exit 1 ) + $(E) "[RUN] Testing resolve_address_using_native_resolver_test" + $(Q) $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test || ( echo test resolve_address_using_native_resolver_test failed ; exit 1 ) $(E) "[RUN] Testing resource_quota_test" $(Q) $(BINDIR)/$(CONFIG)/resource_quota_test || ( echo test resource_quota_test failed ; exit 1 ) $(E) "[RUN] Testing secure_channel_create_test" @@ -14031,34 +14035,66 @@ endif endif -RESOLVE_ADDRESS_TEST_SRC = \ +RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_SRC = \ test/core/iomgr/resolve_address_test.cc \ -RESOLVE_ADDRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_TEST_SRC)))) +RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. -$(BINDIR)/$(CONFIG)/resolve_address_test: openssl_dep_error +$(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test: openssl_dep_error else -$(BINDIR)/$(CONFIG)/resolve_address_test: $(RESOLVE_ADDRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test: $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(RESOLVE_ADDRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/resolve_address_test + $(Q) $(LD) $(LDFLAGS) $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/resolve_address_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_resolve_address_test: $(RESOLVE_ADDRESS_TEST_OBJS:.o=.dep) +deps_resolve_address_using_ares_resolver_test: $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) --include $(RESOLVE_ADDRESS_TEST_OBJS:.o=.dep) +-include $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_OBJS:.o=.dep) +endif +endif + + +RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_SRC = \ + test/core/iomgr/resolve_address_test.cc \ + +RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test: $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/resolve_address_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_resolve_address_using_native_resolver_test: $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_OBJS:.o=.dep) endif endif diff --git a/build.yaml b/build.yaml index a50a0a4ab6..b354826128 100644 --- a/build.yaml +++ b/build.yaml @@ -3363,7 +3363,7 @@ targets: - mac - linux - posix -- name: resolve_address_test +- name: resolve_address_using_ares_resolver_test build: test language: c src: @@ -3373,6 +3373,20 @@ targets: - grpc - gpr_test_util - gpr + args: + - --resolver=ares +- name: resolve_address_using_native_resolver_test + build: test + language: c + src: + - test/core/iomgr/resolve_address_test.cc + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr + args: + - --resolver=native - name: resource_quota_test cpu_cost: 30 build: test diff --git a/src/core/ext/filters/client_channel/parse_address.cc b/src/core/ext/filters/client_channel/parse_address.cc index 7e726dd562..b94429e207 100644 --- a/src/core/ext/filters/client_channel/parse_address.cc +++ b/src/core/ext/filters/client_channel/parse_address.cc @@ -197,3 +197,12 @@ bool grpc_parse_uri(const grpc_uri* uri, grpc_resolved_address* resolved_addr) { gpr_log(GPR_ERROR, "Can't parse scheme '%s'", uri->scheme); return false; } + +uint16_t grpc_strhtons(const char* port) { + if (strcmp(port, "http") == 0) { + return htons(80); + } else if (strcmp(port, "https") == 0) { + return htons(443); + } + return htons(static_cast(atoi(port))); +} diff --git a/src/core/ext/filters/client_channel/parse_address.h b/src/core/ext/filters/client_channel/parse_address.h index 9a88b66edc..c2af0e6c49 100644 --- a/src/core/ext/filters/client_channel/parse_address.h +++ b/src/core/ext/filters/client_channel/parse_address.h @@ -47,4 +47,7 @@ bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr, bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr, bool log_errors); +/* Converts named or numeric port to a uint16 suitable for use in a sockaddr. */ +uint16_t grpc_strhtons(const char* port); + #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc index 485998f5e4..4c795c34c8 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc @@ -87,15 +87,6 @@ typedef struct grpc_ares_hostbyname_request { static void do_basic_init(void) { gpr_mu_init(&g_init_mu); } -static uint16_t strhtons(const char* port) { - if (strcmp(port, "http") == 0) { - return htons(80); - } else if (strcmp(port, "https") == 0) { - return htons(443); - } - return htons(static_cast(atoi(port))); -} - static void log_address_sorting_list(grpc_lb_addresses* lb_addrs, const char* input_output_str) { for (size_t i = 0; i < lb_addrs->num_addresses; i++) { @@ -139,12 +130,6 @@ void grpc_cares_wrapper_address_sorting_sort(grpc_lb_addresses* lb_addrs) { } } -/* Allow tests to access grpc_ares_wrapper_address_sorting_sort */ -void grpc_cares_wrapper_test_only_address_sorting_sort( - grpc_lb_addresses* lb_addrs) { - grpc_cares_wrapper_address_sorting_sort(lb_addrs); -} - static void grpc_ares_request_ref_locked(grpc_ares_request* r) { r->pending_queries++; } @@ -371,7 +356,8 @@ done: grpc_ares_request_unref_locked(r); } -static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( +static grpc_ares_request* +grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json, @@ -454,12 +440,12 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( } r->pending_queries = 1; if (grpc_ares_query_ipv6()) { - hr = create_hostbyname_request_locked(r, host, strhtons(port), + hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port), false /* is_balancer */); ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked, hr); } - hr = create_hostbyname_request_locked(r, host, strhtons(port), + hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port), false /* is_balancer */); ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_locked, hr); @@ -494,6 +480,79 @@ error_cleanup: return nullptr; } +static bool inner_resolve_as_ip_literal_locked(const char* name, + const char* default_port, + grpc_lb_addresses** addrs, + char** host, char** port, + char** hostport) { + gpr_split_host_port(name, host, port); + if (*host == nullptr) { + gpr_log(GPR_ERROR, + "Failed to parse %s to host:port while attempting to resolve as ip " + "literal.", + name); + return false; + } + if (*port == nullptr) { + if (default_port == nullptr) { + gpr_log(GPR_ERROR, + "No port or default port for %s while attempting to resolve as " + "ip literal.", + name); + return false; + } + *port = gpr_strdup(default_port); + } + grpc_resolved_address addr; + GPR_ASSERT(gpr_join_host_port(hostport, *host, atoi(*port))); + if (grpc_parse_ipv4_hostport(*hostport, &addr, false /* log errors */) || + grpc_parse_ipv6_hostport(*hostport, &addr, false /* log errors */)) { + GPR_ASSERT(*addrs == nullptr); + *addrs = grpc_lb_addresses_create(1, nullptr); + grpc_lb_addresses_set_address( + *addrs, 0, addr.addr, addr.len, false /* is_balancer */, + nullptr /* balancer_name */, nullptr /* user_data */); + return true; + } + return false; +} + +static bool resolve_as_ip_literal_locked(const char* name, + const char* default_port, + grpc_lb_addresses** addrs) { + char* host = nullptr; + char* port = nullptr; + char* hostport = nullptr; + bool out = inner_resolve_as_ip_literal_locked(name, default_port, addrs, + &host, &port, &hostport); + gpr_free(host); + gpr_free(port); + gpr_free(hostport); + return out; +} + +static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( + const char* dns_server, const char* name, const char* default_port, + grpc_pollset_set* interested_parties, grpc_closure* on_done, + grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json, + grpc_combiner* combiner) { + // Early out if the target is an ipv4 or ipv6 literal. + if (resolve_as_ip_literal_locked(name, default_port, addrs)) { + GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE); + return nullptr; + } + // Early out if the target is localhost and we're on Windows. + if (grpc_ares_maybe_resolve_localhost_manually_locked(name, default_port, + addrs)) { + GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE); + return nullptr; + } + // Look up name using c-ares lib. + return grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( + dns_server, name, default_port, interested_parties, on_done, addrs, + check_grpclb, service_config_json, combiner); +} + grpc_ares_request* (*grpc_dns_lookup_ares_locked)( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, @@ -502,7 +561,9 @@ grpc_ares_request* (*grpc_dns_lookup_ares_locked)( void grpc_cancel_ares_request(grpc_ares_request* r) { if (grpc_dns_lookup_ares_locked == grpc_dns_lookup_ares_locked_impl) { - grpc_ares_ev_driver_shutdown_locked(r->ev_driver); + if (r != nullptr) { + grpc_ares_ev_driver_shutdown_locked(r->ev_driver); + } } } diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h index ca5779e1d7..1bc457d4cf 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h @@ -81,9 +81,15 @@ void grpc_ares_complete_request_locked(grpc_ares_request* request); /* E.g., return false if ipv6 is known to not be available. */ bool grpc_ares_query_ipv6(); -/* Exposed only for testing */ -void grpc_cares_wrapper_test_only_address_sorting_sort( - grpc_lb_addresses* lb_addrs); +/* Maybe (depending on the current platform) checks if "name" matches + * "localhost" and if so fills in addrs with the correct sockaddr structures. + * Returns a bool indicating whether or not such an action was performed. + * See https://github.com/grpc/grpc/issues/15158. */ +bool grpc_ares_maybe_resolve_localhost_manually_locked( + const char* name, const char* default_port, grpc_lb_addresses** addrs); + +/* Sorts destinations in lb_addrs according to RFC 6724. */ +void grpc_cares_wrapper_address_sorting_sort(grpc_lb_addresses* lb_addrs); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_WRAPPER_H \ */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc index 23c0fec74f..639eec2323 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc @@ -26,4 +26,9 @@ bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } +bool grpc_ares_maybe_resolve_localhost_manually_locked( + const char* name, const char* default_port, grpc_lb_addresses** addrs) { + return false; +} + #endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc index ee827e284e..7e34784691 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc @@ -21,9 +21,79 @@ #include "src/core/lib/iomgr/port.h" #if GRPC_ARES == 1 && defined(GPR_WINDOWS) +#include + +#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/lib/gpr/host_port.h" +#include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/socket_windows.h" bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } +static bool inner_maybe_resolve_localhost_manually_locked( + const char* name, const char* default_port, grpc_lb_addresses** addrs, + char** host, char** port) { + gpr_split_host_port(name, host, port); + if (*host == nullptr) { + gpr_log(GPR_ERROR, + "Failed to parse %s into host:port during Windows localhost " + "resolution check.", + name); + return false; + } + if (*port == nullptr) { + if (default_port == nullptr) { + gpr_log(GPR_ERROR, + "No port or default port for %s during Windows localhost " + "resolution check.", + name); + return false; + } + *port = gpr_strdup(default_port); + } + if (gpr_stricmp(*host, "localhost") == 0) { + GPR_ASSERT(*addrs == nullptr); + *addrs = grpc_lb_addresses_create(2, nullptr); + uint16_t numeric_port = grpc_strhtons(*port); + // Append the ipv6 loopback address. + struct sockaddr_in6 ipv6_loopback_addr; + memset(&ipv6_loopback_addr, 0, sizeof(ipv6_loopback_addr)); + ((char*)&ipv6_loopback_addr.sin6_addr)[15] = 1; + ipv6_loopback_addr.sin6_family = AF_INET6; + ipv6_loopback_addr.sin6_port = numeric_port; + grpc_lb_addresses_set_address( + *addrs, 0, &ipv6_loopback_addr, sizeof(ipv6_loopback_addr), + false /* is_balancer */, nullptr /* balancer_name */, + nullptr /* user_data */); + // Append the ipv4 loopback address. + struct sockaddr_in ipv4_loopback_addr; + memset(&ipv4_loopback_addr, 0, sizeof(ipv4_loopback_addr)); + ((char*)&ipv4_loopback_addr.sin_addr)[0] = 0x7f; + ((char*)&ipv4_loopback_addr.sin_addr)[3] = 0x01; + ipv4_loopback_addr.sin_family = AF_INET; + ipv4_loopback_addr.sin_port = numeric_port; + grpc_lb_addresses_set_address( + *addrs, 1, &ipv4_loopback_addr, sizeof(ipv4_loopback_addr), + false /* is_balancer */, nullptr /* balancer_name */, + nullptr /* user_data */); + // Let the address sorter figure out which one should be tried first. + grpc_cares_wrapper_address_sorting_sort(*addrs); + return true; + } + return false; +} + +bool grpc_ares_maybe_resolve_localhost_manually_locked( + const char* name, const char* default_port, grpc_lb_addresses** addrs) { + char* host = nullptr; + char* port = nullptr; + bool out = inner_maybe_resolve_localhost_manually_locked(name, default_port, + addrs, &host, &port); + gpr_free(host); + gpr_free(port); + return out; +} + #endif /* GRPC_ARES == 1 && defined(GPR_WINDOWS) */ diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index 675d9e6278..7754bc4970 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -174,9 +174,27 @@ grpc_cc_test( ) grpc_cc_test( - name = "resolve_address_test", + name = "resolve_address_using_ares_resolver_test", srcs = ["resolve_address_test.cc"], language = "C++", + args = [ + "--resolver=ares", + ], + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + +grpc_cc_test( + name = "resolve_address_using_native_resolver_test", + srcs = ["resolve_address_test.cc"], + language = "C++", + args = [ + "--resolver=native", + ], deps = [ "//:gpr", "//:grpc", diff --git a/test/core/iomgr/resolve_address_test.cc b/test/core/iomgr/resolve_address_test.cc index 2fb831a6a4..52e4840c7c 100644 --- a/test/core/iomgr/resolve_address_test.cc +++ b/test/core/iomgr/resolve_address_test.cc @@ -22,8 +22,14 @@ #include #include #include + +#include + +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" +#include "test/core/util/cmdline.h" #include "test/core/util/test_config.h" static gpr_timespec test_deadline(void) { @@ -240,6 +246,28 @@ static void test_unparseable_hostports(void) { } int main(int argc, char** argv) { + // First set the resolver type based off of --resolver + const char* resolver_type = nullptr; + gpr_cmdline* cl = gpr_cmdline_create("resolve address test"); + gpr_cmdline_add_string(cl, "resolver", "Resolver type (ares or native)", + &resolver_type); + gpr_cmdline_parse(cl, argc, argv); + const char* cur_resolver = gpr_getenv("GRPC_DNS_RESOLVER"); + if (cur_resolver != nullptr && strlen(cur_resolver) != 0) { + gpr_log(GPR_INFO, "Warning: overriding resolver setting of %s", + cur_resolver); + } + if (gpr_stricmp(resolver_type, "native") == 0) { + gpr_setenv("GRPC_DNS_RESOLVER", "native"); + } else if (gpr_stricmp(resolver_type, "ares") == 0) { +#ifndef GRPC_UV + gpr_setenv("GRPC_DNS_RESOLVER", "ares"); +#endif + } else { + gpr_log(GPR_ERROR, "--resolver_type was not set to ares or native"); + abort(); + } + // Run the test. grpc_test_init(argc, argv); grpc_init(); { @@ -250,10 +278,18 @@ int main(int argc, char** argv) { test_missing_default_port(); test_ipv6_with_port(); test_ipv6_without_port(); - test_invalid_ip_addresses(); - test_unparseable_hostports(); + if (gpr_stricmp(resolver_type, "ares") != 0) { + // These tests can trigger DNS queries to the nearby nameserver + // that need to come back in order for the test to succeed. + // c-ares is prone to not using the local system caches that the + // native getaddrinfo implementations take advantage of, so running + // these unit tests under c-ares risks flakiness. + test_invalid_ip_addresses(); + test_unparseable_hostports(); + } grpc_executor_shutdown(); } + gpr_cmdline_destroy(cl); grpc_shutdown(); return 0; diff --git a/test/cpp/naming/address_sorting_test.cc b/test/cpp/naming/address_sorting_test.cc index 04c300876c..fc6721d0ba 100644 --- a/test/cpp/naming/address_sorting_test.cc +++ b/test/cpp/naming/address_sorting_test.cc @@ -216,7 +216,7 @@ TEST_F(AddressSortingTest, TestDepriotizesUnreachableAddresses) { {"1.2.3.4:443", AF_INET}, {"5.6.7.8:443", AF_INET}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "1.2.3.4:443", "5.6.7.8:443", @@ -235,7 +235,7 @@ TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) { {"[2607:f8b0:400a:801::1002]:443", AF_INET6}, {"1.2.3.4:443", AF_INET}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "1.2.3.4:443", "[2607:f8b0:400a:801::1002]:443", @@ -255,7 +255,7 @@ TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) { {"[2607:f8b0:400a:801::1002]:443", AF_INET6}, {"1.2.3.4:443", AF_INET}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[2607:f8b0:400a:801::1002]:443", "1.2.3.4:443", @@ -279,7 +279,7 @@ TEST_F(AddressSortingTest, TestDepriotizesNonMatchingScope) { {"[2000:f8b0:400a:801::1002]:443", AF_INET6}, {"[fec0::5000]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[fec0::5000]:443", "[2000:f8b0:400a:801::1002]:443", @@ -302,7 +302,7 @@ TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTable) { {"[2002::5001]:443", AF_INET6}, {"[2001::5001]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[2001::5001]:443", "[2002::5001]:443", @@ -325,7 +325,7 @@ TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) { {"[2001::5001]:443", AF_INET6}, {"[2002::5001]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[2001::5001]:443", "[2002::5001]:443", @@ -348,7 +348,7 @@ TEST_F(AddressSortingTest, {"[3ffe::5001]:443", AF_INET6}, {"1.2.3.4:443", AF_INET}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs( lb_addrs, { // The AF_INET address should be IPv4-mapped by the sort, @@ -381,7 +381,7 @@ TEST_F(AddressSortingTest, {v4_compat_dest, AF_INET6}, {"[::1]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[::1]:443", v4_compat_dest, @@ -404,7 +404,7 @@ TEST_F(AddressSortingTest, {"[1234::2]:443", AF_INET6}, {"[::1]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs( lb_addrs, { @@ -428,7 +428,7 @@ TEST_F(AddressSortingTest, {"[2001::1234]:443", AF_INET6}, {"[2000::5001]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs( lb_addrs, { // The 2000::/16 address should match the ::/0 prefix rule @@ -452,7 +452,7 @@ TEST_F( {"[2001::1231]:443", AF_INET6}, {"[2000::5001]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[2000::5001]:443", "[2001::1231]:443", @@ -473,7 +473,7 @@ TEST_F(AddressSortingTest, {"[fec0::1234]:443", AF_INET6}, {"[fc00::5001]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[fc00::5001]:443", "[fec0::1234]:443", @@ -498,7 +498,7 @@ TEST_F( {"[::ffff:1.1.1.2]:443", AF_INET6}, {"[1234::2]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { // ::ffff:0:2 should match the v4-mapped // precedence entry and be deprioritized. @@ -525,7 +525,7 @@ TEST_F(AddressSortingTest, TestPrefersSmallerScope) { {"[3ffe::5001]:443", AF_INET6}, {"[fec0::1234]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[fec0::1234]:443", "[3ffe::5001]:443", @@ -550,7 +550,7 @@ TEST_F(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) { {"[3ffe:5001::]:443", AF_INET6}, {"[3ffe:1234::]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe:1234::]:443", "[3ffe:5001::]:443", @@ -571,7 +571,7 @@ TEST_F(AddressSortingTest, {"[3ffe::5001]:443", AF_INET6}, {"[3ffe::1234]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe::1234]:443", "[3ffe::5001]:443", @@ -591,7 +591,7 @@ TEST_F(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) { {"[3ffe:8000::]:443", AF_INET6}, {"[3ffe:2000::]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe:2000::]:443", "[3ffe:8000::]:443", @@ -611,7 +611,7 @@ TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) { {"[3ffe:6::]:443", AF_INET6}, {"[3ffe:c::]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe:c::]:443", "[3ffe:6::]:443", @@ -633,7 +633,7 @@ TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) { {"[3ffe:1111:1111:1110::]:443", AF_INET6}, {"[3ffe:1111:1111:1111::]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe:1111:1111:1111::]:443", "[3ffe:1111:1111:1110::]:443", @@ -655,7 +655,7 @@ TEST_F(AddressSortingTest, TestStableSort) { {"[3ffe::1234]:443", AF_INET6}, {"[3ffe::1235]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe::1234]:443", "[3ffe::1235]:443", @@ -681,7 +681,7 @@ TEST_F(AddressSortingTest, TestStableSortFiveElements) { {"[3ffe::1234]:443", AF_INET6}, {"[3ffe::1235]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe::1231]:443", "[3ffe::1232]:443", @@ -702,7 +702,7 @@ TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExist) { {"[3ffe::1234]:443", AF_INET6}, {"[3ffe::1235]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe::1231]:443", "[3ffe::1232]:443", @@ -720,7 +720,7 @@ TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) { {"[::ffff:5.6.7.8]:443", AF_INET6}, {"1.2.3.4:443", AF_INET}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[::ffff:5.6.7.8]:443", "1.2.3.4:443", @@ -748,7 +748,7 @@ TEST_F(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) { {"[fec0::2000]:443", AF_INET6}, {v4_compat_dest, AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { // The sort should be stable since @@ -769,7 +769,7 @@ TEST_F(AddressSortingTest, TestPrefersIpv6Loopback) { {"[::1]:443", AF_INET6}, {"127.0.0.1:443", AF_INET}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[::1]:443", "127.0.0.1:443", @@ -783,7 +783,7 @@ TEST_F(AddressSortingTest, TestPrefersIpv6LoopbackInputsFlipped) { {"127.0.0.1:443", AF_INET}, {"[::1]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[::1]:443", "127.0.0.1:443", diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8ea5126fde..5d6113bc18 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -1897,7 +1897,24 @@ "headers": [], "is_filegroup": false, "language": "c", - "name": "resolve_address_test", + "name": "resolve_address_using_ares_resolver_test", + "src": [ + "test/core/iomgr/resolve_address_test.cc" + ], + "third_party": false, + "type": "target" + }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "resolve_address_using_native_resolver_test", "src": [ "test/core/iomgr/resolve_address_test.cc" ], diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index fba76d69d1..0ecc8a120a 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -2146,7 +2146,35 @@ "uses_polling": true }, { - "args": [], + "args": [ + "--resolver=ares" + ], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "resolve_address_using_ares_resolver_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, + { + "args": [ + "--resolver=native" + ], "benchmark": false, "ci_platforms": [ "linux", @@ -2160,7 +2188,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "resolve_address_test", + "name": "resolve_address_using_native_resolver_test", "platforms": [ "linux", "mac", -- cgit v1.2.3 From 157e7fa03e600a4156a2913f8f645c5af4270408 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 11 Sep 2018 14:33:40 -0700 Subject: fix clang tidy --- include/grpc/grpc.h | 2 +- src/core/lib/channel/channel_trace.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index ce421e93bd..3ef95ff462 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -500,7 +500,7 @@ GRPCAPI const grpc_arg_pointer_vtable* grpc_resource_quota_arg_vtable(void); GRPCAPI char* grpc_channelz_get_top_channels(intptr_t start_channel_id); /* Gets all servers that exist in the process. */ -GRPCAPI char* grpc_channelz_get_servers(intptr_t start_channel_id); +GRPCAPI char* grpc_channelz_get_servers(intptr_t start_server_id); /* Returns a single Channel, or else a NOT_FOUND code. The returned string is allocated and must be freed by the application. */ diff --git a/src/core/lib/channel/channel_trace.h b/src/core/lib/channel/channel_trace.h index 230faa483e..94fea20b45 100644 --- a/src/core/lib/channel/channel_trace.h +++ b/src/core/lib/channel/channel_trace.h @@ -63,7 +63,7 @@ class ChannelTrace { // stack, determine if it makes more sense to accept a char* instead of a // slice. void AddTraceEventWithReference(Severity severity, grpc_slice data, - RefCountedPtr referenced_channel); + RefCountedPtr referenced_entity); // Creates and returns the raw grpc_json object, so a parent channelz // object may incorporate the json before rendering. -- cgit v1.2.3 From 2f6640f005196d71cb27d9d47e06cb130fd84502 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 12 Sep 2018 17:09:01 -0700 Subject: Add logging to be sure about set values --- src/core/lib/iomgr/socket_utils_common_posix.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/core') diff --git a/src/core/lib/iomgr/socket_utils_common_posix.cc b/src/core/lib/iomgr/socket_utils_common_posix.cc index 4ef3d8319f..50674b0845 100644 --- a/src/core/lib/iomgr/socket_utils_common_posix.cc +++ b/src/core/lib/iomgr/socket_utils_common_posix.cc @@ -287,6 +287,11 @@ grpc_error* grpc_set_socket_tcp_user_timeout( } } if (enable) { + extern grpc_core::TraceFlag grpc_tcp_trace; + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "Enabling TCP_USER_TIMEOUT with a timeout of %d ms", + timeout); + } int newval; socklen_t len = sizeof(newval); if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, -- cgit v1.2.3