Mark D. Roth | 5e9848e | 2017-10-06 13:59:32 -0700 | [diff] [blame] | 1 | /* |
| 2 | * |
| 3 | * Copyright 2015 gRPC authors. |
| 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | * |
| 17 | */ |
| 18 | |
| 19 | #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_SUBCHANNEL_LIST_H |
| 20 | #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_SUBCHANNEL_LIST_H |
| 21 | |
| 22 | #include "src/core/ext/filters/client_channel/lb_policy_registry.h" |
| 23 | #include "src/core/ext/filters/client_channel/subchannel.h" |
| 24 | #include "src/core/lib/transport/connectivity_state.h" |
| 25 | |
| 26 | // TODO(roth): This code is intended to be shared between pick_first and |
| 27 | // round_robin. However, the interface needs more work to provide clean |
| 28 | // encapsulation. For example, the structs here have some fields that are |
| 29 | // only used in one of the two (e.g., the state counters in |
| 30 | // grpc_lb_subchannel_list and the prev_connectivity_state field in |
| 31 | // grpc_lb_subchannel_data are only used in round_robin, and the |
| 32 | // checking_subchannel field in grpc_lb_subchannel_list is only used by |
| 33 | // pick_first). Also, there is probably some code duplication between the |
| 34 | // connectivity state notification callback code in both pick_first and |
| 35 | // round_robin that could be refactored and moved here. In a future PR, |
| 36 | // need to clean this up. |
| 37 | |
| 38 | #ifdef __cplusplus |
| 39 | extern "C" { |
| 40 | #endif |
| 41 | |
| 42 | typedef struct grpc_lb_subchannel_list grpc_lb_subchannel_list; |
| 43 | |
| 44 | typedef struct { |
| 45 | /** backpointer to owning subchannel list */ |
| 46 | grpc_lb_subchannel_list *subchannel_list; |
| 47 | /** subchannel itself */ |
| 48 | grpc_subchannel *subchannel; |
| 49 | grpc_connected_subchannel *connected_subchannel; |
| 50 | /** Is a connectivity notification pending? */ |
| 51 | bool connectivity_notification_pending; |
| 52 | /** notification that connectivity has changed on subchannel */ |
| 53 | grpc_closure connectivity_changed_closure; |
| 54 | /** previous and current connectivity states. Updated by \a |
| 55 | * \a connectivity_changed_closure based on |
| 56 | * \a pending_connectivity_state_unsafe. */ |
| 57 | grpc_connectivity_state prev_connectivity_state; |
| 58 | grpc_connectivity_state curr_connectivity_state; |
| 59 | /** connectivity state to be updated by |
| 60 | * grpc_subchannel_notify_on_state_change(), not guarded by |
| 61 | * the combiner. To be copied to \a curr_connectivity_state by |
| 62 | * \a connectivity_changed_closure. */ |
| 63 | grpc_connectivity_state pending_connectivity_state_unsafe; |
| 64 | /** the subchannel's target user data */ |
| 65 | void *user_data; |
| 66 | /** vtable to operate over \a user_data */ |
| 67 | const grpc_lb_user_data_vtable *user_data_vtable; |
| 68 | } grpc_lb_subchannel_data; |
| 69 | |
| 70 | // Unrefs the subchannel contained in sd. |
Mark D. Roth | 62ca6ce | 2017-10-10 10:01:51 -0700 | [diff] [blame] | 71 | void grpc_lb_subchannel_data_unref_subchannel(grpc_exec_ctx *exec_ctx, |
| 72 | grpc_lb_subchannel_data *sd, |
| 73 | const char *reason); |
Mark D. Roth | 5e9848e | 2017-10-06 13:59:32 -0700 | [diff] [blame] | 74 | |
| 75 | // Starts watching the connectivity state of the subchannel. |
| 76 | // The connectivity_changed_cb callback must invoke either |
| 77 | // grpc_lb_subchannel_data_stop_connectivity_watch() or again call |
| 78 | // grpc_lb_subchannel_data_start_connectivity_watch(). |
| 79 | void grpc_lb_subchannel_data_start_connectivity_watch( |
| 80 | grpc_exec_ctx *exec_ctx, grpc_lb_subchannel_data *sd); |
| 81 | |
| 82 | // Stops watching the connectivity state of the subchannel. |
| 83 | void grpc_lb_subchannel_data_stop_connectivity_watch( |
| 84 | grpc_exec_ctx *exec_ctx, grpc_lb_subchannel_data *sd); |
| 85 | |
| 86 | struct grpc_lb_subchannel_list { |
| 87 | /** backpointer to owning policy */ |
| 88 | grpc_lb_policy *policy; |
| 89 | |
| 90 | /** all our subchannels */ |
| 91 | size_t num_subchannels; |
| 92 | grpc_lb_subchannel_data *subchannels; |
| 93 | |
| 94 | /** Index into subchannels of the one we're currently checking. |
| 95 | * Used when connecting to subchannels serially instead of in parallel. */ |
| 96 | // TODO(roth): When we have time, we can probably make this go away |
| 97 | // and the index dynamically by subtracting |
| 98 | // subchannel_list->subchannels from the subchannel_data pointer. |
| 99 | size_t checking_subchannel; |
| 100 | |
| 101 | /** how many subchannels are in state READY */ |
| 102 | size_t num_ready; |
| 103 | /** how many subchannels are in state TRANSIENT_FAILURE */ |
| 104 | size_t num_transient_failures; |
| 105 | /** how many subchannels are in state SHUTDOWN */ |
| 106 | size_t num_shutdown; |
| 107 | /** how many subchannels are in state IDLE */ |
| 108 | size_t num_idle; |
| 109 | |
| 110 | /** There will be one ref for each entry in subchannels for which there is a |
| 111 | * pending connectivity state watcher callback. */ |
| 112 | gpr_refcount refcount; |
| 113 | |
| 114 | /** Is this list shutting down? This may be true due to the shutdown of the |
| 115 | * policy itself or because a newer update has arrived while this one hadn't |
| 116 | * finished processing. */ |
| 117 | bool shutting_down; |
| 118 | }; |
| 119 | |
| 120 | grpc_lb_subchannel_list *grpc_lb_subchannel_list_create( |
| 121 | grpc_exec_ctx *exec_ctx, grpc_lb_policy *p, |
| 122 | const grpc_lb_addresses *addresses, const grpc_lb_policy_args *args, |
| 123 | grpc_iomgr_cb_func connectivity_changed_cb); |
| 124 | |
| 125 | void grpc_lb_subchannel_list_ref(grpc_lb_subchannel_list *subchannel_list, |
| 126 | const char *reason); |
| 127 | |
| 128 | void grpc_lb_subchannel_list_unref(grpc_exec_ctx *exec_ctx, |
| 129 | grpc_lb_subchannel_list *subchannel_list, |
| 130 | const char *reason); |
| 131 | |
| 132 | // Takes and releases refs needed for a connectivity notification. |
| 133 | // This includes a ref to subchannel_list and a weak ref to the LB policy. |
| 134 | void grpc_lb_subchannel_list_ref_for_connectivity_watch( |
| 135 | grpc_lb_subchannel_list *subchannel_list, const char *reason); |
| 136 | void grpc_lb_subchannel_list_unref_for_connectivity_watch( |
| 137 | grpc_exec_ctx *exec_ctx, grpc_lb_subchannel_list *subchannel_list, |
| 138 | const char *reason); |
| 139 | |
| 140 | // Mark subchannel_list as discarded. Unsubscribes all its subchannels. The |
| 141 | // connectivity state notification callback will ultimately unref it. |
| 142 | void grpc_lb_subchannel_list_shutdown_and_unref( |
| 143 | grpc_exec_ctx *exec_ctx, grpc_lb_subchannel_list *subchannel_list, |
| 144 | const char *reason); |
| 145 | |
| 146 | #ifdef __cplusplus |
| 147 | } |
| 148 | #endif |
| 149 | |
| 150 | #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_SUBCHANNEL_LIST_H */ |