Search in sources :

Example 1 with Topology

use of org.apache.cassandra.locator.TokenMetadata.Topology in project cassandra by apache.

the class TokenAllocation method getStrategy.

static StrategyAdapter getStrategy(final TokenMetadata tokenMetadata, final NetworkTopologyStrategy rs, final IEndpointSnitch snitch, final InetAddress endpoint) {
    final String dc = snitch.getDatacenter(endpoint);
    final int replicas = rs.getReplicationFactor(dc);
    if (replicas == 0 || replicas == 1) {
        // No replication, each node is treated as separate.
        return new StrategyAdapter() {

            @Override
            public int replicas() {
                return 1;
            }

            @Override
            public Object getGroup(InetAddress unit) {
                return unit;
            }

            @Override
            public boolean inAllocationRing(InetAddress other) {
                return dc.equals(snitch.getDatacenter(other));
            }
        };
    }
    Topology topology = tokenMetadata.getTopology();
    int racks = topology.getDatacenterRacks().get(dc).asMap().size();
    if (racks >= replicas) {
        return new StrategyAdapter() {

            @Override
            public int replicas() {
                return replicas;
            }

            @Override
            public Object getGroup(InetAddress unit) {
                return snitch.getRack(unit);
            }

            @Override
            public boolean inAllocationRing(InetAddress other) {
                return dc.equals(snitch.getDatacenter(other));
            }
        };
    } else if (racks == 1) {
        // One rack, each node treated as separate.
        return new StrategyAdapter() {

            @Override
            public int replicas() {
                return replicas;
            }

            @Override
            public Object getGroup(InetAddress unit) {
                return unit;
            }

            @Override
            public boolean inAllocationRing(InetAddress other) {
                return dc.equals(snitch.getDatacenter(other));
            }
        };
    } else
        throw new ConfigurationException(String.format("Token allocation failed: the number of racks %d in datacenter %s is lower than its replication factor %d.", racks, dc, replicas));
}
Also used : ConfigurationException(org.apache.cassandra.exceptions.ConfigurationException) Topology(org.apache.cassandra.locator.TokenMetadata.Topology) InetAddress(java.net.InetAddress)

Example 2 with Topology

use of org.apache.cassandra.locator.TokenMetadata.Topology in project cassandra by apache.

the class NetworkTopologyStrategyTest method calculateNaturalEndpoints.

// Copy of older endpoints calculation algorithm for comparison
public static List<InetAddress> calculateNaturalEndpoints(Token searchToken, TokenMetadata tokenMetadata, Map<String, Integer> datacenters, IEndpointSnitch snitch) {
    // we want to preserve insertion order so that the first added endpoint becomes primary
    Set<InetAddress> replicas = new LinkedHashSet<>();
    // replicas we have found in each DC
    Map<String, Set<InetAddress>> dcReplicas = new HashMap<>(datacenters.size());
    for (Map.Entry<String, Integer> dc : datacenters.entrySet()) dcReplicas.put(dc.getKey(), new HashSet<InetAddress>(dc.getValue()));
    Topology topology = tokenMetadata.getTopology();
    // all endpoints in each DC, so we can check when we have exhausted all the members of a DC
    Multimap<String, InetAddress> allEndpoints = topology.getDatacenterEndpoints();
    // all racks in a DC so we can check when we have exhausted all racks in a DC
    Map<String, Multimap<String, InetAddress>> racks = topology.getDatacenterRacks();
    assert !allEndpoints.isEmpty() && !racks.isEmpty() : "not aware of any cluster members";
    // tracks the racks we have already placed replicas in
    Map<String, Set<String>> seenRacks = new HashMap<>(datacenters.size());
    for (Map.Entry<String, Integer> dc : datacenters.entrySet()) seenRacks.put(dc.getKey(), new HashSet<String>());
    // tracks the endpoints that we skipped over while looking for unique racks
    // when we relax the rack uniqueness we can append this to the current result so we don't have to wind back the iterator
    Map<String, Set<InetAddress>> skippedDcEndpoints = new HashMap<>(datacenters.size());
    for (Map.Entry<String, Integer> dc : datacenters.entrySet()) skippedDcEndpoints.put(dc.getKey(), new LinkedHashSet<InetAddress>());
    Iterator<Token> tokenIter = TokenMetadata.ringIterator(tokenMetadata.sortedTokens(), searchToken, false);
    while (tokenIter.hasNext() && !hasSufficientReplicas(dcReplicas, allEndpoints, datacenters)) {
        Token next = tokenIter.next();
        InetAddress ep = tokenMetadata.getEndpoint(next);
        String dc = snitch.getDatacenter(ep);
        // have we already found all replicas for this dc?
        if (!datacenters.containsKey(dc) || hasSufficientReplicas(dc, dcReplicas, allEndpoints, datacenters))
            continue;
        // can we skip checking the rack?
        if (seenRacks.get(dc).size() == racks.get(dc).keySet().size()) {
            dcReplicas.get(dc).add(ep);
            replicas.add(ep);
        } else {
            String rack = snitch.getRack(ep);
            // is this a new rack?
            if (seenRacks.get(dc).contains(rack)) {
                skippedDcEndpoints.get(dc).add(ep);
            } else {
                dcReplicas.get(dc).add(ep);
                replicas.add(ep);
                seenRacks.get(dc).add(rack);
                // if we've run out of distinct racks, add the hosts we skipped past already (up to RF)
                if (seenRacks.get(dc).size() == racks.get(dc).keySet().size()) {
                    Iterator<InetAddress> skippedIt = skippedDcEndpoints.get(dc).iterator();
                    while (skippedIt.hasNext() && !hasSufficientReplicas(dc, dcReplicas, allEndpoints, datacenters)) {
                        InetAddress nextSkipped = skippedIt.next();
                        dcReplicas.get(dc).add(nextSkipped);
                        replicas.add(nextSkipped);
                    }
                }
            }
        }
    }
    return new ArrayList<InetAddress>(replicas);
}
Also used : StringToken(org.apache.cassandra.dht.OrderPreservingPartitioner.StringToken) Token(org.apache.cassandra.dht.Token) Topology(org.apache.cassandra.locator.TokenMetadata.Topology) Multimap(com.google.common.collect.Multimap) HashMultimap(com.google.common.collect.HashMultimap) InetAddress(java.net.InetAddress) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 3 with Topology

use of org.apache.cassandra.locator.TokenMetadata.Topology in project cassandra by apache.

the class NetworkTopologyStrategy method calculateNaturalEndpoints.

/**
     * calculate endpoints in one pass through the tokens by tracking our progress in each DC.
     */
public List<InetAddress> calculateNaturalEndpoints(Token searchToken, TokenMetadata tokenMetadata) {
    // we want to preserve insertion order so that the first added endpoint becomes primary
    Set<InetAddress> replicas = new LinkedHashSet<>();
    Set<Pair<String, String>> seenRacks = new HashSet<>();
    Topology topology = tokenMetadata.getTopology();
    // all endpoints in each DC, so we can check when we have exhausted all the members of a DC
    Multimap<String, InetAddress> allEndpoints = topology.getDatacenterEndpoints();
    // all racks in a DC so we can check when we have exhausted all racks in a DC
    Map<String, Multimap<String, InetAddress>> racks = topology.getDatacenterRacks();
    assert !allEndpoints.isEmpty() && !racks.isEmpty() : "not aware of any cluster members";
    int dcsToFill = 0;
    Map<String, DatacenterEndpoints> dcs = new HashMap<>(datacenters.size() * 2);
    // Create a DatacenterEndpoints object for each non-empty DC.
    for (Map.Entry<String, Integer> en : datacenters.entrySet()) {
        String dc = en.getKey();
        int rf = en.getValue();
        int nodeCount = sizeOrZero(allEndpoints.get(dc));
        if (rf <= 0 || nodeCount <= 0)
            continue;
        DatacenterEndpoints dcEndpoints = new DatacenterEndpoints(rf, sizeOrZero(racks.get(dc)), nodeCount, replicas, seenRacks);
        dcs.put(dc, dcEndpoints);
        ++dcsToFill;
    }
    Iterator<Token> tokenIter = TokenMetadata.ringIterator(tokenMetadata.sortedTokens(), searchToken, false);
    while (dcsToFill > 0 && tokenIter.hasNext()) {
        Token next = tokenIter.next();
        InetAddress ep = tokenMetadata.getEndpoint(next);
        Pair<String, String> location = topology.getLocation(ep);
        DatacenterEndpoints dcEndpoints = dcs.get(location.left);
        if (dcEndpoints != null && dcEndpoints.addEndpointAndCheckIfDone(ep, location))
            --dcsToFill;
    }
    return new ArrayList<>(replicas);
}
Also used : Token(org.apache.cassandra.dht.Token) Topology(org.apache.cassandra.locator.TokenMetadata.Topology) Multimap(com.google.common.collect.Multimap) InetAddress(java.net.InetAddress) Pair(org.apache.cassandra.utils.Pair)

Aggregations

InetAddress (java.net.InetAddress)3 Topology (org.apache.cassandra.locator.TokenMetadata.Topology)3 Multimap (com.google.common.collect.Multimap)2 Token (org.apache.cassandra.dht.Token)2 HashMultimap (com.google.common.collect.HashMultimap)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 StringToken (org.apache.cassandra.dht.OrderPreservingPartitioner.StringToken)1 ConfigurationException (org.apache.cassandra.exceptions.ConfigurationException)1 Pair (org.apache.cassandra.utils.Pair)1