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));
}
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);
}
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);
}
Aggregations