Search in sources :

Example 1 with NetworkTopologyStrategy

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;
}
Also used : NetworkTopologyStrategy(org.apache.cassandra.locator.NetworkTopologyStrategy) InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) RangesAtEndpoint(org.apache.cassandra.locator.RangesAtEndpoint)

Example 2 with NetworkTopologyStrategy

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));
}
Also used : Iterables(com.google.common.collect.Iterables) Token(org.apache.cassandra.dht.Token) AbstractReplicationStrategy(org.apache.cassandra.locator.AbstractReplicationStrategy) EndpointsForToken(org.apache.cassandra.locator.EndpointsForToken) Predicate(java.util.function.Predicate) Optional(java.util.Optional) DatabaseDescriptor(org.apache.cassandra.config.DatabaseDescriptor) Keyspace(org.apache.cassandra.db.Keyspace) NetworkTopologyStrategy(org.apache.cassandra.locator.NetworkTopologyStrategy) Replica(org.apache.cassandra.locator.Replica) EndpointsForToken(org.apache.cassandra.locator.EndpointsForToken) NetworkTopologyStrategy(org.apache.cassandra.locator.NetworkTopologyStrategy) Replica(org.apache.cassandra.locator.Replica)

Example 3 with NetworkTopologyStrategy

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)));
}
Also used : VersionedValue(org.apache.cassandra.gms.VersionedValue) InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) EndpointsForToken(org.apache.cassandra.locator.EndpointsForToken) EndpointsForToken(org.apache.cassandra.locator.EndpointsForToken) BigIntegerToken(org.apache.cassandra.dht.RandomPartitioner.BigIntegerToken) Token(org.apache.cassandra.dht.Token) TokenMetadata(org.apache.cassandra.locator.TokenMetadata) RangesAtEndpoint(org.apache.cassandra.locator.RangesAtEndpoint) RangesByEndpoint(org.apache.cassandra.locator.RangesByEndpoint) NetworkTopologyStrategy(org.apache.cassandra.locator.NetworkTopologyStrategy) AbstractReplicationStrategy(org.apache.cassandra.locator.AbstractReplicationStrategy) Test(org.junit.Test)

Example 4 with NetworkTopologyStrategy

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));
}
Also used : NetworkTopologyStrategy(org.apache.cassandra.locator.NetworkTopologyStrategy) ArrayList(java.util.ArrayList) AbstractReplicationStrategy(org.apache.cassandra.locator.AbstractReplicationStrategy) InetAddress(java.net.InetAddress)

Example 5 with NetworkTopologyStrategy

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;
}
Also used : NetworkTopologyStrategy(org.apache.cassandra.locator.NetworkTopologyStrategy) HashMap(java.util.HashMap)

Aggregations

NetworkTopologyStrategy (org.apache.cassandra.locator.NetworkTopologyStrategy)6 AbstractReplicationStrategy (org.apache.cassandra.locator.AbstractReplicationStrategy)3 InetAddress (java.net.InetAddress)2 Token (org.apache.cassandra.dht.Token)2 EndpointsForToken (org.apache.cassandra.locator.EndpointsForToken)2 InetAddressAndPort (org.apache.cassandra.locator.InetAddressAndPort)2 RangesAtEndpoint (org.apache.cassandra.locator.RangesAtEndpoint)2 Iterables (com.google.common.collect.Iterables)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 Optional (java.util.Optional)1 Predicate (java.util.function.Predicate)1 DatabaseDescriptor (org.apache.cassandra.config.DatabaseDescriptor)1 Keyspace (org.apache.cassandra.db.Keyspace)1 BigIntegerToken (org.apache.cassandra.dht.RandomPartitioner.BigIntegerToken)1 VersionedValue (org.apache.cassandra.gms.VersionedValue)1 RangesByEndpoint (org.apache.cassandra.locator.RangesByEndpoint)1 Replica (org.apache.cassandra.locator.Replica)1 TokenMetadata (org.apache.cassandra.locator.TokenMetadata)1 Test (org.junit.Test)1