/* * * 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 "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/transport/connectivity_state.h" /** A load balancing policy: specified by a vtable and a struct (which is expected to be extended to contain some parameters) */ typedef struct grpc_lb_policy grpc_lb_policy; typedef struct grpc_lb_policy_vtable grpc_lb_policy_vtable; typedef struct grpc_lb_policy_args grpc_lb_policy_args; extern grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount; struct grpc_lb_policy { const grpc_lb_policy_vtable* vtable; gpr_refcount refs; /* owned pointer to interested parties in load balancing decisions */ grpc_pollset_set* interested_parties; /* combiner under which lb_policy actions take place */ grpc_combiner* combiner; /* callback to force a re-resolution */ grpc_closure* request_reresolution; }; /// State used for an LB pick. typedef struct grpc_lb_policy_pick_state { /// Initial metadata associated with the picking call. grpc_metadata_batch* initial_metadata; /// Bitmask used for selective cancelling. See \a /// grpc_lb_policy_cancel_picks() and \a GRPC_INITIAL_METADATA_* in /// grpc_types.h. uint32_t initial_metadata_flags; /// Storage for LB token in \a initial_metadata, or NULL if not used. grpc_linked_mdelem lb_token_mdelem_storage; /// Closure to run when pick is complete, if not completed 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. grpc_core::RefCountedPtr 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 NULL if not needed. void** user_data; /// Next pointer. For internal use by LB policy. struct grpc_lb_policy_pick_state* next; } grpc_lb_policy_pick_state; struct grpc_lb_policy_vtable { void (*destroy)(grpc_lb_policy* policy); /// \see grpc_lb_policy_shutdown_locked(). void (*shutdown_locked)(grpc_lb_policy* policy, grpc_lb_policy* new_policy); /** \see grpc_lb_policy_pick */ int (*pick_locked)(grpc_lb_policy* policy, grpc_lb_policy_pick_state* pick); /** \see grpc_lb_policy_cancel_pick */ void (*cancel_pick_locked)(grpc_lb_policy* policy, grpc_lb_policy_pick_state* pick, grpc_error* error); /** \see grpc_lb_policy_cancel_picks */ void (*cancel_picks_locked)(grpc_lb_policy* policy, uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_eq, grpc_error* error); /** \see grpc_lb_policy_ping_one */ void (*ping_one_locked)(grpc_lb_policy* policy, grpc_closure* on_initiate, grpc_closure* on_ack); /** Try to enter a READY connectivity state */ void (*exit_idle_locked)(grpc_lb_policy* policy); /** check the current connectivity of the lb_policy */ grpc_connectivity_state (*check_connectivity_locked)( grpc_lb_policy* policy, grpc_error** connectivity_error); /** call notify when the connectivity state of a channel changes from *state. Updates *state with the new state of the policy. Calling with a NULL \a state cancels the subscription. */ void (*notify_on_state_change_locked)(grpc_lb_policy* policy, grpc_connectivity_state* state, grpc_closure* closure); void (*update_locked)(grpc_lb_policy* policy, const grpc_lb_policy_args* args); /** \see grpc_lb_policy_set_reresolve_closure */ void (*set_reresolve_closure_locked)(grpc_lb_policy* policy, grpc_closure* request_reresolution); }; #ifndef NDEBUG #define GRPC_LB_POLICY_REF(p, r) \ grpc_lb_policy_ref((p), __FILE__, __LINE__, (r)) #define GRPC_LB_POLICY_UNREF(p, r) \ grpc_lb_policy_unref((p), __FILE__, __LINE__, (r)) void grpc_lb_policy_ref(grpc_lb_policy* policy, const char* file, int line, const char* reason); void grpc_lb_policy_unref(grpc_lb_policy* policy, const char* file, int line, const char* reason); #else // !NDEBUG #define GRPC_LB_POLICY_REF(p, r) grpc_lb_policy_ref((p)) #define GRPC_LB_POLICY_UNREF(p, r) grpc_lb_policy_unref((p)) void grpc_lb_policy_ref(grpc_lb_policy* policy); void grpc_lb_policy_unref(grpc_lb_policy* policy); #endif /** called by concrete implementations to initialize the base struct */ void grpc_lb_policy_init(grpc_lb_policy* policy, const grpc_lb_policy_vtable* vtable, grpc_combiner* combiner); /// Shuts down \a policy. /// If \a new_policy is non-null, any pending picks will be restarted /// on that policy; otherwise, they will be failed. void grpc_lb_policy_shutdown_locked(grpc_lb_policy* policy, grpc_lb_policy* new_policy); /** Finds an appropriate subchannel for a call, based on data in \a pick. \a pick must remain alive until the pick is complete. If the pick succeeds and a result is known immediately, a non-zero value will be returned. Otherwise, \a pick->on_complete will be invoked once the pick is complete with its error argument set to indicate success or failure. Any IO should be done under the \a interested_parties \a grpc_pollset_set in the \a grpc_lb_policy struct. */ int grpc_lb_policy_pick_locked(grpc_lb_policy* policy, grpc_lb_policy_pick_state* pick); /** Perform a connected subchannel ping (see \a grpc_core::ConnectedSubchannel::Ping) against one of the connected subchannels managed by \a policy. */ void grpc_lb_policy_ping_one_locked(grpc_lb_policy* policy, grpc_closure* on_initiate, grpc_closure* on_ack); /** Cancel picks for \a pick. The \a on_complete callback of the pending picks will be invoked with \a *target set to NULL. */ void grpc_lb_policy_cancel_pick_locked(grpc_lb_policy* policy, grpc_lb_policy_pick_state* pick, grpc_error* error); /** Cancel all pending picks for which their \a initial_metadata_flags (as given in the call to \a grpc_lb_policy_pick) matches \a initial_metadata_flags_eq when AND'd with \a initial_metadata_flags_mask */ void grpc_lb_policy_cancel_picks_locked(grpc_lb_policy* policy, uint32_t initial_metadata_flags_mask, uint32_t initial_metadata_flags_eq, grpc_error* error); /** Try to enter a READY connectivity state */ void grpc_lb_policy_exit_idle_locked(grpc_lb_policy* policy); /* Call notify when the connectivity state of a channel changes from \a *state. * Updates \a *state with the new state of the policy */ void grpc_lb_policy_notify_on_state_change_locked( grpc_lb_policy* policy, grpc_connectivity_state* state, grpc_closure* closure); grpc_connectivity_state grpc_lb_policy_check_connectivity_locked( grpc_lb_policy* policy, grpc_error** connectivity_error); /** Update \a policy with \a lb_policy_args. */ void grpc_lb_policy_update_locked(grpc_lb_policy* policy, const grpc_lb_policy_args* lb_policy_args); /** Set the re-resolution closure to \a request_reresolution. */ void grpc_lb_policy_set_reresolve_closure_locked( grpc_lb_policy* policy, grpc_closure* request_reresolution); /** Try to request a re-resolution. It's NOT a public API; it's only for use by the LB policy implementations. */ void grpc_lb_policy_try_reresolve(grpc_lb_policy* policy, grpc_core::TraceFlag* grpc_lb_trace, grpc_error* error); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H */