com.datastax.driver.core.ReplicationStategy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cassandra-driver-core Show documentation
Show all versions of cassandra-driver-core Show documentation
A driver for Apache Cassandra 1.2+ that works exclusively with the Cassandra Query Language version 3 (CQL3) and Cassandra's binary protocol.
The newest version!
/*
* 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;
import java.util.*;
import com.google.common.collect.ImmutableSet;
/*
* Computes the token->list association, given the token ring and token->primary token map.
*
* Note: it's not an interface mainly because we don't want to expose it.
*/
abstract class ReplicationStrategy {
static ReplicationStrategy create(Map replicationOptions) {
String strategyClass = replicationOptions.get("class");
if (strategyClass == null)
return null;
try {
if (strategyClass.contains("SimpleStrategy")) {
String repFactorString = replicationOptions.get("replication_factor");
return repFactorString == null ? null : new SimpleStrategy(Integer.parseInt(repFactorString));
} else if (strategyClass.contains("NetworkTopologyStrategy")) {
Map dcRfs = new HashMap();
for (Map.Entry entry : replicationOptions.entrySet())
{
if (entry.getKey().equals("class"))
continue;
dcRfs.put(entry.getKey(), Integer.parseInt(entry.getValue()));
}
return new NetworkTopologyStrategy(dcRfs);
} else {
// We might want to support oldNetworkTopologyStrategy, though not sure anyone still using that
return null;
}
} catch (NumberFormatException e) {
// Cassandra wouldn't let that pass in the first place so this really should never happen
return null;
}
}
abstract Map> computeTokenToReplicaMap(Map tokenToPrimary, List ring);
private static Token getTokenWrapping(int i, List ring) {
return ring.get(i % ring.size());
}
static class SimpleStrategy extends ReplicationStrategy {
private final int replicationFactor;
private SimpleStrategy(int replicationFactor) {
this.replicationFactor = replicationFactor;
}
Map> computeTokenToReplicaMap(Map tokenToPrimary, List ring) {
int rf = Math.min(replicationFactor, ring.size());
Map> replicaMap = new HashMap>(tokenToPrimary.size());
for (int i = 0; i < ring.size(); i++) {
// Consecutive sections of the ring can assigned to the same host
Set replicas = new LinkedHashSet();
for (int j = 0; j < ring.size() && replicas.size() < rf; j++)
replicas.add(tokenToPrimary.get(getTokenWrapping(i+j, ring)));
replicaMap.put(ring.get(i), ImmutableSet.copyOf(replicas));
}
return replicaMap;
}
}
static class NetworkTopologyStrategy extends ReplicationStrategy {
private final Map replicationFactors;
private NetworkTopologyStrategy(Map replicationFactors) {
this.replicationFactors = replicationFactors;
}
Map> computeTokenToReplicaMap(Map tokenToPrimary, List ring) {
// This is essentially a copy of org.apache.cassandra.locator.NetworkTopologyStrategy
Map> racks = getRacksInDcs(tokenToPrimary.values());
Map> replicaMap = new HashMap>(tokenToPrimary.size());
for (int i = 0; i < ring.size(); i++) {
Map> allDcReplicas = new HashMap>();
Map> seenRacks = new HashMap>();
Map> skippedDcEndpoints = new HashMap>();
for (String dc : replicationFactors.keySet()) {
allDcReplicas.put(dc, new HashSet());
seenRacks.put(dc, new HashSet());
skippedDcEndpoints.put(dc, new LinkedHashSet()); // preserve order
}
// Preserve order - primary replica will be first
Set replicas = new LinkedHashSet();
for (int j = 0; j < ring.size() && !allDone(allDcReplicas); j++) {
Host h = tokenToPrimary.get(getTokenWrapping(i + j, ring));
String dc = h.getDatacenter();
if (dc == null || !allDcReplicas.containsKey(dc))
continue;
Integer rf = replicationFactors.get(dc);
Set dcReplicas = allDcReplicas.get(dc);
if (rf == null || dcReplicas.size() >= rf)
continue;
String rack = h.getRack();
// Check if we already visited all racks in dc
if (rack == null || seenRacks.get(dc).size() == racks.get(dc).size()) {
replicas.add(h);
dcReplicas.add(h);
} else {
// Is this a new rack?
if (seenRacks.get(dc).contains(rack)) {
skippedDcEndpoints.get(dc).add(h);
} else {
replicas.add(h);
dcReplicas.add(h);
seenRacks.get(dc).add(rack);
// If we've run out of distinct racks, add the nodes skipped so far
if (seenRacks.get(dc).size() == racks.get(dc).size()) {
Iterator skippedIt = skippedDcEndpoints.get(dc).iterator();
while (skippedIt.hasNext() && dcReplicas.size() < rf) {
Host nextSkipped = skippedIt.next();
replicas.add(nextSkipped);
dcReplicas.add(nextSkipped);
}
}
}
}
}
replicaMap.put(ring.get(i), ImmutableSet.copyOf(replicas));
}
return replicaMap;
}
private boolean allDone(Map> map) {
for (Map.Entry> entry : map.entrySet())
if (entry.getValue().size() < replicationFactors.get(entry.getKey()))
return false;
return true;
}
private Map> getRacksInDcs(Iterable hosts) {
Map> result = new HashMap>();
for (Host host : hosts) {
Set racks = result.get(host.getDatacenter());
if (racks == null) {
racks = new HashSet();
result.put(host.getDatacenter(), racks);
}
racks.add(host.getRack());
}
return result;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy