public long replace()

in modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/replacement/RandomLruPageReplacementPolicy.java [58:181]


    public long replace() throws IgniteInternalCheckedException {
        ThreadLocalRandom rnd = ThreadLocalRandom.current();

        LoadedPagesMap loadedPages = seg.loadedPages();
        PagePool pool = seg.pool();

        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();

                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);

                boolean dirty = PageHeader.dirty(absPageAddr);

                CheckpointPages checkpointPages = seg.checkpointPages();

                if (relRmvAddr == rndAddr || pinned || skip || (dirty && (checkpointPages == null || !checkpointPages.contains(fullId)))) {
                    i--;

                    continue;
                }

                long pageTs = PageHeader.readTimestamp(absPageAddr);

                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);
            }

            long absRmvAddr = seg.absolute(relRmvAddr);

            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;
        }
    }