pick_first.cc
Go to the documentation of this file.
1 //
2 // Copyright 2015 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
18 
19 #include <inttypes.h>
20 #include <string.h>
21 
22 #include <algorithm>
23 #include <memory>
24 #include <string>
25 #include <utility>
26 #include <vector>
27 
28 #include "absl/memory/memory.h"
29 #include "absl/status/status.h"
30 #include "absl/status/statusor.h"
31 #include "absl/strings/str_cat.h"
32 #include "absl/types/optional.h"
33 
36 #include <grpc/support/log.h>
37 
49 #include "src/core/lib/json/json.h"
52 
53 namespace grpc_core {
54 
55 TraceFlag grpc_lb_pick_first_trace(false, "pick_first");
56 
57 namespace {
58 
59 //
60 // pick_first LB policy
61 //
62 
63 constexpr char kPickFirst[] = "pick_first";
64 
65 class PickFirst : public LoadBalancingPolicy {
66  public:
67  explicit PickFirst(Args args);
68 
69  const char* name() const override { return kPickFirst; }
70 
71  void UpdateLocked(UpdateArgs args) override;
72  void ExitIdleLocked() override;
73  void ResetBackoffLocked() override;
74 
75  private:
76  ~PickFirst() override;
77 
78  class PickFirstSubchannelList;
79 
80  class PickFirstSubchannelData
81  : public SubchannelData<PickFirstSubchannelList,
82  PickFirstSubchannelData> {
83  public:
84  PickFirstSubchannelData(
85  SubchannelList<PickFirstSubchannelList, PickFirstSubchannelData>*
86  subchannel_list,
87  const ServerAddress& address,
88  RefCountedPtr<SubchannelInterface> subchannel)
89  : SubchannelData(subchannel_list, address, std::move(subchannel)) {}
90 
91  void ProcessConnectivityChangeLocked(
93  grpc_connectivity_state new_state) override;
94 
95  // Processes the connectivity change to READY for an unselected subchannel.
96  void ProcessUnselectedReadyLocked();
97  };
98 
99  class PickFirstSubchannelList
100  : public SubchannelList<PickFirstSubchannelList,
101  PickFirstSubchannelData> {
102  public:
103  PickFirstSubchannelList(PickFirst* policy, ServerAddressList addresses,
104  const grpc_channel_args& args)
105  : SubchannelList(policy,
107  ? "PickFirstSubchannelList"
108  : nullptr),
109  std::move(addresses), policy->channel_control_helper(),
110  args) {
111  // Need to maintain a ref to the LB policy as long as we maintain
112  // any references to subchannels, since the subchannels'
113  // pollset_sets will include the LB policy's pollset_set.
114  policy->Ref(DEBUG_LOCATION, "subchannel_list").release();
115  // Note that we do not start trying to connect to any subchannel here,
116  // since we will wait until we see the initial connectivity state for all
117  // subchannels before doing that.
118  }
119 
120  ~PickFirstSubchannelList() override {
121  PickFirst* p = static_cast<PickFirst*>(policy());
122  p->Unref(DEBUG_LOCATION, "subchannel_list");
123  }
124 
125  bool in_transient_failure() const { return in_transient_failure_; }
126  void set_in_transient_failure(bool in_transient_failure) {
127  in_transient_failure_ = in_transient_failure;
128  }
129 
130  size_t attempting_index() const { return attempting_index_; }
131  void set_attempting_index(size_t index) { attempting_index_ = index; }
132 
133  bool AllSubchannelsSeenInitialState() {
134  for (size_t i = 0; i < num_subchannels(); ++i) {
135  if (!subchannel(i)->connectivity_state().has_value()) return false;
136  }
137  return true;
138  }
139 
140  private:
141  bool in_transient_failure_ = false;
142  size_t attempting_index_ = 0;
143  };
144 
145  class Picker : public SubchannelPicker {
146  public:
147  explicit Picker(RefCountedPtr<SubchannelInterface> subchannel)
149 
150  PickResult Pick(PickArgs /*args*/) override {
151  return PickResult::Complete(subchannel_);
152  }
153 
154  private:
155  RefCountedPtr<SubchannelInterface> subchannel_;
156  };
157 
158  void ShutdownLocked() override;
159 
160  void AttemptToConnectUsingLatestUpdateArgsLocked();
161 
162  // Lateset update args.
164  // All our subchannels.
165  OrphanablePtr<PickFirstSubchannelList> subchannel_list_;
166  // Latest pending subchannel list.
167  OrphanablePtr<PickFirstSubchannelList> latest_pending_subchannel_list_;
168  // Selected subchannel in \a subchannel_list_.
169  PickFirstSubchannelData* selected_ = nullptr;
170  // Are we in IDLE state?
171  bool idle_ = false;
172  // Are we shut down?
173  bool shutdown_ = false;
174 };
175 
176 PickFirst::PickFirst(Args args) : LoadBalancingPolicy(std::move(args)) {
178  gpr_log(GPR_INFO, "Pick First %p created.", this);
179  }
180 }
181 
182 PickFirst::~PickFirst() {
184  gpr_log(GPR_INFO, "Destroying Pick First %p", this);
185  }
186  GPR_ASSERT(subchannel_list_ == nullptr);
188 }
189 
190 void PickFirst::ShutdownLocked() {
192  gpr_log(GPR_INFO, "Pick First %p Shutting down", this);
193  }
194  shutdown_ = true;
195  subchannel_list_.reset();
197 }
198 
200  if (shutdown_) return;
201  if (idle_) {
203  gpr_log(GPR_INFO, "Pick First %p exiting idle", this);
204  }
205  idle_ = false;
206  AttemptToConnectUsingLatestUpdateArgsLocked();
207  }
208 }
209 
210 void PickFirst::ResetBackoffLocked() {
211  if (subchannel_list_ != nullptr) subchannel_list_->ResetBackoffLocked();
212  if (latest_pending_subchannel_list_ != nullptr) {
213  latest_pending_subchannel_list_->ResetBackoffLocked();
214  }
215 }
216 
217 void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() {
218  // Create a subchannel list from latest_update_args_.
219  ServerAddressList addresses;
220  if (latest_update_args_.addresses.ok()) {
221  addresses = *latest_update_args_.addresses;
222  }
223  // Replace latest_pending_subchannel_list_.
225  latest_pending_subchannel_list_ != nullptr) {
227  "[PF %p] Shutting down previous pending subchannel list %p", this,
229  }
230  latest_pending_subchannel_list_ = MakeOrphanable<PickFirstSubchannelList>(
231  this, std::move(addresses), *latest_update_args_.args);
232  latest_pending_subchannel_list_->StartWatchingLocked();
233  // Empty update or no valid subchannels. Put the channel in
234  // TRANSIENT_FAILURE.
235  if (latest_pending_subchannel_list_->num_subchannels() == 0) {
237  latest_update_args_.addresses.ok()
239  "empty address list: ", latest_update_args_.resolution_note))
240  : latest_update_args_.addresses.status();
241  channel_control_helper()->UpdateState(
243  absl::make_unique<TransientFailurePicker>(status));
244  }
245  // Otherwise, if this is the initial update, report CONNECTING.
246  else if (subchannel_list_.get() == nullptr) {
247  channel_control_helper()->UpdateState(
249  absl::make_unique<QueuePicker>(Ref(DEBUG_LOCATION, "QueuePicker")));
250  }
251  // If the new update is empty or we don't yet have a selected subchannel in
252  // the current list, replace the current subchannel list immediately.
253  if (latest_pending_subchannel_list_->num_subchannels() == 0 ||
254  selected_ == nullptr) {
255  selected_ = nullptr;
257  subchannel_list_ != nullptr) {
258  gpr_log(GPR_INFO, "[PF %p] Shutting down previous subchannel list %p",
259  this, subchannel_list_.get());
260  }
262  }
263 }
264 
265 void PickFirst::UpdateLocked(UpdateArgs args) {
267  if (args.addresses.ok()) {
269  "Pick First %p received update with %" PRIuPTR " addresses", this,
270  args.addresses->size());
271  } else {
272  gpr_log(GPR_INFO, "Pick First %p received update with address error: %s",
273  this, args.addresses.status().ToString().c_str());
274  }
275  }
276  // Add GRPC_ARG_INHIBIT_HEALTH_CHECKING channel arg.
278  const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1);
279  const grpc_channel_args* new_args =
280  grpc_channel_args_copy_and_add(args.args, &new_arg, 1);
281  std::swap(new_args, args.args);
282  grpc_channel_args_destroy(new_args);
283  // If the update contains a resolver error and we have a previous update
284  // that was not a resolver error, keep using the previous addresses.
285  if (!args.addresses.ok() && latest_update_args_.config != nullptr) {
286  args.addresses = std::move(latest_update_args_.addresses);
287  }
288  // Update latest_update_args_.
290  // If we are not in idle, start connection attempt immediately.
291  // Otherwise, we defer the attempt into ExitIdleLocked().
292  if (!idle_) {
293  AttemptToConnectUsingLatestUpdateArgsLocked();
294  }
295 }
296 
297 void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
299  grpc_connectivity_state new_state) {
300  PickFirst* p = static_cast<PickFirst*>(subchannel_list()->policy());
301  // The notification must be for a subchannel in either the current or
302  // latest pending subchannel lists.
303  GPR_ASSERT(subchannel_list() == p->subchannel_list_.get() ||
304  subchannel_list() == p->latest_pending_subchannel_list_.get());
305  GPR_ASSERT(new_state != GRPC_CHANNEL_SHUTDOWN);
306  // Handle updates for the currently selected subchannel.
307  if (p->selected_ == this) {
308  GPR_ASSERT(subchannel_list() == p->subchannel_list_.get());
311  "Pick First %p selected subchannel connectivity changed to %s", p,
312  ConnectivityStateName(new_state));
313  }
314  // Any state change is considered to be a failure of the existing
315  // connection.
316  // If there is a pending update, switch to the pending update.
317  if (p->latest_pending_subchannel_list_ != nullptr) {
320  "Pick First %p promoting pending subchannel list %p to "
321  "replace %p",
322  p, p->latest_pending_subchannel_list_.get(),
323  p->subchannel_list_.get());
324  }
325  p->selected_ = nullptr;
326  p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
327  // Set our state to that of the pending subchannel list.
328  if (p->subchannel_list_->in_transient_failure()) {
330  "selected subchannel failed; switching to pending update; "
331  "last failure: ",
332  p->subchannel_list_
333  ->subchannel(p->subchannel_list_->num_subchannels())
334  ->connectivity_status()
335  .ToString()));
336  p->channel_control_helper()->UpdateState(
338  absl::make_unique<TransientFailurePicker>(status));
339  } else {
340  p->channel_control_helper()->UpdateState(
342  absl::make_unique<QueuePicker>(
343  p->Ref(DEBUG_LOCATION, "QueuePicker")));
344  }
345  return;
346  }
347  // If the selected subchannel goes bad, request a re-resolution.
348  // TODO(qianchengz): We may want to request re-resolution in
349  // ExitIdleLocked().
350  p->channel_control_helper()->RequestReresolution();
351  // TODO(roth): We chould check the connectivity states of all the
352  // subchannels here, just in case one of them happens to be READY,
353  // and we could switch to that rather than going IDLE.
354  // Enter idle.
355  p->idle_ = true;
356  p->selected_ = nullptr;
357  p->subchannel_list_.reset();
358  p->channel_control_helper()->UpdateState(
360  absl::make_unique<QueuePicker>(p->Ref(DEBUG_LOCATION, "QueuePicker")));
361  return;
362  }
363  // If we get here, there are two possible cases:
364  // 1. We do not currently have a selected subchannel, and the update is
365  // for a subchannel in p->subchannel_list_ that we're trying to
366  // connect to. The goal here is to find a subchannel that we can
367  // select.
368  // 2. We do currently have a selected subchannel, and the update is
369  // for a subchannel in p->latest_pending_subchannel_list_. The
370  // goal here is to find a subchannel from the update that we can
371  // select in place of the current one.
372  // If the subchannel is READY, use it.
373  if (new_state == GRPC_CHANNEL_READY) {
374  subchannel_list()->set_in_transient_failure(false);
375  ProcessUnselectedReadyLocked();
376  return;
377  }
378  // If this is the initial connectivity state notification for this
379  // subchannel, check to see if it's the last one we were waiting for,
380  // in which case we start trying to connect to the first subchannel.
381  // Otherwise, do nothing, since we'll continue to wait until all of
382  // the subchannels report their state.
383  if (!old_state.has_value()) {
384  if (subchannel_list()->AllSubchannelsSeenInitialState()) {
385  subchannel_list()->subchannel(0)->subchannel()->RequestConnection();
386  }
387  return;
388  }
389  // Ignore any other updates for subchannels we're not currently trying to
390  // connect to.
391  if (Index() != subchannel_list()->attempting_index()) return;
392  // Otherwise, process connectivity state.
393  switch (new_state) {
394  case GRPC_CHANNEL_READY:
395  // Already handled this case above, so this should not happen.
396  GPR_UNREACHABLE_CODE(break);
398  size_t next_index = (Index() + 1) % subchannel_list()->num_subchannels();
399  subchannel_list()->set_attempting_index(next_index);
400  PickFirstSubchannelData* sd = subchannel_list()->subchannel(next_index);
401  // If we're tried all subchannels, set state to TRANSIENT_FAILURE.
402  if (sd->Index() == 0) {
405  "Pick First %p subchannel list %p failed to connect to "
406  "all subchannels",
407  p, subchannel_list());
408  }
409  subchannel_list()->set_in_transient_failure(true);
410  // In case 2, swap to the new subchannel list. This means reporting
411  // TRANSIENT_FAILURE and dropping the existing (working) connection,
412  // but we can't ignore what the control plane has told us.
413  if (subchannel_list() == p->latest_pending_subchannel_list_.get()) {
416  "Pick First %p promoting pending subchannel list %p to "
417  "replace %p",
418  p, p->latest_pending_subchannel_list_.get(),
419  p->subchannel_list_.get());
420  }
421  p->selected_ = nullptr; // owned by p->subchannel_list_
422  p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
423  }
424  // If this is the current subchannel list (either because we were
425  // in case 1 or because we were in case 2 and just promoted it to
426  // be the current list), re-resolve and report new state.
427  if (subchannel_list() == p->subchannel_list_.get()) {
428  p->channel_control_helper()->RequestReresolution();
430  absl::StrCat("failed to connect to all addresses; last error: ",
431  connectivity_status().ToString()));
432  p->channel_control_helper()->UpdateState(
434  absl::make_unique<TransientFailurePicker>(status));
435  }
436  }
437  // If the next subchannel is in IDLE, trigger a connection attempt.
438  // If it's in READY, we can't get here, because we would already
439  // have selected the subchannel above.
440  // If it's already in CONNECTING, we don't need to do this.
441  // If it's in TRANSIENT_FAILURE, then we will trigger the
442  // connection attempt later when it reports IDLE.
443  auto sd_state = sd->connectivity_state();
444  if (sd_state.has_value() && *sd_state == GRPC_CHANNEL_IDLE) {
445  sd->subchannel()->RequestConnection();
446  }
447  break;
448  }
449  case GRPC_CHANNEL_IDLE: {
450  subchannel()->RequestConnection();
451  break;
452  }
454  // Only update connectivity state in case 1, and only if we're not
455  // already in TRANSIENT_FAILURE.
456  if (subchannel_list() == p->subchannel_list_.get() &&
457  !subchannel_list()->in_transient_failure()) {
458  p->channel_control_helper()->UpdateState(
460  absl::make_unique<QueuePicker>(
461  p->Ref(DEBUG_LOCATION, "QueuePicker")));
462  }
463  break;
464  }
466  GPR_UNREACHABLE_CODE(break);
467  }
468 }
469 
470 void PickFirst::PickFirstSubchannelData::ProcessUnselectedReadyLocked() {
471  PickFirst* p = static_cast<PickFirst*>(subchannel_list()->policy());
472  // If we get here, there are two possible cases:
473  // 1. We do not currently have a selected subchannel, and the update is
474  // for a subchannel in p->subchannel_list_ that we're trying to
475  // connect to. The goal here is to find a subchannel that we can
476  // select.
477  // 2. We do currently have a selected subchannel, and the update is
478  // for a subchannel in p->latest_pending_subchannel_list_. The
479  // goal here is to find a subchannel from the update that we can
480  // select in place of the current one.
481  GPR_ASSERT(subchannel_list() == p->subchannel_list_.get() ||
482  subchannel_list() == p->latest_pending_subchannel_list_.get());
483  // Case 2. Promote p->latest_pending_subchannel_list_ to p->subchannel_list_.
484  if (subchannel_list() == p->latest_pending_subchannel_list_.get()) {
487  "Pick First %p promoting pending subchannel list %p to "
488  "replace %p",
489  p, p->latest_pending_subchannel_list_.get(),
490  p->subchannel_list_.get());
491  }
492  p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
493  }
494  // Cases 1 and 2.
496  gpr_log(GPR_INFO, "Pick First %p selected subchannel %p", p, subchannel());
497  }
498  p->selected_ = this;
499  p->channel_control_helper()->UpdateState(
501  absl::make_unique<Picker>(subchannel()->Ref()));
502  for (size_t i = 0; i < subchannel_list()->num_subchannels(); ++i) {
503  if (i != Index()) {
504  subchannel_list()->subchannel(i)->ShutdownLocked();
505  }
506  }
507 }
508 
509 class PickFirstConfig : public LoadBalancingPolicy::Config {
510  public:
511  const char* name() const override { return kPickFirst; }
512 };
513 
514 //
515 // factory
516 //
517 
518 class PickFirstFactory : public LoadBalancingPolicyFactory {
519  public:
520  OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
521  LoadBalancingPolicy::Args args) const override {
522  return MakeOrphanable<PickFirst>(std::move(args));
523  }
524 
525  const char* name() const override { return kPickFirst; }
526 
527  RefCountedPtr<LoadBalancingPolicy::Config> ParseLoadBalancingConfig(
528  const Json& /*json*/, grpc_error_handle* /*error*/) const override {
529  return MakeRefCounted<PickFirstConfig>();
530  }
531 };
532 
533 } // namespace
534 
535 } // namespace grpc_core
536 
540  absl::make_unique<grpc_core::PickFirstFactory>());
541 }
542 
grpc_arg
Definition: grpc_types.h:103
trace.h
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
GRPC_CHANNEL_READY
@ GRPC_CHANNEL_READY
Definition: include/grpc/impl/codegen/connectivity_state.h:36
grpc_core::LoadBalancingPolicyRegistry::Builder::RegisterLoadBalancingPolicyFactory
static void RegisterLoadBalancingPolicyFactory(std::unique_ptr< LoadBalancingPolicyFactory > factory)
Definition: lb_policy_registry.cc:87
orphanable.h
log.h
subchannel_list_
OrphanablePtr< PickFirstSubchannelList > subchannel_list_
Definition: pick_first.cc:165
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
connectivity_state.h
grpc_core
Definition: call_metric_recorder.h:31
string.h
ExitIdleLocked
void StartUpdate() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb void MaybeFinishUpdate() ABSL_LOCKS_EXCLUDED(&RlsLb void ExitIdleLocked()
Definition: rls.cc:299
subchannel
RingHashSubchannelData * subchannel
Definition: ring_hash.cc:285
lb_policy.h
lb_policy_factory.h
GRPC_CHANNEL_TRANSIENT_FAILURE
@ GRPC_CHANNEL_TRANSIENT_FAILURE
Definition: include/grpc/impl/codegen/connectivity_state.h:38
status
absl::Status status
Definition: rls.cc:251
setup.name
name
Definition: setup.py:542
xds_manager.p
p
Definition: xds_manager.py:60
grpc_channel_args
Definition: grpc_types.h:132
GRPC_TRACE_FLAG_ENABLED
#define GRPC_TRACE_FLAG_ENABLED(f)
Definition: debug/trace.h:114
subchannel_interface.h
grpc_connectivity_state
grpc_connectivity_state
Definition: include/grpc/impl/codegen/connectivity_state.h:30
latest_update_args_
UpdateArgs latest_update_args_
Definition: pick_first.cc:163
grpc_types.h
DEBUG_LOCATION
#define DEBUG_LOCATION
Definition: debug_location.h:41
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
hpack_encoder_fixtures::Args
Args({0, 16384})
ToString
std::string ToString(const grpc::string_ref &r)
Definition: string_ref_helper.cc:24
absl::optional::has_value
constexpr bool has_value() const noexcept
Definition: abseil-cpp/absl/types/optional.h:461
latest_pending_subchannel_list_
OrphanablePtr< PickFirstSubchannelList > latest_pending_subchannel_list_
Definition: pick_first.cc:167
Json
JSON (JavaScript Object Notation).
Definition: third_party/bloaty/third_party/protobuf/conformance/third_party/jsoncpp/json.h:227
in_transient_failure_
bool in_transient_failure_
Definition: pick_first.cc:141
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
connectivity_state.h
absl::optional< grpc_connectivity_state >
GRPC_CHANNEL_IDLE
@ GRPC_CHANNEL_IDLE
Definition: include/grpc/impl/codegen/connectivity_state.h:32
grpc_channel_args_destroy
void grpc_channel_args_destroy(grpc_channel_args *a)
Definition: channel_args.cc:360
server_address.h
std::swap
void swap(Json::Value &a, Json::Value &b)
Specialize std::swap() for Json::Value.
Definition: third_party/bloaty/third_party/protobuf/conformance/third_party/jsoncpp/json.h:1226
attempting_index_
size_t attempting_index_
Definition: pick_first.cc:142
grpc_lb_policy_pick_first_shutdown
void grpc_lb_policy_pick_first_shutdown()
Definition: pick_first.cc:543
error.h
json.h
GPR_UNREACHABLE_CODE
#define GPR_UNREACHABLE_CODE(STATEMENT)
Definition: impl/codegen/port_platform.h:652
selected_
PickFirstSubchannelData * selected_
Definition: pick_first.cc:169
grpc_core::ServerAddressList
std::vector< ServerAddress > ServerAddressList
Definition: server_address.h:120
GRPC_CHANNEL_CONNECTING
@ GRPC_CHANNEL_CONNECTING
Definition: include/grpc/impl/codegen/connectivity_state.h:34
grpc_lb_policy_pick_first_init
void grpc_lb_policy_pick_first_init()
Definition: pick_first.cc:537
subchannel_
RefCountedPtr< SubchannelInterface > subchannel_
Definition: pick_first.cc:155
GRPC_ARG_INHIBIT_HEALTH_CHECKING
#define GRPC_ARG_INHIBIT_HEALTH_CHECKING
Definition: grpc_types.h:424
shutdown_
bool shutdown_
Definition: pick_first.cc:173
grpc_core::ConnectivityStateName
const char * ConnectivityStateName(grpc_connectivity_state state)
Definition: connectivity_state.cc:38
debug_location.h
grpc_channel_arg_integer_create
grpc_arg grpc_channel_arg_integer_create(char *name, int value)
Definition: channel_args.cc:484
lb_policy_registry.h
absl::Status
Definition: third_party/abseil-cpp/absl/status/status.h:424
index
int index
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1184
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
subchannel_list.h
grpc_core::grpc_lb_pick_first_trace
TraceFlag grpc_lb_pick_first_trace(false, "pick_first")
absl::UnavailableError
Status UnavailableError(absl::string_view message)
Definition: third_party/abseil-cpp/absl/status/status.cc:375
ref_counted_ptr.h
channel_args.h
check_redundant_namespace_qualifiers.Config
Config
Definition: check_redundant_namespace_qualifiers.py:142
GRPC_CHANNEL_SHUTDOWN
@ GRPC_CHANNEL_SHUTDOWN
Definition: include/grpc/impl/codegen/connectivity_state.h:40
google::protobuf::python::descriptor::Index
static PyObject * Index(PyContainer *self, PyObject *item)
Definition: bloaty/third_party/protobuf/python/google/protobuf/pyext/descriptor_containers.cc:672
grpc_error
Definition: error_internal.h:42
testing::Ref
internal::RefMatcher< T & > Ref(T &x)
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:8628
idle_
bool idle_
Definition: pick_first.cc:171
grpc_channel_args_copy_and_add
grpc_channel_args * grpc_channel_args_copy_and_add(const grpc_channel_args *src, const grpc_arg *to_add, size_t num_to_add)
Definition: channel_args.cc:224
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
port_platform.h


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:43