in src/java/org/apache/cassandra/db/context/CounterContext.java [454:532]
private Relationship compare(ContextState leftState, ContextState rightState)
{
long leftClock = leftState.getClock();
long leftCount = leftState.getCount();
long rightClock = rightState.getClock();
long rightCount = rightState.getCount();
if (leftState.isGlobal() || rightState.isGlobal())
{
if (leftState.isGlobal() && rightState.isGlobal())
{
if (leftClock == rightClock)
{
// Can happen if an sstable gets lost and disk failure policy is set to 'best effort'
if (leftCount != rightCount && CompactionManager.isCompactor(Thread.currentThread()))
{
logger.warn("invalid global counter shard detected; ({}, {}, {}) and ({}, {}, {}) differ only in "
+ "count; will pick highest to self-heal on compaction",
leftState.getCounterId(), leftClock, leftCount,
rightState.getCounterId(), rightClock, rightCount);
}
if (leftCount > rightCount)
return Relationship.GREATER_THAN;
else if (leftCount == rightCount)
return Relationship.EQUAL;
else
return Relationship.LESS_THAN;
}
else
{
return leftClock > rightClock ? Relationship.GREATER_THAN : Relationship.LESS_THAN;
}
}
else // only one is global - keep that one
{
return leftState.isGlobal() ? Relationship.GREATER_THAN : Relationship.LESS_THAN;
}
}
if (leftState.isLocal() || rightState.isLocal())
{
// Local id and at least one is a local shard.
if (leftState.isLocal() && rightState.isLocal())
return Relationship.DISJOINT;
else // only one is local - keep that one
return leftState.isLocal() ? Relationship.GREATER_THAN : Relationship.LESS_THAN;
}
// both are remote shards
if (leftClock == rightClock)
{
// We should never see non-local shards w/ same id+clock but different counts. However, if we do
// we should "heal" the problem by being deterministic in our selection of shard - and
// log the occurrence so that the operator will know something is wrong.
if (leftCount != rightCount && CompactionManager.isCompactor(Thread.currentThread()))
{
logger.warn("invalid remote counter shard detected; ({}, {}, {}) and ({}, {}, {}) differ only in "
+ "count; will pick highest to self-heal on compaction",
leftState.getCounterId(), leftClock, leftCount,
rightState.getCounterId(), rightClock, rightCount);
}
if (leftCount > rightCount)
return Relationship.GREATER_THAN;
else if (leftCount == rightCount)
return Relationship.EQUAL;
else
return Relationship.LESS_THAN;
}
else
{
if ((leftClock >= 0 && rightClock > 0 && leftClock >= rightClock)
|| (leftClock < 0 && (rightClock > 0 || leftClock < rightClock)))
return Relationship.GREATER_THAN;
else
return Relationship.LESS_THAN;
}
}