Similar to :class:`.RoundRobinPolicy`, but prefers hosts in the local datacenter and only uses nodes in remote datacenters as a last resort.
| 201 | |
| 202 | |
| 203 | class DCAwareRoundRobinPolicy(LoadBalancingPolicy): |
| 204 | """ |
| 205 | Similar to :class:`.RoundRobinPolicy`, but prefers hosts |
| 206 | in the local datacenter and only uses nodes in remote |
| 207 | datacenters as a last resort. |
| 208 | """ |
| 209 | |
| 210 | local_dc = None |
| 211 | used_hosts_per_remote_dc = 0 |
| 212 | |
| 213 | def __init__(self, local_dc='', used_hosts_per_remote_dc=0): |
| 214 | """ |
| 215 | The `local_dc` parameter should be the name of the datacenter |
| 216 | (such as is reported by ``nodetool ring``) that should |
| 217 | be considered local. If not specified, the driver will choose |
| 218 | a local_dc based on the first host among :attr:`.Cluster.contact_points` |
| 219 | having a valid DC. If relying on this mechanism, all specified |
| 220 | contact points should be nodes in a single, local DC. |
| 221 | |
| 222 | `used_hosts_per_remote_dc` controls how many nodes in |
| 223 | each remote datacenter will have connections opened |
| 224 | against them. In other words, `used_hosts_per_remote_dc` hosts |
| 225 | will be considered :attr:`~.HostDistance.REMOTE` and the |
| 226 | rest will be considered :attr:`~.HostDistance.IGNORED`. |
| 227 | By default, all remote hosts are ignored. |
| 228 | """ |
| 229 | self.local_dc = local_dc |
| 230 | self.used_hosts_per_remote_dc = used_hosts_per_remote_dc |
| 231 | self._dc_live_hosts = {} |
| 232 | self._position = 0 |
| 233 | self._endpoints = [] |
| 234 | LoadBalancingPolicy.__init__(self) |
| 235 | |
| 236 | def _dc(self, host): |
| 237 | return host.datacenter or self.local_dc |
| 238 | |
| 239 | def populate(self, cluster, hosts): |
| 240 | for dc, dc_hosts in groupby(hosts, lambda h: self._dc(h)): |
| 241 | self._dc_live_hosts[dc] = tuple(set(dc_hosts)) |
| 242 | |
| 243 | if not self.local_dc: |
| 244 | self._endpoints = [ |
| 245 | endpoint |
| 246 | for endpoint in cluster.endpoints_resolved] |
| 247 | |
| 248 | self._position = randint(0, len(hosts) - 1) if hosts else 0 |
| 249 | |
| 250 | def distance(self, host): |
| 251 | dc = self._dc(host) |
| 252 | if dc == self.local_dc: |
| 253 | return HostDistance.LOCAL |
| 254 | |
| 255 | if not self.used_hosts_per_remote_dc: |
| 256 | return HostDistance.IGNORED |
| 257 | else: |
| 258 | dc_hosts = self._dc_live_hosts.get(dc) |
| 259 | if not dc_hosts: |
| 260 | return HostDistance.IGNORED |
no outgoing calls