Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   *      Copyright (C) 2012 DataStax Inc.
   *
   *   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.
  */
 package com.datastax.driver.core.policies;
 
 import java.util.*;
 
 
A data-center aware Round-robin load balancing policy.

This policy provides round-robin queries over the node of the local datacenter. It also includes in the query plans returned a configurable number of hosts in the remote datacenters, but those are always tried after the local nodes. In other words, this policy guarantees that no host in a remote datacenter will be queried unless no host in the local datacenter can be reached.

If used with a single datacenter, this policy is equivalent to the LoadBalancingPolicy.RoundRobin policy, but its DC awareness incurs a slight overhead so the LoadBalancingPolicy.RoundRobin policy could be prefered to this policy in that case.

 
 public class DCAwareRoundRobinPolicy implements LoadBalancingPolicy {
 
     private final AtomicInteger index = new AtomicInteger();
     private final String localDc;
     private final int usedHostsPerRemoteDc;
     private final boolean dontHopForLocalCL;

    
Creates a new datacenter aware round robin policy given the name of the local datacenter.

The name of the local datacenter provided must be the local datacenter name as known by Cassandra.

The policy created will ignore all remote hosts. In other words, this is equivalent to new DCAwareRoundRobinPolicy(localDc, 0).

Parameters:
localDc the name of the local datacenter (as known by Cassandra).
 
     public DCAwareRoundRobinPolicy(String localDc) {
         this(localDc, 0);
     }

    
Creates a new DCAwareRoundRobin policy given the name of the local datacenter and that uses the provided number of host per remote datacenter as failover for the local hosts.

The name of the local datacenter provided must be the local datacenter name as known by Cassandra.

If usedHostsPerRemoteDc > 0, then if for a query no host in the local datacenter can be reached and if the consistency level of the query is not LOCAL_ONE or LOCAL_QUORUM, then up to usedHostsPerRemoteDc host per remote data-center will be tried by the policy as a fallback. Please note that no remote host will be used for LOCAL_ONE and LOCAL_QUORUM since this would change the meaning of the consistency level (and thus somewhat break the consistency contract).

Parameters:
localDc the name of the local datacenter (as known by Cassandra).
usedHostsPerRemoteDc the number of host per remote datacenter that policies created by the returned factory should consider. Created policies distance method will return a HostDistance.REMOTE distance for only usedHostsPerRemoteDc hosts per remote datacenter. Other hosts of the remote datacenters will be ignored (and thus no connections to them will be maintained).
 
     public DCAwareRoundRobinPolicy(String localDcint usedHostsPerRemoteDc) {
        this(localDcusedHostsPerRemoteDcfalse);
    }

    
Creates a new DCAwareRoundRobin policy given the name of the local datacenter and that uses the provided number of host per remote datacenter as failover for the local hosts.

This constructor is equivalent to DCAwareRoundRobinPolicy(String, int) but allows to override the policy of never using remote data-center nodes for LOCAL_ONE and LOCAL_QUORUM queries. It is however inadvisable to do so in almost all cases, as this would potentially break consistency guarantees and if you are fine with that, it's probably better to use a weaker consitency like ONE, TWO or THREE. As such, this constructor should generally be avoided in favor of DCAwareRoundRobinPolicy(String, int). Use it only if you know and understand what you do.

Parameters:
localDc the name of the local datacenter (as known by Cassandra).
usedHostsPerRemoteDc the number of host per remote datacenter that policies created by the returned factory should consider. Created policies distance method will return a HostDistance.REMOTE distance for only usedHostsPerRemoteDc hosts per remote datacenter. Other hosts of the remote datacenters will be ignored (and thus no connections to them will be maintained).
allowRemoteDCsForLocalConsistencyLevel whether or not the policy may return remote host when building query plan for query having consitency LOCAL_ONE and LOCAL_QUORUM.
    public DCAwareRoundRobinPolicy(String localDcint usedHostsPerRemoteDcboolean allowRemoteDCsForLocalConsistencyLevel) {
        this. = localDc;
        this. = usedHostsPerRemoteDc;
        this. = !allowRemoteDCsForLocalConsistencyLevel;
    }
    @Override
    public void init(Cluster clusterCollection<Hosthosts) {
        this..set(new Random().nextInt(Math.max(hosts.size(), 1)));
        for (Host host : hosts) {
            String dc = dc(host);
            CopyOnWriteArrayList<Hostprev = .get(dc);
            if (prev == null)
                .put(dcnew CopyOnWriteArrayList<Host>(Collections.singletonList(host)));
            else
                prev.addIfAbsent(host);
        }
    }
    private String dc(Host host) {
        String dc = host.getDatacenter();
        return dc == null ?  : dc;
    }
    @SuppressWarnings("unchecked")
    private static CopyOnWriteArrayList<HostcloneList(CopyOnWriteArrayList<Hostlist) {
        return (CopyOnWriteArrayList<Host>)list.clone();
    }

    
Return the HostDistance for the provided host.

This policy consider nodes in the local datacenter as LOCAL. For each remote datacenter, it considers a configurable number of hosts as REMOTE and the rest is IGNORED.

To configure how many host in each remote datacenter is considered REMOTE, see DCAwareRoundRobinPolicy(java.lang.String,int).

Parameters:
host the host of which to return the distance of.
Returns:
the HostDistance to host.
    @Override
    public HostDistance distance(Host host) {
        String dc = dc(host);
        if (dc.equals())
            return .;
        CopyOnWriteArrayList<HostdcHosts = .get(dc);
        if (dcHosts == null ||  == 0)
            return .;
        // We need to clone, otherwise our subList call is not thread safe
        dcHosts = cloneList(dcHosts);
        return dcHosts.subList(0, Math.min(dcHosts.size(), )).contains(host)
             ? .
             : .;
    }

    
Returns the hosts to use for a new query.

The returned plan will always try each known host in the local datacenter first, and then, if none of the local host is reachable, will try up to a configurable number of other host per remote datacenter. The order of the local node in the returned query plan will follow a Round-robin algorithm.

Parameters:
query the query for which to build the plan.
Returns:
a new query plan, i.e. an iterator indicating which host to try first for querying, which one to use as failover, etc...
    @Override
    public Iterator<HostnewQueryPlan(final Query query) {
        CopyOnWriteArrayList<HostlocalLiveHosts = .get();
        final List<Hosthosts = localLiveHosts == null ? Collections.<Host>emptyList() : cloneList(localLiveHosts);
        final int startIdx = .getAndIncrement();
        return new AbstractIterator<Host>() {
            private int idx = startIdx;
            private int remainingLocal = hosts.size();
            // For remote Dcs
            private Iterator<StringremoteDcs;
            private List<HostcurrentDcHosts;
            private int currentDcRemaining;
            @Override
            protected Host computeNext() {
                if ( > 0) {
                    --;
                    int c = ++ % hosts.size();
                    if (c < 0)
                        c += hosts.size();
                    return hosts.get(c);
                }
                if ( != null &&  > 0) {
                    --;
                    int c = ++ % .size();
                    if (c < 0)
                        c += .size();
                    return .get(c);
                }
                if ( && query.getConsistencyLevel() != null && query.getConsistencyLevel().isDCLocal())
                    return endOfData();
                if ( == null) {
                    Set<Stringcopy = new HashSet<String>(.keySet());
                    copy.remove();
                     = copy.iterator();
                }
                if (!.hasNext())
                    return endOfData();
                String nextRemoteDc = .next();
                CopyOnWriteArrayList<HostnextDcHosts = .get(nextRemoteDc);
                if (nextDcHosts != null) {
                    // Clone for thread safety
                    List<HostdcHosts = cloneList(nextDcHosts);
                     = dcHosts.subList(0, Math.min(dcHosts.size(), ));
                     = .size();
                }
                return computeNext();
            }
        };
    }
    @Override
    public void onUp(Host host) {
        String dc = dc(host);
        CopyOnWriteArrayList<HostdcHosts = .get(dc);
        if (dcHosts == null) {
            CopyOnWriteArrayList<HostnewMap = new CopyOnWriteArrayList<Host>(Collections.singletonList(host));
            dcHosts = .putIfAbsent(dcnewMap);
            // If we've successfully put our new host, we're good, otherwise we've been beaten so continue
            if (dcHosts == null)
                return;
        }
        dcHosts.addIfAbsent(host);
    }
    @Override
    public void onDown(Host host) {
        CopyOnWriteArrayList<HostdcHosts = .get(dc(host));
        if (dcHosts != null)
            dcHosts.remove(host);
    }
    @Override
    public void onAdd(Host host) {
        onUp(host);
    }
    @Override
    public void onRemove(Host host) {
        onDown(host);
    }
New to GrepCode? Check out our FAQ X