aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/ext/filters/client_channel/lb_policy.h
blob: 31c08246ae46bb46df6444d2c63174064e9aa938 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*
 *
 * 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 GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H

#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"
#include "src/core/lib/gprpp/orphanable.h"
#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/transport/connectivity_state.h"

extern grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount;

namespace grpc_core {

/// Interface for load balancing policies.
///
/// Note: All methods with a "Locked" suffix must be called from the
/// combiner passed to the constructor.
///
/// Any I/O done by the LB policy should be done under the pollset_set
/// returned by \a interested_parties().
class LoadBalancingPolicy
    : public InternallyRefCountedWithTracing<LoadBalancingPolicy> {
 public:
  struct Args {
    /// The combiner under which all LB policy calls will be run.
    /// Policy does NOT take ownership of the reference to the combiner.
    // TODO(roth): Once we have a C++-like interface for combiners, this
    // API should change to take a smart pointer that does pass ownership
    // of a reference.
    grpc_combiner* combiner = nullptr;
    /// Used to create channels and subchannels.
    grpc_client_channel_factory* client_channel_factory = nullptr;
    /// Channel args from the resolver.
    /// Note that the LB policy gets the set of addresses from the
    /// GRPC_ARG_LB_ADDRESSES channel arg.
    grpc_channel_args* args = nullptr;
  };

  /// State used for an LB pick.
  struct PickState {
    /// Initial metadata associated with the picking call.
    grpc_metadata_batch* initial_metadata;
    /// Bitmask used for selective cancelling. See
    /// \a CancelMatchingPicksLocked() and \a GRPC_INITIAL_METADATA_* in
    /// grpc_types.h.
    uint32_t initial_metadata_flags;
    /// Storage for LB token in \a initial_metadata, or nullptr if not used.
    grpc_linked_mdelem lb_token_mdelem_storage;
    /// Closure to run when pick is complete, if not completed synchronously.
    /// If null, pick will fail if a result is not available synchronously.
    grpc_closure* on_complete;
    /// Will be set to the selected subchannel, or nullptr on failure or when
    /// the LB policy decides to drop the call.
    RefCountedPtr<ConnectedSubchannel> connected_subchannel;
    /// Will be populated with context to pass to the subchannel call, if
    /// needed.
    grpc_call_context_element subchannel_call_context[GRPC_CONTEXT_COUNT];
    /// Upon success, \a *user_data will be set to whatever opaque information
    /// may need to be propagated from the LB policy, or nullptr if not needed.
    // TODO(roth): As part of revamping our metadata APIs, try to find a
    // way to clean this up and C++-ify it.
    void** user_data;
    /// Next pointer.  For internal use by LB policy.
    PickState* next;
  };

  // Not copyable nor movable.
  LoadBalancingPolicy(const LoadBalancingPolicy&) = delete;
  LoadBalancingPolicy& operator=(const LoadBalancingPolicy&) = delete;

  /// Updates the policy with a new set of \a args from the resolver.
  /// Note that the LB policy gets the set of addresses from the
  /// GRPC_ARG_LB_ADDRESSES channel arg.
  virtual void UpdateLocked(const grpc_channel_args& args) GRPC_ABSTRACT;

  /// Finds an appropriate subchannel for a call, based on data in \a pick.
  /// \a pick must remain alive until the pick is complete.
  ///
  /// If a result is known immediately, returns true, setting \a *error
  /// upon failure.  Otherwise, \a pick->on_complete will be invoked once
  /// the pick is complete with its error argument set to indicate success
  /// or failure.
  ///
  /// If \a pick->on_complete is null and no result is known immediately,
  /// a synchronous failure will be returned (i.e., \a *error will be
  /// set and true will be returned).
  virtual bool PickLocked(PickState* pick, grpc_error** error) GRPC_ABSTRACT;

  /// Cancels \a pick.
  /// The \a on_complete callback of the pending pick will be invoked with
  /// \a pick->connected_subchannel set to null.
  virtual void CancelPickLocked(PickState* pick,
                                grpc_error* error) GRPC_ABSTRACT;

  /// Cancels all pending picks for which their \a initial_metadata_flags (as
  /// given in the call to \a PickLocked()) matches
  /// \a initial_metadata_flags_eq when ANDed with
  /// \a initial_metadata_flags_mask.
  virtual void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
                                         uint32_t initial_metadata_flags_eq,
                                         grpc_error* error) GRPC_ABSTRACT;

  /// Requests a notification when the connectivity state of the policy
  /// changes from \a *state.  When that happens, sets \a *state to the
  /// new state and schedules \a closure.
  virtual void NotifyOnStateChangeLocked(grpc_connectivity_state* state,
                                         grpc_closure* closure) GRPC_ABSTRACT;

  /// Returns the policy's current connectivity state.  Sets \a error to
  /// the associated error, if any.
  virtual grpc_connectivity_state CheckConnectivityLocked(
      grpc_error** connectivity_error) GRPC_ABSTRACT;

  /// Hands off pending picks to \a new_policy.
  virtual void HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy)
      GRPC_ABSTRACT;

  /// Tries to enter a READY connectivity state.
  /// TODO(roth): As part of restructuring how we handle IDLE state,
  /// consider whether this method is still needed.
  virtual void ExitIdleLocked() GRPC_ABSTRACT;

  /// populates child_subchannels and child_channels with the uuids of this
  /// LB policy's referenced children. This is not invoked from the
  /// client_channel's combiner. The implementation is responsible for
  /// providing its own synchronization.
  virtual void FillChildRefsForChannelz(ChildRefsList* child_subchannels,
                                        ChildRefsList* child_channels)
      GRPC_ABSTRACT;

  void Orphan() override {
    // Invoke ShutdownAndUnrefLocked() inside of the combiner.
    GRPC_CLOSURE_SCHED(
        GRPC_CLOSURE_CREATE(&LoadBalancingPolicy::ShutdownAndUnrefLocked, this,
                            grpc_combiner_scheduler(combiner_)),
        GRPC_ERROR_NONE);
  }

  /// Sets the re-resolution closure to \a request_reresolution.
  void SetReresolutionClosureLocked(grpc_closure* request_reresolution) {
    GPR_ASSERT(request_reresolution_ == nullptr);
    request_reresolution_ = request_reresolution;
  }

  grpc_pollset_set* interested_parties() const { return interested_parties_; }

  GRPC_ABSTRACT_BASE_CLASS

 protected:
  GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE

  explicit LoadBalancingPolicy(const Args& args);
  virtual ~LoadBalancingPolicy();

  grpc_combiner* combiner() const { return combiner_; }
  grpc_client_channel_factory* client_channel_factory() const {
    return client_channel_factory_;
  }

  /// Shuts down the policy.  Any pending picks that have not been
  /// handed off to a new policy via HandOffPendingPicksLocked() will be
  /// failed.
  virtual void ShutdownLocked() GRPC_ABSTRACT;

  /// Tries to request a re-resolution.
  void TryReresolutionLocked(grpc_core::TraceFlag* grpc_lb_trace,
                             grpc_error* error);

 private:
  static void ShutdownAndUnrefLocked(void* arg, grpc_error* ignored) {
    LoadBalancingPolicy* policy = static_cast<LoadBalancingPolicy*>(arg);
    policy->ShutdownLocked();
    policy->Unref();
  }

  /// Combiner under which LB policy actions take place.
  grpc_combiner* combiner_;
  /// 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.
  grpc_pollset_set* interested_parties_;
  /// Callback to force a re-resolution.
  grpc_closure* request_reresolution_;

  // Dummy classes needed for alignment issues.
  // See https://github.com/grpc/grpc/issues/16032 for context.
  // TODO(ncteisen): remove this as soon as the issue is resolved.
  ChildRefsList dummy_list_foo;
  ChildRefsList dummy_list_bar;
};

}  // namespace grpc_core

#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H */