use of org.apache.cassandra.locator.NetworkTopologyStrategy in project cassandra by apache.
the class RangeStreamer method useStrictSourcesForRanges.
/**
* @param strat AbstractReplicationStrategy of keyspace to check
* @return true when the node is bootstrapping, useStrictConsistency is true and # of nodes in the cluster is more than # of replica
*/
private boolean useStrictSourcesForRanges(AbstractReplicationStrategy strat) {
boolean res = useStrictConsistency && tokens != null;
if (res) {
int nodes = 0;
if (strat instanceof NetworkTopologyStrategy) {
ImmutableMultimap<String, InetAddressAndPort> dc2Nodes = metadata.getDC2AllEndpoints(snitch);
NetworkTopologyStrategy ntps = (NetworkTopologyStrategy) strat;
for (String dc : dc2Nodes.keySet()) nodes += ntps.getReplicationFactor(dc).allReplicas > 0 ? dc2Nodes.get(dc).size() : 0;
} else
nodes = metadata.getSizeOfAllEndpoints();
res = nodes > strat.getReplicationFactor().allReplicas;
}
return res;
}
use of org.apache.cassandra.locator.NetworkTopologyStrategy in project cassandra by apache.
the class ViewUtils method getViewNaturalEndpoint.
/**
* Calculate the natural endpoint for the view.
*
* The view natural endpoint is the endpoint which has the same cardinality as this node in the replication factor.
* The cardinality is the number at which this node would store a piece of data, given the change in replication
* factor. If the keyspace's replication strategy is a NetworkTopologyStrategy, we filter the ring to contain only
* nodes in the local datacenter when calculating cardinality.
*
* For example, if we have the following ring:
* {@code A, T1 -> B, T2 -> C, T3 -> A}
*
* For the token T1, at RF=1, A would be included, so A's cardinality for T1 is 1. For the token T1, at RF=2, B would
* be included, so B's cardinality for token T1 is 2. For token T3, at RF = 2, A would be included, so A's cardinality
* for T3 is 2.
*
* For a view whose base token is T1 and whose view token is T3, the pairings between the nodes would be:
* A writes to C (A's cardinality is 1 for T1, and C's cardinality is 1 for T3)
* B writes to A (B's cardinality is 2 for T1, and A's cardinality is 2 for T3)
* C writes to B (C's cardinality is 3 for T1, and B's cardinality is 3 for T3)
*
* @return Optional.empty() if this method is called using a base token which does not belong to this replica
*/
public static Optional<Replica> getViewNaturalEndpoint(AbstractReplicationStrategy replicationStrategy, Token baseToken, Token viewToken) {
String localDataCenter = DatabaseDescriptor.getEndpointSnitch().getLocalDatacenter();
EndpointsForToken naturalBaseReplicas = replicationStrategy.getNaturalReplicasForToken(baseToken);
EndpointsForToken naturalViewReplicas = replicationStrategy.getNaturalReplicasForToken(viewToken);
Optional<Replica> localReplica = Iterables.tryFind(naturalViewReplicas, Replica::isSelf).toJavaUtil();
if (localReplica.isPresent())
return localReplica;
// We only select replicas from our own DC
// TODO: this is poor encapsulation, leaking implementation details of replication strategy
Predicate<Replica> isLocalDC = r -> !(replicationStrategy instanceof NetworkTopologyStrategy) || DatabaseDescriptor.getEndpointSnitch().getDatacenter(r).equals(localDataCenter);
// We have to remove any endpoint which is shared between the base and the view, as it will select itself
// and throw off the counts otherwise.
EndpointsForToken baseReplicas = naturalBaseReplicas.filter(r -> !naturalViewReplicas.endpoints().contains(r.endpoint()) && isLocalDC.test(r));
EndpointsForToken viewReplicas = naturalViewReplicas.filter(r -> !naturalBaseReplicas.endpoints().contains(r.endpoint()) && isLocalDC.test(r));
// number of replicas for all of the tokens in the ring.
assert baseReplicas.size() == viewReplicas.size() : "Replication strategy should have the same number of endpoints for the base and the view";
int baseIdx = -1;
for (int i = 0; i < baseReplicas.size(); i++) {
if (baseReplicas.get(i).isSelf()) {
baseIdx = i;
break;
}
}
if (baseIdx < 0)
// This node is not a base replica of this key, so we return empty
return Optional.empty();
return Optional.of(viewReplicas.get(baseIdx));
}
use of org.apache.cassandra.locator.NetworkTopologyStrategy in project cassandra by apache.
the class MoveTest method newTestWriteEndpointsDuringMove.
/*
* Test whether write endpoints is correct when the node is moving. Uses
* StorageService.onChange and does not manipulate token metadata directly.
*/
@Test
public void newTestWriteEndpointsDuringMove() throws Exception {
StorageService ss = StorageService.instance;
final int RING_SIZE = 10;
// index of the moving node
final int MOVING_NODE = 3;
TokenMetadata tmd = ss.getTokenMetadata();
VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner);
ArrayList<Token> endpointTokens = new ArrayList<Token>();
ArrayList<Token> keyTokens = new ArrayList<Token>();
List<InetAddressAndPort> hosts = new ArrayList<>();
List<UUID> hostIds = new ArrayList<UUID>();
Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, RING_SIZE);
Map<Token, List<InetAddressAndPort>> expectedEndpoints = new HashMap<>();
for (Token token : keyTokens) {
List<InetAddressAndPort> endpoints = new ArrayList<>();
Iterator<Token> tokenIter = TokenMetadata.ringIterator(tmd.sortedTokens(), token, false);
while (tokenIter.hasNext()) {
endpoints.add(tmd.getEndpoint(tokenIter.next()));
}
expectedEndpoints.put(token, endpoints);
}
// node LEAVING_NODE should move to this token
Token newToken = positionToken(MOVING_NODE);
// Third node leaves
ss.onChange(hosts.get(MOVING_NODE), ApplicationState.STATUS, valueFactory.moving(newToken));
PendingRangeCalculatorService.instance.blockUntilFinished();
assertTrue(tmd.isMoving(hosts.get(MOVING_NODE)));
AbstractReplicationStrategy strategy;
for (String keyspaceName : Schema.instance.getNonLocalStrategyKeyspaces()) {
strategy = getStrategy(keyspaceName, tmd);
if (strategy instanceof NetworkTopologyStrategy)
continue;
int numMoved = 0;
for (Token token : keyTokens) {
int replicationFactor = strategy.getReplicationFactor().allReplicas;
EndpointsForToken actual = tmd.getWriteEndpoints(token, keyspaceName, strategy.calculateNaturalReplicas(token, tmd.cloneOnlyTokenMap()).forToken(token));
HashSet<InetAddressAndPort> expected = new HashSet<>();
for (int i = 0; i < replicationFactor; i++) {
expected.add(expectedEndpoints.get(token).get(i));
}
if (expected.size() == actual.size()) {
assertEquals("mismatched endpoint sets", expected, actual.endpoints());
} else {
expected.add(hosts.get(MOVING_NODE));
assertEquals("mismatched endpoint sets", expected, actual.endpoints());
numMoved++;
}
}
assertEquals("mismatched number of moved token", 1, numMoved);
}
// moving endpoint back to the normal state
ss.onChange(hosts.get(MOVING_NODE), ApplicationState.STATUS, valueFactory.normal(Collections.singleton(newToken)));
}
use of org.apache.cassandra.locator.NetworkTopologyStrategy in project cassandra by apache.
the class ViewUtils method getViewNaturalEndpoint.
/**
* Calculate the natural endpoint for the view.
*
* The view natural endpoint is the endpoint which has the same cardinality as this node in the replication factor.
* The cardinality is the number at which this node would store a piece of data, given the change in replication
* factor. If the keyspace's replication strategy is a NetworkTopologyStrategy, we filter the ring to contain only
* nodes in the local datacenter when calculating cardinality.
*
* For example, if we have the following ring:
* {@code A, T1 -> B, T2 -> C, T3 -> A}
*
* For the token T1, at RF=1, A would be included, so A's cardinality for T1 is 1. For the token T1, at RF=2, B would
* be included, so B's cardinality for token T1 is 2. For token T3, at RF = 2, A would be included, so A's cardinality
* for T3 is 2.
*
* For a view whose base token is T1 and whose view token is T3, the pairings between the nodes would be:
* A writes to C (A's cardinality is 1 for T1, and C's cardinality is 1 for T3)
* B writes to A (B's cardinality is 2 for T1, and A's cardinality is 2 for T3)
* C writes to B (C's cardinality is 3 for T1, and B's cardinality is 3 for T3)
*
* @return Optional.empty() if this method is called using a base token which does not belong to this replica
*/
public static Optional<InetAddress> getViewNaturalEndpoint(String keyspaceName, Token baseToken, Token viewToken) {
AbstractReplicationStrategy replicationStrategy = Keyspace.open(keyspaceName).getReplicationStrategy();
String localDataCenter = DatabaseDescriptor.getEndpointSnitch().getDatacenter(FBUtilities.getBroadcastAddress());
List<InetAddress> baseEndpoints = new ArrayList<>();
List<InetAddress> viewEndpoints = new ArrayList<>();
for (InetAddress baseEndpoint : replicationStrategy.getNaturalEndpoints(baseToken)) {
// An endpoint is local if we're not using Net
if (!(replicationStrategy instanceof NetworkTopologyStrategy) || DatabaseDescriptor.getEndpointSnitch().getDatacenter(baseEndpoint).equals(localDataCenter))
baseEndpoints.add(baseEndpoint);
}
for (InetAddress viewEndpoint : replicationStrategy.getNaturalEndpoints(viewToken)) {
// If we are a base endpoint which is also a view replica, we use ourselves as our view replica
if (viewEndpoint.equals(FBUtilities.getBroadcastAddress()))
return Optional.of(viewEndpoint);
// and throw off the counts otherwise.
if (baseEndpoints.contains(viewEndpoint))
baseEndpoints.remove(viewEndpoint);
else if (!(replicationStrategy instanceof NetworkTopologyStrategy) || DatabaseDescriptor.getEndpointSnitch().getDatacenter(viewEndpoint).equals(localDataCenter))
viewEndpoints.add(viewEndpoint);
}
// number of replicas for all of the tokens in the ring.
assert baseEndpoints.size() == viewEndpoints.size() : "Replication strategy should have the same number of endpoints for the base and the view";
int baseIdx = baseEndpoints.indexOf(FBUtilities.getBroadcastAddress());
if (baseIdx < 0)
//This node is not a base replica of this key, so we return empty
return Optional.empty();
return Optional.of(viewEndpoints.get(baseIdx));
}
use of org.apache.cassandra.locator.NetworkTopologyStrategy in project cassandra by apache.
the class TokenAllocation method create.
static TokenAllocation create(IEndpointSnitch snitch, TokenMetadata tokenMetadata, int replicas, int numTokens) {
// We create a fake NTS replication strategy with the specified RF in the local DC
HashMap<String, String> options = new HashMap<>();
options.put(snitch.getLocalDatacenter(), Integer.toString(replicas));
NetworkTopologyStrategy fakeReplicationStrategy = new NetworkTopologyStrategy(null, tokenMetadata, snitch, options);
TokenAllocation allocator = new TokenAllocation(tokenMetadata, fakeReplicationStrategy, numTokens);
return allocator;
}
Aggregations