use of org.apache.cassandra.dht.Token in project cassandra by apache.
the class ViewBuilder method run.
public void run() {
logger.trace("Running view builder for {}.{}", baseCfs.metadata.keyspace, view.name);
UUID localHostId = SystemKeyspace.getLocalHostId();
String ksname = baseCfs.metadata.keyspace, viewName = view.name;
if (SystemKeyspace.isViewBuilt(ksname, viewName)) {
if (!SystemKeyspace.isViewStatusReplicated(ksname, viewName))
updateDistributed(ksname, viewName, localHostId);
return;
}
Iterable<Range<Token>> ranges = StorageService.instance.getLocalRanges(baseCfs.metadata.keyspace);
final Pair<Integer, Token> buildStatus = SystemKeyspace.getViewBuildStatus(ksname, viewName);
Token lastToken;
Function<org.apache.cassandra.db.lifecycle.View, Iterable<SSTableReader>> function;
if (buildStatus == null) {
baseCfs.forceBlockingFlush();
function = org.apache.cassandra.db.lifecycle.View.selectFunction(SSTableSet.CANONICAL);
int generation = Integer.MIN_VALUE;
try (Refs<SSTableReader> temp = baseCfs.selectAndReference(function).refs) {
for (SSTableReader reader : temp) {
generation = Math.max(reader.descriptor.generation, generation);
}
}
SystemKeyspace.beginViewBuild(ksname, viewName, generation);
lastToken = null;
} else {
function = new Function<org.apache.cassandra.db.lifecycle.View, Iterable<SSTableReader>>() {
@Nullable
public Iterable<SSTableReader> apply(org.apache.cassandra.db.lifecycle.View view) {
Iterable<SSTableReader> readers = org.apache.cassandra.db.lifecycle.View.selectFunction(SSTableSet.CANONICAL).apply(view);
if (readers != null)
return Iterables.filter(readers, ssTableReader -> ssTableReader.descriptor.generation <= buildStatus.left);
return null;
}
};
lastToken = buildStatus.right;
}
prevToken = lastToken;
try (Refs<SSTableReader> sstables = baseCfs.selectAndReference(function).refs;
ReducingKeyIterator iter = new ReducingKeyIterator(sstables)) {
SystemDistributedKeyspace.startViewBuild(ksname, viewName, localHostId);
while (!isStopped && iter.hasNext()) {
DecoratedKey key = iter.next();
Token token = key.getToken();
if (lastToken == null || lastToken.compareTo(token) < 0) {
for (Range<Token> range : ranges) {
if (range.contains(token)) {
buildKey(key);
if (prevToken == null || prevToken.compareTo(token) != 0) {
SystemKeyspace.updateViewBuildStatus(ksname, viewName, key.getToken());
prevToken = token;
}
}
}
lastToken = null;
}
}
if (!isStopped) {
SystemKeyspace.finishViewBuildStatus(ksname, viewName);
updateDistributed(ksname, viewName, localHostId);
}
} catch (Exception e) {
ScheduledExecutors.nonPeriodicTasks.schedule(() -> CompactionManager.instance.submitViewBuilder(this), 5, TimeUnit.MINUTES);
logger.warn("Materialized View failed to complete, sleeping 5 minutes before restarting", e);
}
}
use of org.apache.cassandra.dht.Token in project cassandra by apache.
the class Gossiper method assassinateEndpoint.
/**
* Do not call this method unless you know what you are doing.
* It will try extremely hard to obliterate any endpoint from the ring,
* even if it does not know about it.
*
* @param address
* @throws UnknownHostException
*/
public void assassinateEndpoint(String address) throws UnknownHostException {
InetAddress endpoint = InetAddress.getByName(address);
EndpointState epState = endpointStateMap.get(endpoint);
Collection<Token> tokens = null;
logger.warn("Assassinating {} via gossip", endpoint);
if (epState == null) {
epState = new EndpointState(new HeartBeatState((int) ((System.currentTimeMillis() + 60000) / 1000), 9999));
} else {
int generation = epState.getHeartBeatState().getGeneration();
int heartbeat = epState.getHeartBeatState().getHeartBeatVersion();
logger.info("Sleeping for {}ms to ensure {} does not change", StorageService.RING_DELAY, endpoint);
Uninterruptibles.sleepUninterruptibly(StorageService.RING_DELAY, TimeUnit.MILLISECONDS);
// make sure it did not change
EndpointState newState = endpointStateMap.get(endpoint);
if (newState == null)
logger.warn("Endpoint {} disappeared while trying to assassinate, continuing anyway", endpoint);
else if (newState.getHeartBeatState().getGeneration() != generation)
throw new RuntimeException("Endpoint still alive: " + endpoint + " generation changed while trying to assassinate it");
else if (newState.getHeartBeatState().getHeartBeatVersion() != heartbeat)
throw new RuntimeException("Endpoint still alive: " + endpoint + " heartbeat changed while trying to assassinate it");
// make sure we don't evict it too soon
epState.updateTimestamp();
epState.getHeartBeatState().forceNewerGenerationUnsafe();
}
try {
tokens = StorageService.instance.getTokenMetadata().getTokens(endpoint);
} catch (Throwable th) {
JVMStabilityInspector.inspectThrowable(th);
// TODO this is broken
logger.warn("Unable to calculate tokens for {}. Will use a random one", address);
tokens = Collections.singletonList(StorageService.instance.getTokenMetadata().partitioner.getRandomToken());
}
// do not pass go, do not collect 200 dollars, just gtfo
epState.addApplicationState(ApplicationState.STATUS, StorageService.instance.valueFactory.left(tokens, computeExpireTime()));
handleMajorStateChange(endpoint, epState);
Uninterruptibles.sleepUninterruptibly(intervalInMillis * 4, TimeUnit.MILLISECONDS);
logger.warn("Finished assassinating {}", endpoint);
}
use of org.apache.cassandra.dht.Token in project cassandra by apache.
the class ReplicationAwareTokenAllocator method evaluateImprovement.
/**
* Evaluates the improvement in variance for both units and individual tokens when candidate is inserted into the
* ring.
*/
private double evaluateImprovement(CandidateInfo<Unit> candidate, double optTokenOwnership, double newUnitMult) {
double tokenChange = 0;
UnitInfo<Unit> candidateUnit = candidate.owningUnit;
Token candidateEnd = candidate.token;
// Form a chain of units affected by the insertion to be able to qualify change of unit ownership.
// A unit may be affected more than once.
UnitAdjustmentTracker<Unit> unitTracker = new UnitAdjustmentTracker<>(candidateUnit);
// Reflect change in ownership of the splitting token (candidate).
tokenChange += applyOwnershipAdjustment(candidate, candidateUnit, candidate.replicationStart, candidateEnd, optTokenOwnership, unitTracker);
// Loop through all vnodes that replicate candidate or split and update their ownership.
ReplicationVisitor replicationVisitor = new ReplicationVisitor();
for (TokenInfo<Unit> curr = candidate.split; !replicationVisitor.visitedAll(); curr = curr.next) {
UnitInfo<Unit> currUnit = curr.owningUnit;
if (!replicationVisitor.add(currUnit.group))
// If this group is already seen, the token cannot be affected.
continue;
Token replicationEnd = curr.token;
Token replicationStart = findUpdatedReplicationStart(curr, candidate);
tokenChange += applyOwnershipAdjustment(curr, currUnit, replicationStart, replicationEnd, optTokenOwnership, unitTracker);
}
replicationVisitor.clean();
double nodeChange = unitTracker.calculateUnitChange(newUnitMult, optTokenOwnership);
return -(tokenChange + nodeChange);
}
use of org.apache.cassandra.dht.Token in project cassandra by apache.
the class ReplicationAwareTokenAllocator method confirmCandidate.
/**
* Incorporates the selected candidate into the ring, adjusting ownership information and calculated token
* information.
*/
private void confirmCandidate(CandidateInfo<Unit> candidate) {
// This process is less efficient than it could be (loops through each vnode's replication span instead
// of recalculating replicationStart, replicationThreshold from existing data + new token data in an O(1)
// case analysis similar to evaluateImprovement). This is fine as the method does not dominate processing
// time.
// Put the accepted candidate in the token list.
UnitInfo<Unit> newUnit = candidate.owningUnit;
Token newToken = candidate.token;
sortedTokens.put(newToken, newUnit.unit);
unitToTokens.put(newUnit.unit, newToken);
TokenInfo<Unit> prev = candidate.prevInRing();
TokenInfo<Unit> newTokenInfo = new TokenInfo<>(newToken, newUnit);
newTokenInfo.replicatedOwnership = candidate.replicatedOwnership;
// List is not empty so this won't need to change head of list.
newTokenInfo.insertAfter(prev, prev);
// Update data for candidate.
populateTokenInfoAndAdjustUnit(newTokenInfo, newUnit.group);
ReplicationVisitor replicationVisitor = new ReplicationVisitor();
assert newTokenInfo.next == candidate.split;
for (TokenInfo<Unit> curr = newTokenInfo.next; !replicationVisitor.visitedAll(); curr = curr.next) {
// update the candidate between curr and next
candidate = candidate.next;
populateCandidate(candidate);
if (!replicationVisitor.add(curr.owningUnit.group))
// If we've already seen this group, the token cannot be affected.
continue;
populateTokenInfoAndAdjustUnit(curr, newUnit.group);
}
replicationVisitor.clean();
}
use of org.apache.cassandra.dht.Token in project cassandra by apache.
the class TokenAllocation method evaluateReplicatedOwnership.
// return the ratio of ownership for each endpoint
public static Map<InetAddress, Double> evaluateReplicatedOwnership(TokenMetadata tokenMetadata, AbstractReplicationStrategy rs) {
Map<InetAddress, Double> ownership = Maps.newHashMap();
List<Token> sortedTokens = tokenMetadata.sortedTokens();
Iterator<Token> it = sortedTokens.iterator();
Token current = it.next();
while (it.hasNext()) {
Token next = it.next();
addOwnership(tokenMetadata, rs, current, next, ownership);
current = next;
}
addOwnership(tokenMetadata, rs, current, sortedTokens.get(0), ownership);
return ownership;
}
Aggregations