Search in sources :

Example 6 with Token

use of com.datastax.oss.driver.api.core.metadata.token.Token in project java-driver by datastax.

the class NetworkTopologyReplicationStrategyTest method should_abort_early_and_log_when_bad_replication_factor_cannot_be_met.

/**
 * When the replication factors are invalid (user error) and a datacenter has a replication factor
 * that cannot be met, we want to quickly abort and move on to the next DC (instead of keeping
 * scanning the ring in vain, which results in quadratic complexity). We also log a warning to
 * give the user a chance to fix their settings.
 *
 * @see <a href="https://datastax-oss.atlassian.net/browse/JAVA-702">JAVA-702</a>
 * @see <a href="https://datastax-oss.atlassian.net/browse/JAVA-859">JAVA-859</a>
 */
@Test
public void should_abort_early_and_log_when_bad_replication_factor_cannot_be_met() {
    // Given
    List<Token> ring = ImmutableList.of(TOKEN01, TOKEN04, TOKEN14, TOKEN19);
    locate(node1, DC1, RACK11);
    locate(node2, DC2, RACK21);
    Map<Token, Node> tokenToPrimary = ImmutableMap.of(TOKEN01, node1, TOKEN04, node2, TOKEN14, node1, TOKEN19, node2);
    Logger logger = (Logger) LoggerFactory.getLogger(NetworkTopologyReplicationStrategy.class);
    logger.addAppender(appender);
    try {
        // When
        int traversedTokensForValidSettings = countTraversedTokens(ring, tokenToPrimary, ImmutableMap.of(DC1, "1", DC2, "1"));
        // Then
        // No logs:
        verify(appender, never()).doAppend(any(ILoggingEvent.class));
        // When
        int traversedTokensForInvalidSettings = countTraversedTokens(ring, tokenToPrimary, ImmutableMap.of(DC1, "1", DC2, "1", DC3, "1"));
        // Did not take more steps than the valid settings
        assertThat(traversedTokensForInvalidSettings).isEqualTo(traversedTokensForValidSettings);
        // Did log:
        verify(appender).doAppend(loggingEventCaptor.capture());
        ILoggingEvent log = loggingEventCaptor.getValue();
        assertThat(log.getLevel()).isEqualTo(Level.WARN);
        assertThat(log.getMessage()).contains("could not achieve replication factor");
    } finally {
        logger.detachAppender(appender);
    }
}
Also used : Node(com.datastax.oss.driver.api.core.metadata.Node) Token(com.datastax.oss.driver.api.core.metadata.token.Token) Logger(ch.qos.logback.classic.Logger) ILoggingEvent(ch.qos.logback.classic.spi.ILoggingEvent) Test(org.junit.Test)

Example 7 with Token

use of com.datastax.oss.driver.api.core.metadata.token.Token in project java-driver by datastax.

the class NetworkTopologyReplicationStrategyTest method countTraversedTokens.

// Counts the number of steps on the ring for a particular computation
private int countTraversedTokens(List<Token> ring, Map<Token, Node> tokenToPrimary, ImmutableMap<String, String> replicationConfig) {
    AtomicInteger count = new AtomicInteger();
    List<Token> ringSpy = spy(ring);
    when(ringSpy.get(anyInt())).thenAnswer(invocation -> {
        count.incrementAndGet();
        return invocation.callRealMethod();
    });
    new NetworkTopologyReplicationStrategy(replicationConfig, "test").computeReplicasByToken(tokenToPrimary, ringSpy);
    return count.get();
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Token(com.datastax.oss.driver.api.core.metadata.token.Token)

Example 8 with Token

use of com.datastax.oss.driver.api.core.metadata.token.Token in project java-driver by datastax.

the class TokenRangeBase method mergeWith.

@NonNull
@Override
public TokenRange mergeWith(@NonNull TokenRange that) {
    if (this.equals(that)) {
        return this;
    }
    if (!(this.intersects(that) || this.end.equals(that.getStart()) || that.getEnd().equals(this.start))) {
        throw new IllegalArgumentException(String.format("Can't merge %s with %s because they neither intersect nor are adjacent", this, that));
    }
    if (this.isEmpty()) {
        return that;
    }
    if (that.isEmpty()) {
        return this;
    }
    // That's actually "starts in or is adjacent to the end of"
    boolean thisStartsInThat = contains(that, this.start, true) || this.start.equals(that.getEnd());
    boolean thatStartsInThis = contains(this, that.getStart(), true) || that.getStart().equals(this.end);
    // about them below
    if (thisStartsInThat && thatStartsInThis) {
        return fullRing();
    }
    // Starting at this.start, see how far we can go while staying in at least one of the ranges.
    Token mergedEnd = (thatStartsInThis && !contains(this, that.getEnd(), false)) ? that.getEnd() : this.end;
    // Repeat in the other direction.
    Token mergedStart = thisStartsInThat ? that.getStart() : this.start;
    return newTokenRange(mergedStart, mergedEnd);
}
Also used : Token(com.datastax.oss.driver.api.core.metadata.token.Token) NonNull(edu.umd.cs.findbugs.annotations.NonNull)

Example 9 with Token

use of com.datastax.oss.driver.api.core.metadata.token.Token in project java-driver by datastax.

the class EverywhereReplicationStrategy method computeReplicasByToken.

@Override
public Map<Token, Set<Node>> computeReplicasByToken(Map<Token, Node> tokenToPrimary, List<Token> ring) {
    ImmutableMap.Builder<Token, Set<Node>> result = ImmutableMap.builder();
    Set<Node> allNodes = ImmutableSet.copyOf(tokenToPrimary.values());
    for (Token token : tokenToPrimary.keySet()) {
        result = result.put(token, allNodes);
    }
    return result.build();
}
Also used : ImmutableSet(com.datastax.oss.driver.shaded.guava.common.collect.ImmutableSet) Set(java.util.Set) Node(com.datastax.oss.driver.api.core.metadata.Node) Token(com.datastax.oss.driver.api.core.metadata.token.Token) ImmutableMap(com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap)

Example 10 with Token

use of com.datastax.oss.driver.api.core.metadata.token.Token in project java-driver by datastax.

the class NetworkTopologyReplicationStrategy method computeReplicasByToken.

@Override
public Map<Token, Set<Node>> computeReplicasByToken(Map<Token, Node> tokenToPrimary, List<Token> ring) {
    // The implementation of this method was adapted from
    // org.apache.cassandra.locator.NetworkTopologyStrategy
    ImmutableMap.Builder<Token, Set<Node>> result = ImmutableMap.builder();
    Map<String, Set<String>> racks = getRacksInDcs(tokenToPrimary.values());
    Map<String, Integer> dcNodeCount = Maps.newHashMapWithExpectedSize(replicationFactors.size());
    Set<String> warnedDcs = Sets.newHashSetWithExpectedSize(replicationFactors.size());
    CanonicalNodeSetBuilder replicasBuilder = new CanonicalNodeSetBuilder();
    // find maximum number of nodes in each DC
    for (Node node : Sets.newHashSet(tokenToPrimary.values())) {
        String dc = node.getDatacenter();
        dcNodeCount.merge(dc, 1, Integer::sum);
    }
    for (int i = 0; i < ring.size(); i++) {
        replicasBuilder.clear();
        Map<String, Set<Node>> allDcReplicas = new HashMap<>();
        Map<String, Set<String>> seenRacks = new HashMap<>();
        Map<String, Set<Node>> skippedDcEndpoints = new HashMap<>();
        for (String dc : replicationFactors.keySet()) {
            allDcReplicas.put(dc, new HashSet<>());
            seenRacks.put(dc, new HashSet<>());
            // preserve order
            skippedDcEndpoints.put(dc, new LinkedHashSet<>());
        }
        for (int j = 0; j < ring.size() && !allDone(allDcReplicas, dcNodeCount); j++) {
            Node h = tokenToPrimary.get(getTokenWrapping(i + j, ring));
            String dc = h.getDatacenter();
            if (dc == null || !allDcReplicas.containsKey(dc)) {
                continue;
            }
            ReplicationFactor dcConfig = replicationFactors.get(dc);
            // since allDcReplicas.containsKey(dc)
            assert dcConfig != null;
            int rf = dcConfig.fullReplicas();
            Set<Node> dcReplicas = allDcReplicas.get(dc);
            if (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()) {
                replicasBuilder.add(h);
                dcReplicas.add(h);
            } else {
                // Is this a new rack?
                if (seenRacks.get(dc).contains(rack)) {
                    skippedDcEndpoints.get(dc).add(h);
                } else {
                    replicasBuilder.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<Node> skippedIt = skippedDcEndpoints.get(dc).iterator();
                        while (skippedIt.hasNext() && dcReplicas.size() < rf) {
                            Node nextSkipped = skippedIt.next();
                            replicasBuilder.add(nextSkipped);
                            dcReplicas.add(nextSkipped);
                        }
                    }
                }
            }
        }
        // Warn the user because that leads to quadratic performance of this method (JAVA-702).
        for (Map.Entry<String, Set<Node>> entry : allDcReplicas.entrySet()) {
            String dcName = entry.getKey();
            int expectedFactor = replicationFactors.get(dcName).fullReplicas();
            int achievedFactor = entry.getValue().size();
            if (achievedFactor < expectedFactor && !warnedDcs.contains(dcName)) {
                LOG.warn("[{}] Error while computing token map for replication settings {}: " + "could not achieve replication factor {} for datacenter {} (found only {} replicas).", logPrefix, replicationConfig, expectedFactor, dcName, achievedFactor);
                // only warn once per DC
                warnedDcs.add(dcName);
            }
        }
        result.put(ring.get(i), replicasBuilder.build());
    }
    return result.build();
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) HashMap(java.util.HashMap) Node(com.datastax.oss.driver.api.core.metadata.Node) Token(com.datastax.oss.driver.api.core.metadata.token.Token) ImmutableMap(com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap) HashMap(java.util.HashMap) ImmutableMap(com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap) Map(java.util.Map)

Aggregations

Token (com.datastax.oss.driver.api.core.metadata.token.Token)22 Node (com.datastax.oss.driver.api.core.metadata.Node)6 Test (org.junit.Test)6 TokenRange (com.datastax.oss.driver.api.core.metadata.token.TokenRange)5 TokenMap (com.datastax.oss.driver.api.core.metadata.TokenMap)4 ImmutableMap (com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap)4 ByteBuffer (java.nio.ByteBuffer)4 CqlIdentifier (com.datastax.oss.driver.api.core.CqlIdentifier)3 PreparedStatement (com.datastax.oss.driver.api.core.cql.PreparedStatement)3 Row (com.datastax.oss.driver.api.core.cql.Row)3 NonNull (edu.umd.cs.findbugs.annotations.NonNull)3 BigInteger (java.math.BigInteger)3 Set (java.util.Set)3 CqlSession (com.datastax.oss.driver.api.core.CqlSession)2 BoundStatement (com.datastax.oss.driver.api.core.cql.BoundStatement)2 DefaultNode (com.datastax.oss.driver.internal.core.metadata.DefaultNode)2 ByteOrderedToken (com.datastax.oss.driver.internal.core.metadata.token.ByteOrderedToken)2 Murmur3Token (com.datastax.oss.driver.internal.core.metadata.token.Murmur3Token)2 RandomToken (com.datastax.oss.driver.internal.core.metadata.token.RandomToken)2 ImmutableSet (com.datastax.oss.driver.shaded.guava.common.collect.ImmutableSet)2