in modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/replacement/RandomLruPageReplacementPolicy.java [58:179]
public long replace() throws IgniteInternalCheckedException {
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
LoadedPagesMap loadedPages = seg.loadedPages();
PagePool pool = seg.pool();
final int cap = loadedPages.capacity();
// With big number of random picked pages we may fall into infinite loop, because
// every time the same page may be found.
Set<Long> ignored = null;
long relRmvAddr = INVALID_REL_PTR;
int iterations = 0;
while (true) {
long cleanAddr = INVALID_REL_PTR;
long cleanTs = Long.MAX_VALUE;
long dirtyAddr = INVALID_REL_PTR;
long dirtyTs = Long.MAX_VALUE;
long metaAddr = INVALID_REL_PTR;
long metaTs = Long.MAX_VALUE;
for (int i = 0; i < RANDOM_PAGES_EVICT_NUM; i++) {
++iterations;
if (iterations > pool.pages() * FULL_SCAN_THRESHOLD) {
break;
}
// We need to lookup for pages only in current segment for thread safety,
// so peeking random memory will lead to checking for found page segment.
// It's much faster to check available pages for segment right away.
ReplaceCandidate nearest = loadedPages.getNearestAt(rnd.nextInt(cap));
assert nearest != null && nearest.relativePointer() != INVALID_REL_PTR;
long rndAddr = nearest.relativePointer();
int partGen = nearest.generation();
final long absPageAddr = seg.absolute(rndAddr);
FullPageId fullId = fullPageId(absPageAddr);
// Check page mapping consistency.
assert fullId.equals(nearest.fullId()) : "Invalid page mapping [tableId=" + nearest.fullId()
+ ", actual=" + fullId + ", nearest=" + nearest;
boolean outdated = partGen < seg.partGeneration(fullId.groupId(), partitionId(fullId.pageId()));
if (outdated) {
return seg.refreshOutdatedPage(fullId.groupId(), fullId.pageId(), true);
}
boolean pinned = PageHeader.isAcquired(absPageAddr);
boolean skip = ignored != null && ignored.contains(rndAddr);
final boolean dirty = PageHeader.dirty(absPageAddr);
if (relRmvAddr == rndAddr || pinned || skip || dirty) {
i--;
continue;
}
final long pageTs = PageHeader.readTimestamp(absPageAddr);
final boolean storMeta = isStoreMetadataPage(absPageAddr);
if (pageTs < cleanTs && !dirty && !storMeta) {
cleanAddr = rndAddr;
cleanTs = pageTs;
} else if (pageTs < dirtyTs && dirty && !storMeta) {
dirtyAddr = rndAddr;
dirtyTs = pageTs;
} else if (pageTs < metaTs && storMeta) {
metaAddr = rndAddr;
metaTs = pageTs;
}
if (cleanAddr != INVALID_REL_PTR) {
relRmvAddr = cleanAddr;
} else if (dirtyAddr != INVALID_REL_PTR) {
relRmvAddr = dirtyAddr;
} else {
relRmvAddr = metaAddr;
}
}
if (relRmvAddr == INVALID_REL_PTR) {
return tryToFindSequentially(cap);
}
final long absRmvAddr = seg.absolute(relRmvAddr);
final FullPageId fullPageId = fullPageId(absRmvAddr);
if (!seg.tryToRemovePage(fullPageId, absRmvAddr)) {
if (iterations > 10) {
if (ignored == null) {
ignored = new HashSet<>();
}
ignored.add(relRmvAddr);
}
if (iterations > seg.pool().pages() * FULL_SCAN_THRESHOLD) {
return tryToFindSequentially(cap);
}
continue;
}
return relRmvAddr;
}
}