aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/ext
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/ext')
-rw-r--r--src/core/ext/filters/client_channel/client_channel.cc10
-rw-r--r--src/core/ext/filters/client_channel/client_channel.h6
-rw-r--r--src/core/ext/filters/client_channel/client_channel_channelz.cc31
-rw-r--r--src/core/ext/filters/client_channel/client_channel_channelz.h8
-rw-r--r--src/core/ext/filters/client_channel/lb_policy.cc17
-rw-r--r--src/core/ext/filters/client_channel/lb_policy.h17
-rw-r--r--src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc51
-rw-r--r--src/core/ext/filters/client_channel/subchannel.cc12
-rw-r--r--src/core/ext/filters/client_channel/subchannel.h2
9 files changed, 153 insertions, 1 deletions
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index 520431e63b..8c3e9f2b30 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -3159,6 +3159,16 @@ static void try_to_connect_locked(void* arg, grpc_error* error_ignored) {
GRPC_CHANNEL_STACK_UNREF(chand->owning_stack, "try_to_connect");
}
+void grpc_client_channel_populate_child_refs(
+ grpc_channel_element* elem, grpc_core::ChildRefsList* child_subchannels,
+ grpc_core::ChildRefsList* child_channels) {
+ channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+ if (chand->lb_policy) {
+ chand->lb_policy->FillChildRefsForChannelz(child_subchannels,
+ child_channels);
+ }
+}
+
grpc_connectivity_state grpc_client_channel_check_connectivity_state(
grpc_channel_element* elem, int try_to_connect) {
channel_data* chand = static_cast<channel_data*>(elem->channel_data);
diff --git a/src/core/ext/filters/client_channel/client_channel.h b/src/core/ext/filters/client_channel/client_channel.h
index a21e5623a7..0f95f6670a 100644
--- a/src/core/ext/filters/client_channel/client_channel.h
+++ b/src/core/ext/filters/client_channel/client_channel.h
@@ -21,9 +21,11 @@
#include <grpc/support/port_platform.h>
+#include "src/core/ext/filters/client_channel/client_channel_channelz.h"
#include "src/core/ext/filters/client_channel/client_channel_factory.h"
#include "src/core/ext/filters/client_channel/resolver.h"
#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/json/json.h"
extern grpc_core::TraceFlag grpc_client_channel_trace;
@@ -39,6 +41,10 @@ extern grpc_core::TraceFlag grpc_client_channel_trace;
extern const grpc_channel_filter grpc_client_channel_filter;
+void grpc_client_channel_populate_child_refs(
+ grpc_channel_element* elem, grpc_core::ChildRefsList* child_subchannels,
+ grpc_core::ChildRefsList* child_channels);
+
grpc_connectivity_state grpc_client_channel_check_connectivity_state(
grpc_channel_element* elem, int try_to_connect);
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 08ceb2dd05..235b8f3207 100644
--- a/src/core/ext/filters/client_channel/client_channel_channelz.cc
+++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc
@@ -63,6 +63,37 @@ void ClientChannelNode::PopulateConnectivityState(grpc_json* json) {
false);
}
+void ClientChannelNode::PopulateChildRefs(grpc_json* json) {
+ ChildRefsList child_subchannels;
+ ChildRefsList child_channels;
+ grpc_json* json_iterator = nullptr;
+ grpc_client_channel_populate_child_refs(client_channel_, &child_subchannels,
+ &child_channels);
+ if (child_subchannels.size() > 0) {
+ grpc_json* array_parent = grpc_json_create_child(
+ nullptr, json, "subchannelRef", nullptr, GRPC_JSON_ARRAY, false);
+ for (size_t i = 0; i < child_subchannels.size(); ++i) {
+ json_iterator =
+ grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr,
+ GRPC_JSON_OBJECT, false);
+ grpc_json_add_number_string_child(json_iterator, nullptr, "subchannelId",
+ child_subchannels[i]);
+ }
+ }
+ if (child_channels.size() > 0) {
+ grpc_json* array_parent = grpc_json_create_child(
+ nullptr, json, "channelRef", nullptr, GRPC_JSON_ARRAY, false);
+ json_iterator = nullptr;
+ for (size_t i = 0; i < child_subchannels.size(); ++i) {
+ json_iterator =
+ grpc_json_create_child(json_iterator, array_parent, nullptr, nullptr,
+ GRPC_JSON_OBJECT, false);
+ grpc_json_add_number_string_child(json_iterator, nullptr, "channelId",
+ child_subchannels[i]);
+ }
+ }
+}
+
grpc_arg ClientChannelNode::CreateChannelArg() {
return grpc_channel_arg_pointer_create(
const_cast<char*>(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 cf3ef7b6f2..e5be52e778 100644
--- a/src/core/ext/filters/client_channel/client_channel_channelz.h
+++ b/src/core/ext/filters/client_channel/client_channel_channelz.h
@@ -22,9 +22,14 @@
#include <grpc/support/port_platform.h>
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/channelz.h"
+#include "src/core/lib/gprpp/inlined_vector.h"
namespace grpc_core {
+
+typedef InlinedVector<intptr_t, 10> ChildRefsList;
+
namespace channelz {
// Subtype of ChannelNode that overrides and provides client_channel specific
@@ -38,6 +43,9 @@ class ClientChannelNode : public ChannelNode {
// channel connectivity.
void PopulateConnectivityState(grpc_json* json) override;
+ // Override this functionality since client_channels have subchannels
+ void PopulateChildRefs(grpc_json* json) override;
+
// Helper to create a channel arg to ensure this type of ChannelNode is
// created.
static grpc_arg CreateChannelArg();
diff --git a/src/core/ext/filters/client_channel/lb_policy.cc b/src/core/ext/filters/client_channel/lb_policy.cc
index e065f45639..a0d7758f23 100644
--- a/src/core/ext/filters/client_channel/lb_policy.cc
+++ b/src/core/ext/filters/client_channel/lb_policy.cc
@@ -31,13 +31,28 @@ LoadBalancingPolicy::LoadBalancingPolicy(const Args& args)
combiner_(GRPC_COMBINER_REF(args.combiner, "lb_policy")),
client_channel_factory_(args.client_channel_factory),
interested_parties_(grpc_pollset_set_create()),
- request_reresolution_(nullptr) {}
+ request_reresolution_(nullptr) {
+ gpr_mu_init(&child_refs_mu_);
+}
LoadBalancingPolicy::~LoadBalancingPolicy() {
grpc_pollset_set_destroy(interested_parties_);
+ gpr_mu_destroy(&child_refs_mu_);
GRPC_COMBINER_UNREF(combiner_, "lb_policy");
}
+void LoadBalancingPolicy::FillChildRefsForChannelz(
+ ChildRefsList* child_subchannels, ChildRefsList* child_channels) {
+ mu_guard guard(&child_refs_mu_);
+ // TODO, de dup these.
+ for (size_t i = 0; i < child_subchannels_.size(); ++i) {
+ child_subchannels->push_back(child_subchannels_[i]);
+ }
+ for (size_t i = 0; i < child_channels_.size(); ++i) {
+ child_channels->push_back(child_channels_[i]);
+ }
+}
+
void LoadBalancingPolicy::TryReresolutionLocked(
grpc_core::TraceFlag* grpc_lb_trace, grpc_error* error) {
if (request_reresolution_ != nullptr) {
diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h
index dab4466b21..0c5fd2ad9c 100644
--- a/src/core/ext/filters/client_channel/lb_policy.h
+++ b/src/core/ext/filters/client_channel/lb_policy.h
@@ -21,6 +21,7 @@
#include <grpc/support/port_platform.h>
+#include "src/core/ext/filters/client_channel/client_channel_channelz.h"
#include "src/core/ext/filters/client_channel/client_channel_factory.h"
#include "src/core/ext/filters/client_channel/subchannel.h"
#include "src/core/lib/gprpp/abstract.h"
@@ -28,6 +29,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/polling_entity.h"
+#include "src/core/lib/json/json.h"
#include "src/core/lib/transport/connectivity_state.h"
extern grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount;
@@ -157,6 +159,13 @@ class LoadBalancingPolicy
request_reresolution_ = request_reresolution;
}
+ /// populates child_subchannels and child_channels with the uuids of this
+ /// LB policies referenced children. This is not invoked from the
+ /// client_channel's combiner. It has its own synchronization. This is
+ /// not abstract, since the behavior is the same for all LB policies.
+ void FillChildRefsForChannelz(ChildRefsList* child_subchannels,
+ ChildRefsList* child_channels);
+
grpc_pollset_set* interested_parties() const { return interested_parties_; }
GRPC_ABSTRACT_BASE_CLASS
@@ -171,6 +180,9 @@ class LoadBalancingPolicy
grpc_client_channel_factory* client_channel_factory() const {
return client_channel_factory_;
}
+ gpr_mu* child_refs_mu() { return &child_refs_mu_; }
+ ChildRefsList* child_subchannels() { return &child_subchannels_; }
+ ChildRefsList* child_channels() { return &child_channels_; }
/// Shuts down the policy. Any pending picks that have not been
/// handed off to a new policy via HandOffPendingPicksLocked() will be
@@ -190,6 +202,11 @@ class LoadBalancingPolicy
/// Combiner under which LB policy actions take place.
grpc_combiner* combiner_;
+ /// Lock and data used to capture snapshots of this channels child
+ /// channels and subchannels. This data is consumed by channelz.
+ gpr_mu child_refs_mu_;
+ ChildRefsList child_subchannels_;
+ ChildRefsList child_channels_;
/// Client channel factory, used to create channels and subchannels.
grpc_client_channel_factory* client_channel_factory_;
/// Owned pointer to interested parties in load balancing decisions.
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 ff2140e628..e43d1c2ab4 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
@@ -37,6 +37,15 @@ TraceFlag grpc_lb_pick_first_trace(false, "pick_first");
namespace {
+class LockGuard {
+ public:
+ LockGuard(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); }
+ ~LockGuard() { gpr_mu_unlock(mu_); }
+
+ private:
+ gpr_mu* mu_;
+};
+
//
// pick_first LB policy
//
@@ -103,10 +112,20 @@ class PickFirst : public LoadBalancingPolicy {
}
};
+ class UpdateGuard {
+ public:
+ UpdateGuard(PickFirst* pf) : pf_(pf) {}
+ ~UpdateGuard() { pf_->UpdateChildRefsLocked(); }
+
+ private:
+ PickFirst* pf_;
+ };
+
void ShutdownLocked() override;
void StartPickingLocked();
void DestroyUnselectedSubchannelsLocked();
+ void UpdateChildRefsLocked();
// All our subchannels.
OrphanablePtr<PickFirstSubchannelList> subchannel_list_;
@@ -158,6 +177,7 @@ void PickFirst::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) {
}
void PickFirst::ShutdownLocked() {
+ UpdateGuard(this);
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown");
if (grpc_lb_pick_first_trace.enabled()) {
gpr_log(GPR_INFO, "Pick First %p Shutting down", this);
@@ -280,7 +300,37 @@ void PickFirst::PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) {
}
}
+void PickFirst::UpdateChildRefsLocked() {
+ mu_guard guard(child_refs_mu());
+ // reset both lists
+ child_subchannels()->clear();
+ // this will stay empty, because pick_first channels have no children
+ // channels.
+ child_channels()->clear();
+ // populate the subchannels with boths subchannels lists, they will be
+ // deduped when the actual channelz query comes in.
+ if (subchannel_list_ != nullptr) {
+ for (size_t i = 0; i < subchannel_list_->num_subchannels(); ++i) {
+ if (subchannel_list_->subchannel(i)->subchannel() != nullptr) {
+ child_subchannels()->push_back(grpc_subchannel_get_uuid(
+ subchannel_list_->subchannel(i)->subchannel()));
+ }
+ }
+ }
+ if (latest_pending_subchannel_list_ != nullptr) {
+ for (size_t i = 0; i < latest_pending_subchannel_list_->num_subchannels();
+ ++i) {
+ if (latest_pending_subchannel_list_->subchannel(i)->subchannel() !=
+ nullptr) {
+ child_subchannels()->push_back(grpc_subchannel_get_uuid(
+ latest_pending_subchannel_list_->subchannel(i)->subchannel()));
+ }
+ }
+ }
+}
+
void PickFirst::UpdateLocked(const grpc_channel_args& args) {
+ UpdateGuard guard(this);
const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
if (arg == nullptr || arg->type != GRPC_ARG_POINTER) {
if (subchannel_list_ == nullptr) {
@@ -388,6 +438,7 @@ void PickFirst::UpdateLocked(const grpc_channel_args& args) {
void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
grpc_connectivity_state connectivity_state, grpc_error* error) {
PickFirst* p = static_cast<PickFirst*>(subchannel_list()->policy());
+ UpdateGuard guard(p);
// The notification must be for a subchannel in either the current or
// latest pending subchannel lists.
GPR_ASSERT(subchannel_list() == p->subchannel_list_.get() ||
diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc
index 8ab3fe40f5..6c4f1869ea 100644
--- a/src/core/ext/filters/client_channel/subchannel.cc
+++ b/src/core/ext/filters/client_channel/subchannel.cc
@@ -134,6 +134,11 @@ struct grpc_subchannel {
bool backoff_begun;
/** our alarm */
grpc_timer alarm;
+
+ /* the global uuid for this subchannel */
+ // TODO(ncteisen): move this into SubchannelNode while implementing
+ // GetSubchannel.
+ intptr_t subchannel_uuid;
};
struct grpc_subchannel_call {
@@ -374,9 +379,16 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
c->backoff.Init(backoff_options);
gpr_mu_init(&c->mu);
+ // This is just a placeholder for now
+ c->subchannel_uuid = 42;
+
return grpc_subchannel_index_register(key, c);
}
+intptr_t grpc_subchannel_get_uuid(grpc_subchannel* s) {
+ return s->subchannel_uuid;
+}
+
static void continue_connect_locked(grpc_subchannel* c) {
grpc_connect_in_args args;
args.interested_parties = c->pollset_set;
diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h
index e23aec12df..590e80f507 100644
--- a/src/core/ext/filters/client_channel/subchannel.h
+++ b/src/core/ext/filters/client_channel/subchannel.h
@@ -115,6 +115,8 @@ grpc_subchannel_call* grpc_subchannel_call_ref(
void grpc_subchannel_call_unref(
grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
+intptr_t grpc_subchannel_get_uuid(grpc_subchannel* subchannel);
+
/** Returns a pointer to the parent data associated with \a subchannel_call.
The data will be of the size specified in \a parent_data_size
field of the args passed to \a grpc_connected_subchannel_create_call(). */