| 118 | } |
| 119 | |
| 120 | int WeightedRandomizedLoadBalancer::SelectServer(const SelectIn& in, SelectOut* out) { |
| 121 | butil::DoublyBufferedData<Servers>::ScopedPtr s; |
| 122 | if (_db_servers.Read(&s) != 0) { |
| 123 | return ENOMEM; |
| 124 | } |
| 125 | size_t n = s->server_list.size(); |
| 126 | if (n == 0) { |
| 127 | return ENODATA; |
| 128 | } |
| 129 | |
| 130 | butil::FlatSet<SocketId> random_traversed; |
| 131 | uint64_t weight_sum = s->weight_sum; |
| 132 | for (size_t i = 0; i < n; ++i) { |
| 133 | uint64_t random_weight = butil::fast_rand_less_than(weight_sum); |
| 134 | const Server random_server(0, 0, random_weight); |
| 135 | const auto& server = |
| 136 | std::lower_bound(s->server_list.begin(), s->server_list.end(), |
| 137 | random_server, server_compare); |
| 138 | const SocketId id = server->id; |
| 139 | if (ExcludedServers::IsExcluded(in.excluded, id)) { |
| 140 | continue; |
| 141 | } |
| 142 | random_traversed.insert(id); |
| 143 | if (IsServerAvailable(id, out->ptr)) { |
| 144 | // An available server is found. |
| 145 | return 0; |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | if (random_traversed.size() < n) { |
| 150 | // Try to traverse the remaining servers to find an available server. |
| 151 | uint32_t offset = butil::fast_rand_less_than(n); |
| 152 | uint32_t stride = bthread::prime_offset(); |
| 153 | for (size_t i = 0; i < n; ++i) { |
| 154 | offset = (offset + stride) % n; |
| 155 | SocketId id = s->server_list[offset].id; |
| 156 | if (NULL != random_traversed.seek(id)) { |
| 157 | continue; |
| 158 | } |
| 159 | if (IsServerAvailable(id, out->ptr)) { |
| 160 | if (!ExcludedServers::IsExcluded(in.excluded, id)) { |
| 161 | // Prioritize servers that are not excluded. |
| 162 | return 0; |
| 163 | } |
| 164 | } |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | // Returns EHOSTDOWN, if no available server is found |
| 169 | // after traversing the whole server list. |
| 170 | // Otherwise, returns 0 with a available excluded server. |
| 171 | return NULL == out->ptr ? EHOSTDOWN : 0; |
| 172 | } |
| 173 | |
| 174 | LoadBalancer* WeightedRandomizedLoadBalancer::New( |
| 175 | const butil::StringPiece&) const { |
nothing calls this directly
no test coverage detected