| 94 | } |
| 95 | |
| 96 | int RoundRobinLoadBalancer::SelectServer(const SelectIn& in, SelectOut* out) { |
| 97 | butil::DoublyBufferedData<Servers, TLS>::ScopedPtr s; |
| 98 | if (_db_servers.Read(&s) != 0) { |
| 99 | return ENOMEM; |
| 100 | } |
| 101 | const size_t n = s->server_list.size(); |
| 102 | if (n == 0) { |
| 103 | return ENODATA; |
| 104 | } |
| 105 | if (_cluster_recover_policy && _cluster_recover_policy->StopRecoverIfNecessary()) { |
| 106 | if (_cluster_recover_policy->DoReject(s->server_list)) { |
| 107 | return EREJECT; |
| 108 | } |
| 109 | } |
| 110 | TLS tls = s.tls(); |
| 111 | if (tls.stride == 0) { |
| 112 | tls.stride = bthread::prime_offset(); |
| 113 | // use random at first time, for the case of |
| 114 | // use rr lb every time in new thread |
| 115 | tls.offset = butil::fast_rand_less_than(n); |
| 116 | } |
| 117 | |
| 118 | for (size_t i = 0; i < n; ++i) { |
| 119 | tls.offset = (tls.offset + tls.stride) % n; |
| 120 | const SocketId id = s->server_list[tls.offset].id; |
| 121 | if (((i + 1) == n // always take last chance |
| 122 | || !ExcludedServers::IsExcluded(in.excluded, id)) |
| 123 | && IsServerAvailable(id, out->ptr)) { |
| 124 | s.tls() = tls; |
| 125 | return 0; |
| 126 | } |
| 127 | } |
| 128 | if (_cluster_recover_policy) { |
| 129 | _cluster_recover_policy->StartRecover(); |
| 130 | } |
| 131 | s.tls() = tls; |
| 132 | return EHOSTDOWN; |
| 133 | } |
| 134 | |
| 135 | RoundRobinLoadBalancer* RoundRobinLoadBalancer::New( |
| 136 | const butil::StringPiece& params) const { |
nothing calls this directly
no test coverage detected