Search in sources :

Example 1 with Range

use of org.apache.cassandra.dht.Range in project cassandra by apache.

the class StorageService method describeRing.

private List<TokenRange> describeRing(String keyspace, boolean includeOnlyLocalDC) throws InvalidRequestException {
    if (!Schema.instance.getKeyspaces().contains(keyspace))
        throw new InvalidRequestException("No such keyspace: " + keyspace);
    if (keyspace == null || Keyspace.open(keyspace).getReplicationStrategy() instanceof LocalStrategy)
        throw new InvalidRequestException("There is no ring for the keyspace: " + keyspace);
    List<TokenRange> ranges = new ArrayList<>();
    Token.TokenFactory tf = getTokenFactory();
    Map<Range<Token>, List<InetAddress>> rangeToAddressMap = includeOnlyLocalDC ? getRangeToAddressMapInLocalDC(keyspace) : getRangeToAddressMap(keyspace);
    for (Map.Entry<Range<Token>, List<InetAddress>> entry : rangeToAddressMap.entrySet()) ranges.add(TokenRange.create(tf, entry.getKey(), entry.getValue()));
    return ranges;
}
Also used : TokenFactory(org.apache.cassandra.dht.Token.TokenFactory) Arrays.asList(java.util.Arrays.asList) Collectors.toList(java.util.stream.Collectors.toList) Range(org.apache.cassandra.dht.Range)

Example 2 with Range

use of org.apache.cassandra.dht.Range in project cassandra by apache.

the class StorageService method removeNode.

/**
     * Remove a node that has died, attempting to restore the replica count.
     * If the node is alive, decommission should be attempted.  If decommission
     * fails, then removeNode should be called.  If we fail while trying to
     * restore the replica count, finally forceRemoveCompleteion should be
     * called to forcibly remove the node without regard to replica count.
     *
     * @param hostIdString Host ID for the node
     */
public void removeNode(String hostIdString) {
    InetAddress myAddress = FBUtilities.getBroadcastAddress();
    UUID localHostId = tokenMetadata.getHostId(myAddress);
    UUID hostId = UUID.fromString(hostIdString);
    InetAddress endpoint = tokenMetadata.getEndpointForHostId(hostId);
    if (endpoint == null)
        throw new UnsupportedOperationException("Host ID not found.");
    if (!tokenMetadata.isMember(endpoint))
        throw new UnsupportedOperationException("Node to be removed is not a member of the token ring");
    if (endpoint.equals(myAddress))
        throw new UnsupportedOperationException("Cannot remove self");
    if (Gossiper.instance.getLiveMembers().contains(endpoint))
        throw new UnsupportedOperationException("Node " + endpoint + " is alive and owns this ID. Use decommission command to remove it from the ring");
    // A leaving endpoint that is dead is already being removed.
    if (tokenMetadata.isLeaving(endpoint))
        logger.warn("Node {} is already being removed, continuing removal anyway", endpoint);
    if (!replicatingNodes.isEmpty())
        throw new UnsupportedOperationException("This node is already processing a removal. Wait for it to complete, or use 'removenode force' if this has failed.");
    Collection<Token> tokens = tokenMetadata.getTokens(endpoint);
    // Find the endpoints that are going to become responsible for data
    for (String keyspaceName : Schema.instance.getNonLocalStrategyKeyspaces()) {
        // if the replication factor is 1 the data is lost so we shouldn't wait for confirmation
        if (Keyspace.open(keyspaceName).getReplicationStrategy().getReplicationFactor() == 1)
            continue;
        // get all ranges that change ownership (that is, a node needs
        // to take responsibility for new range)
        Multimap<Range<Token>, InetAddress> changedRanges = getChangedRangesForLeaving(keyspaceName, endpoint);
        IFailureDetector failureDetector = FailureDetector.instance;
        for (InetAddress ep : changedRanges.values()) {
            if (failureDetector.isAlive(ep))
                replicatingNodes.add(ep);
            else
                logger.warn("Endpoint {} is down and will not receive data for re-replication of {}", ep, endpoint);
        }
    }
    removingNode = endpoint;
    tokenMetadata.addLeavingEndpoint(endpoint);
    PendingRangeCalculatorService.instance.update();
    // the gossiper will handle spoofing this node's state to REMOVING_TOKEN for us
    // we add our own token so other nodes to let us know when they're done
    Gossiper.instance.advertiseRemoving(endpoint, hostId, localHostId);
    // kick off streaming commands
    restoreReplicaCount(endpoint, myAddress);
    // wait for ReplicationFinishedVerbHandler to signal we're done
    while (!replicatingNodes.isEmpty()) {
        Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS);
    }
    excise(tokens, endpoint);
    // gossiper will indicate the token has left
    Gossiper.instance.advertiseTokenRemoved(endpoint, hostId);
    replicatingNodes.clear();
    removingNode = null;
}
Also used : Range(org.apache.cassandra.dht.Range) InetAddress(java.net.InetAddress)

Example 3 with Range

use of org.apache.cassandra.dht.Range in project cassandra by apache.

the class StorageService method streamRanges.

/**
     * Seed data to the endpoints that will be responsible for it at the future
     *
     * @param rangesToStreamByKeyspace keyspaces and data ranges with endpoints included for each
     * @return async Future for whether stream was success
     */
private Future<StreamState> streamRanges(Map<String, Multimap<Range<Token>, InetAddress>> rangesToStreamByKeyspace) {
    // First, we build a list of ranges to stream to each host, per table
    Map<String, Map<InetAddress, List<Range<Token>>>> sessionsToStreamByKeyspace = new HashMap<>();
    for (Map.Entry<String, Multimap<Range<Token>, InetAddress>> entry : rangesToStreamByKeyspace.entrySet()) {
        String keyspace = entry.getKey();
        Multimap<Range<Token>, InetAddress> rangesWithEndpoints = entry.getValue();
        if (rangesWithEndpoints.isEmpty())
            continue;
        Map<InetAddress, Set<Range<Token>>> transferredRangePerKeyspace = SystemKeyspace.getTransferredRanges("Unbootstrap", keyspace, StorageService.instance.getTokenMetadata().partitioner);
        Map<InetAddress, List<Range<Token>>> rangesPerEndpoint = new HashMap<>();
        for (Map.Entry<Range<Token>, InetAddress> endPointEntry : rangesWithEndpoints.entries()) {
            Range<Token> range = endPointEntry.getKey();
            InetAddress endpoint = endPointEntry.getValue();
            Set<Range<Token>> transferredRanges = transferredRangePerKeyspace.get(endpoint);
            if (transferredRanges != null && transferredRanges.contains(range)) {
                logger.debug("Skipping transferred range {} of keyspace {}, endpoint {}", range, keyspace, endpoint);
                continue;
            }
            List<Range<Token>> curRanges = rangesPerEndpoint.get(endpoint);
            if (curRanges == null) {
                curRanges = new LinkedList<>();
                rangesPerEndpoint.put(endpoint, curRanges);
            }
            curRanges.add(range);
        }
        sessionsToStreamByKeyspace.put(keyspace, rangesPerEndpoint);
    }
    StreamPlan streamPlan = new StreamPlan("Unbootstrap");
    // Vinculate StreamStateStore to current StreamPlan to update transferred ranges per StreamSession
    streamPlan.listeners(streamStateStore);
    for (Map.Entry<String, Map<InetAddress, List<Range<Token>>>> entry : sessionsToStreamByKeyspace.entrySet()) {
        String keyspaceName = entry.getKey();
        Map<InetAddress, List<Range<Token>>> rangesPerEndpoint = entry.getValue();
        for (Map.Entry<InetAddress, List<Range<Token>>> rangesEntry : rangesPerEndpoint.entrySet()) {
            List<Range<Token>> ranges = rangesEntry.getValue();
            InetAddress newEndpoint = rangesEntry.getKey();
            InetAddress preferred = SystemKeyspace.getPreferredIP(newEndpoint);
            // TODO each call to transferRanges re-flushes, this is potentially a lot of waste
            streamPlan.transferRanges(newEndpoint, preferred, keyspaceName, ranges);
        }
    }
    return streamPlan.execute();
}
Also used : Range(org.apache.cassandra.dht.Range) Arrays.asList(java.util.Arrays.asList) Collectors.toList(java.util.stream.Collectors.toList) InetAddress(java.net.InetAddress)

Example 4 with Range

use of org.apache.cassandra.dht.Range in project cassandra by apache.

the class StorageService method getRangeToRpcaddressMap.

/**
     * for a keyspace, return the ranges and corresponding RPC addresses for a given keyspace.
     * @param keyspace
     * @return the endpoint map
     */
public Map<List<String>, List<String>> getRangeToRpcaddressMap(String keyspace) {
    /* All the ranges for the tokens */
    Map<List<String>, List<String>> map = new HashMap<>();
    for (Map.Entry<Range<Token>, List<InetAddress>> entry : getRangeToAddressMap(keyspace).entrySet()) {
        List<String> rpcaddrs = new ArrayList<>(entry.getValue().size());
        for (InetAddress endpoint : entry.getValue()) {
            rpcaddrs.add(getRpcaddress(endpoint));
        }
        map.put(entry.getKey().asList(), rpcaddrs);
    }
    return map;
}
Also used : Arrays.asList(java.util.Arrays.asList) Collectors.toList(java.util.stream.Collectors.toList) Range(org.apache.cassandra.dht.Range) InetAddress(java.net.InetAddress)

Example 5 with Range

use of org.apache.cassandra.dht.Range in project cassandra by apache.

the class SizeEstimatesRecorder method run.

public void run() {
    TokenMetadata metadata = StorageService.instance.getTokenMetadata().cloneOnlyTokenMap();
    if (!metadata.isMember(FBUtilities.getBroadcastAddress())) {
        logger.debug("Node is not part of the ring; not recording size estimates");
        return;
    }
    logger.trace("Recording size estimates");
    for (Keyspace keyspace : Keyspace.nonLocalStrategy()) {
        Collection<Range<Token>> localRanges = StorageService.instance.getPrimaryRangesForEndpoint(keyspace.getName(), FBUtilities.getBroadcastAddress());
        for (ColumnFamilyStore table : keyspace.getColumnFamilyStores()) {
            long start = System.nanoTime();
            recordSizeEstimates(table, localRanges);
            long passed = System.nanoTime() - start;
            logger.trace("Spent {} milliseconds on estimating {}.{} size", TimeUnit.NANOSECONDS.toMillis(passed), table.metadata.keyspace, table.metadata.name);
        }
    }
}
Also used : TokenMetadata(org.apache.cassandra.locator.TokenMetadata) Range(org.apache.cassandra.dht.Range)

Aggregations

Range (org.apache.cassandra.dht.Range)120 Token (org.apache.cassandra.dht.Token)74 Test (org.junit.Test)63 InetAddress (java.net.InetAddress)35 SSTableReader (org.apache.cassandra.io.sstable.format.SSTableReader)28 TokenMetadata (org.apache.cassandra.locator.TokenMetadata)17 TreeRange (org.apache.cassandra.utils.MerkleTree.TreeRange)17 IPartitioner (org.apache.cassandra.dht.IPartitioner)14 UUID (java.util.UUID)12 ColumnFamilyStore (org.apache.cassandra.db.ColumnFamilyStore)12 StringToken (org.apache.cassandra.dht.OrderPreservingPartitioner.StringToken)9 IOException (java.io.IOException)8 ArrayList (java.util.ArrayList)8 LifecycleTransaction (org.apache.cassandra.db.lifecycle.LifecycleTransaction)8 BigIntegerToken (org.apache.cassandra.dht.RandomPartitioner.BigIntegerToken)8 KeyspaceMetadata (org.apache.cassandra.schema.KeyspaceMetadata)8 LongToken (org.apache.cassandra.dht.Murmur3Partitioner.LongToken)7 BigInteger (java.math.BigInteger)6 HashSet (java.util.HashSet)6 BytesToken (org.apache.cassandra.dht.ByteOrderedPartitioner.BytesToken)6