use of org.apache.cassandra.locator.RangesAtEndpoint in project cassandra by apache.
the class StreamSession method addTransferRanges.
/**
* Set up transfer for specific keyspace/ranges/CFs
*
* @param keyspace Transfer keyspace
* @param replicas Transfer ranges
* @param columnFamilies Transfer ColumnFamilies
* @param flushTables flush tables?
*/
synchronized void addTransferRanges(String keyspace, RangesAtEndpoint replicas, Collection<String> columnFamilies, boolean flushTables) {
failIfFinished();
Collection<ColumnFamilyStore> stores = getColumnFamilyStores(keyspace, columnFamilies);
if (flushTables)
flushSSTables(stores);
// Was it safe to remove this normalize, sorting seems not to matter, merging? Maybe we should have?
// Do we need to unwrap here also or is that just making it worse?
// Range and if it's transient
RangesAtEndpoint unwrappedRanges = replicas.unwrap();
List<OutgoingStream> streams = getOutgoingStreamsForRanges(unwrappedRanges, stores, pendingRepair, previewKind);
addTransferStreams(streams);
Set<Range<Token>> toBeUpdated = transferredRangesPerKeyspace.get(keyspace);
if (toBeUpdated == null) {
toBeUpdated = new HashSet<>();
}
toBeUpdated.addAll(replicas.ranges());
transferredRangesPerKeyspace.put(keyspace, toBeUpdated);
}
use of org.apache.cassandra.locator.RangesAtEndpoint in project cassandra by apache.
the class CancelCompactionsTest method testAnticompaction.
@Test
public void testAnticompaction() throws InterruptedException, ExecutionException {
ColumnFamilyStore cfs = MockSchema.newCFS();
List<SSTableReader> sstables = createSSTables(cfs, 10, 0);
List<SSTableReader> alreadyRepairedSSTables = createSSTables(cfs, 10, 10);
for (SSTableReader sstable : alreadyRepairedSSTables) AbstractPendingRepairTest.mutateRepaired(sstable, System.currentTimeMillis());
assertEquals(20, cfs.getLiveSSTables().size());
List<TestCompactionTask> tcts = new ArrayList<>();
tcts.add(new TestCompactionTask(cfs, new HashSet<>(sstables.subList(0, 2))));
tcts.add(new TestCompactionTask(cfs, new HashSet<>(sstables.subList(3, 4))));
tcts.add(new TestCompactionTask(cfs, new HashSet<>(sstables.subList(5, 7))));
tcts.add(new TestCompactionTask(cfs, new HashSet<>(sstables.subList(8, 9))));
List<TestCompactionTask> nonAffectedTcts = new ArrayList<>();
nonAffectedTcts.add(new TestCompactionTask(cfs, new HashSet<>(alreadyRepairedSSTables)));
try {
tcts.forEach(TestCompactionTask::start);
nonAffectedTcts.forEach(TestCompactionTask::start);
List<CompactionInfo.Holder> activeCompactions = getActiveCompactionsForTable(cfs);
assertEquals(5, activeCompactions.size());
// make sure that sstables are fully contained so that the metadata gets mutated
Range<Token> range = new Range<>(token(-1), token(49));
UUID prsid = UUID.randomUUID();
ActiveRepairService.instance.registerParentRepairSession(prsid, InetAddressAndPort.getLocalHost(), Collections.singletonList(cfs), Collections.singleton(range), true, 1, true, PreviewKind.NONE);
InetAddressAndPort local = FBUtilities.getBroadcastAddressAndPort();
RangesAtEndpoint rae = RangesAtEndpoint.builder(local).add(new Replica(local, range, true)).build();
PendingAntiCompaction pac = new PendingAntiCompaction(prsid, Collections.singleton(cfs), rae, Executors.newSingleThreadExecutor(), () -> false);
Future<?> fut = pac.run();
Thread.sleep(600);
List<TestCompactionTask> toAbort = new ArrayList<>();
for (CompactionInfo.Holder holder : getActiveCompactionsForTable(cfs)) {
if (holder.getCompactionInfo().getSSTables().stream().anyMatch(sstable -> sstable.intersects(Collections.singleton(range)) && !sstable.isRepaired() && !sstable.isPendingRepair())) {
assertTrue(holder.isStopRequested());
for (TestCompactionTask tct : tcts) if (tct.sstables.equals(holder.getCompactionInfo().getSSTables()))
toAbort.add(tct);
} else
assertFalse(holder.isStopRequested());
}
assertEquals(2, toAbort.size());
toAbort.forEach(TestCompactionTask::abort);
fut.get();
for (SSTableReader sstable : sstables) assertTrue(!sstable.intersects(Collections.singleton(range)) || sstable.isPendingRepair());
} finally {
tcts.forEach(TestCompactionTask::abort);
nonAffectedTcts.forEach(TestCompactionTask::abort);
}
}
use of org.apache.cassandra.locator.RangesAtEndpoint in project cassandra by apache.
the class RangeRelocator method computeRanges.
private static void computeRanges(RangesAtEndpoint srcRanges, RangesAtEndpoint dstRanges, RangesAtEndpoint.Builder ranges) {
for (Replica src : srcRanges) {
boolean intersect = false;
RangesAtEndpoint remainder = null;
for (Replica dst : dstRanges) {
logger.debug("Comparing {} and {}", src, dst);
// Stream the full range if there's no intersection
if (!src.intersectsOnRange(dst))
continue;
// If we're transitioning from full to transient
if (src.isFull() && dst.isTransient())
continue;
if (remainder == null) {
remainder = src.subtractIgnoreTransientStatus(dst.range());
} else {
// Re-subtract ranges to avoid overstreaming in cases when the single range is split or merged
RangesAtEndpoint.Builder newRemainder = new RangesAtEndpoint.Builder(remainder.endpoint());
for (Replica replica : remainder) newRemainder.addAll(replica.subtractIgnoreTransientStatus(dst.range()));
remainder = newRemainder.build();
}
intersect = true;
}
if (!intersect) {
assert remainder == null;
logger.debug(" Doesn't intersect adding {}", src);
// should stream whole old range
ranges.add(src);
} else {
ranges.addAll(remainder);
logger.debug(" Intersects adding {}", remainder);
}
}
}
use of org.apache.cassandra.locator.RangesAtEndpoint in project cassandra by apache.
the class RangeRelocator method calculateToFromStreams.
public void calculateToFromStreams() {
logger.debug("Current tmd: {}, Updated tmd: {}", tokenMetaClone, tokenMetaCloneAllSettled);
for (String keyspace : keyspaceNames) {
// replication strategy of the current keyspace
AbstractReplicationStrategy strategy = Keyspace.open(keyspace).getReplicationStrategy();
logger.info("Calculating ranges to stream and request for keyspace {}", keyspace);
// From what I have seen we only ever call this with a single token from StorageService.move(Token)
for (Token newToken : tokens) {
Collection<Token> currentTokens = tokenMetaClone.getTokens(localAddress);
if (currentTokens.size() > 1 || currentTokens.isEmpty()) {
throw new AssertionError("Unexpected current tokens: " + currentTokens);
}
// calculated parts of the ranges to request/stream from/to nodes in the ring
Pair<RangesAtEndpoint, RangesAtEndpoint> streamAndFetchOwnRanges;
// so it's easier to just identify this case up front.
if (tokenMetaClone.getTopology().getDatacenterEndpoints().get(DatabaseDescriptor.getEndpointSnitch().getLocalDatacenter()).size() > 1) {
// getting collection of the currently used ranges by this keyspace
RangesAtEndpoint currentReplicas = strategy.getAddressReplicas(localAddress);
// collection of ranges which this node will serve after move to the new token
RangesAtEndpoint updatedReplicas = strategy.getPendingAddressRanges(tokenMetaClone, newToken, localAddress);
streamAndFetchOwnRanges = calculateStreamAndFetchRanges(currentReplicas, updatedReplicas);
} else {
streamAndFetchOwnRanges = Pair.create(RangesAtEndpoint.empty(localAddress), RangesAtEndpoint.empty(localAddress));
}
RangesByEndpoint rangesToStream = calculateRangesToStreamWithEndpoints(streamAndFetchOwnRanges.left, strategy, tokenMetaClone, tokenMetaCloneAllSettled);
logger.info("Endpoint ranges to stream to " + rangesToStream);
// stream ranges
for (InetAddressAndPort address : rangesToStream.keySet()) {
logger.debug("Will stream range {} of keyspace {} to endpoint {}", rangesToStream.get(address), keyspace, address);
RangesAtEndpoint ranges = rangesToStream.get(address);
streamPlan.transferRanges(address, keyspace, ranges);
}
Multimap<InetAddressAndPort, RangeStreamer.FetchReplica> rangesToFetch = calculateRangesToFetchWithPreferredEndpoints(streamAndFetchOwnRanges.right, strategy, keyspace, tokenMetaClone, tokenMetaCloneAllSettled);
// stream requests
rangesToFetch.asMap().forEach((address, sourceAndOurReplicas) -> {
RangesAtEndpoint full = sourceAndOurReplicas.stream().filter(pair -> pair.remote.isFull()).map(pair -> pair.local).collect(RangesAtEndpoint.collector(localAddress));
RangesAtEndpoint trans = sourceAndOurReplicas.stream().filter(pair -> pair.remote.isTransient()).map(pair -> pair.local).collect(RangesAtEndpoint.collector(localAddress));
logger.debug("Will request range {} of keyspace {} from endpoint {}", rangesToFetch.get(address), keyspace, address);
streamPlan.requestRanges(address, keyspace, full, trans);
});
logger.debug("Keyspace {}: work map {}.", keyspace, rangesToFetch);
}
}
}
use of org.apache.cassandra.locator.RangesAtEndpoint in project cassandra by apache.
the class RangeStreamer method fetchAsync.
public StreamResultFuture fetchAsync() {
toFetch.forEach((keyspace, sources) -> {
logger.debug("Keyspace {} Sources {}", keyspace, sources);
sources.asMap().forEach((source, fetchReplicas) -> {
// filter out already streamed ranges
SystemKeyspace.AvailableRanges available = stateStore.getAvailableRanges(keyspace, metadata.partitioner);
Predicate<FetchReplica> isAvailable = fetch -> {
boolean isInFull = available.full.contains(fetch.local.range());
boolean isInTrans = available.trans.contains(fetch.local.range());
if (!isInFull && !isInTrans)
// Range is unavailable
return false;
if (fetch.local.isFull())
// For full, pick only replicas with matching transientness
return isInFull == fetch.remote.isFull();
// Any transient or full will do
return true;
};
List<FetchReplica> remaining = fetchReplicas.stream().filter(not(isAvailable)).collect(Collectors.toList());
if (remaining.size() < available.full.size() + available.trans.size()) {
List<FetchReplica> skipped = fetchReplicas.stream().filter(isAvailable).collect(Collectors.toList());
logger.info("Some ranges of {} are already available. Skipping streaming those ranges. Skipping {}. Fully available {} Transiently available {}", fetchReplicas, skipped, available.full, available.trans);
}
if (logger.isTraceEnabled())
logger.trace("{}ing from {} ranges {}", description, source, StringUtils.join(remaining, ", "));
InetAddressAndPort self = FBUtilities.getBroadcastAddressAndPort();
RangesAtEndpoint full = remaining.stream().filter(pair -> pair.remote.isFull()).map(pair -> pair.local).collect(RangesAtEndpoint.collector(self));
RangesAtEndpoint transientReplicas = remaining.stream().filter(pair -> pair.remote.isTransient()).map(pair -> pair.local).collect(RangesAtEndpoint.collector(self));
logger.debug("Source and our replicas {}", fetchReplicas);
logger.debug("Source {} Keyspace {} streaming full {} transient {}", source, keyspace, full, transientReplicas);
/* Send messages to respective folks to stream data over to me */
streamPlan.requestRanges(source, keyspace, full, transientReplicas);
});
});
return streamPlan.execute();
}
Aggregations