Search in sources :

Example 11 with PagesListSetNextRecord

use of org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord in project ignite by apache.

the class PagesList method putReuseBag.

/**
     * @param pageId Page ID.
     * @param page Page pointer.
     * @param pageAddr Page address.
     * @param io IO.
     * @param bag Reuse bag.
     * @param bucket Bucket.
     * @return {@code true} If succeeded.
     * @throws IgniteCheckedException if failed.
     */
@SuppressWarnings("ForLoopReplaceableByForEach")
private boolean putReuseBag(final long pageId, final long page, final long pageAddr, PagesListNodeIO io, ReuseBag bag, int bucket) throws IgniteCheckedException {
    if (io.getNextId(pageAddr) != 0L)
        // Splitted.
        return false;
    long nextId;
    long prevId = pageId;
    long prevPage = page;
    long prevAddr = pageAddr;
    Boolean walPlc = null;
    // TODO may be unlock right away and do not keep all these pages locked?
    GridLongList locked = null;
    try {
        while ((nextId = bag.pollFreePage()) != 0L) {
            int idx = io.addPage(prevAddr, nextId, pageSize());
            if (idx == -1) {
                // Attempt to add page failed: the node page is full.
                final long nextPage = acquirePage(nextId);
                try {
                    // Page from reuse bag can't be concurrently recycled.
                    long nextPageAddr = writeLock(nextId, nextPage);
                    assert nextPageAddr != 0L;
                    if (locked == null) {
                        locked = new GridLongList(6);
                    }
                    locked.add(nextId);
                    locked.add(nextPage);
                    locked.add(nextPageAddr);
                    setupNextPage(io, prevId, prevAddr, nextId, nextPageAddr);
                    if (needWalDeltaRecord(prevId, prevPage, walPlc))
                        wal.log(new PagesListSetNextRecord(cacheId, prevId, nextId));
                    // Here we should never write full page, because it is known to be new.
                    if (needWalDeltaRecord(nextId, nextPage, FALSE))
                        wal.log(new PagesListInitNewPageRecord(cacheId, nextId, io.getType(), io.getVersion(), nextId, prevId, 0L));
                    // In reuse bucket the page itself can be used as a free page.
                    if (isReuseBucket(bucket))
                        bucketsSize[bucket].incrementAndGet();
                    // Switch to this new page, which is now a part of our list
                    // to add the rest of the bag to the new page.
                    prevAddr = nextPageAddr;
                    prevId = nextId;
                    prevPage = nextPage;
                    // Starting from tis point all wal records are written for reused pages from the bag.
                    // This mean that we use delta records only.
                    walPlc = FALSE;
                } finally {
                    releasePage(nextId, nextPage);
                }
            } else {
                // TODO: use single WAL record for bag?
                if (needWalDeltaRecord(prevId, prevPage, walPlc))
                    wal.log(new PagesListAddPageRecord(cacheId, prevId, nextId));
                bucketsSize[bucket].incrementAndGet();
            }
        }
    } finally {
        if (locked != null) {
            // We have to update our bucket with the new tail.
            updateTail(bucket, pageId, prevId);
            // Release write.
            for (int i = 0; i < locked.size(); i += 3) {
                writeUnlock(locked.get(i), locked.get(i + 1), locked.get(i + 2), FALSE, true);
            }
        }
    }
    return true;
}
Also used : PagesListAddPageRecord(org.apache.ignite.internal.pagemem.wal.record.delta.PagesListAddPageRecord) GridLongList(org.apache.ignite.internal.util.GridLongList) PagesListSetNextRecord(org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord) PagesListInitNewPageRecord(org.apache.ignite.internal.pagemem.wal.record.delta.PagesListInitNewPageRecord)

Example 12 with PagesListSetNextRecord

use of org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord in project ignite by apache.

the class PagesList method fairMerge.

/**
 * Link previous and next to each other.
 * @param prevId Previous Previous page ID.
 * @param pageId Page ID.
 * @param nextId Next page ID.
 * @param nextPage Next page absolute pointer.
 * @param nextAddr Next page address.
 * @throws IgniteCheckedException If failed.
 */
private void fairMerge(final long prevId, long pageId, long nextId, long nextPage, long nextAddr) throws IgniteCheckedException {
    long prevPage = acquirePage(prevId);
    try {
        // No check, we keep a reference.
        final long prevAddr = writeLock(prevId, prevPage);
        assert prevAddr != 0L;
        try {
            PagesListNodeIO prevIO = PagesListNodeIO.VERSIONS.forPage(prevAddr);
            PagesListNodeIO nextIO = PagesListNodeIO.VERSIONS.forPage(nextAddr);
            // These references must be updated at the same time in write locks.
            assert prevIO.getNextId(prevAddr) == pageId;
            assert nextIO.getPreviousId(nextAddr) == pageId;
            prevIO.setNextId(prevAddr, nextId);
            if (needWalDeltaRecord(prevId, prevPage, null))
                wal.log(new PagesListSetNextRecord(grpId, prevId, nextId));
            nextIO.setPreviousId(nextAddr, prevId);
            if (needWalDeltaRecord(nextId, nextPage, null))
                wal.log(new PagesListSetPreviousRecord(grpId, nextId, prevId));
        } finally {
            writeUnlock(prevId, prevPage, prevAddr, true);
        }
    } finally {
        releasePage(prevId, prevPage);
    }
}
Also used : PagesListSetPreviousRecord(org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetPreviousRecord) PagesListNodeIO(org.apache.ignite.internal.processors.cache.persistence.freelist.io.PagesListNodeIO) PagesListSetNextRecord(org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord)

Example 13 with PagesListSetNextRecord

use of org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord in project ignite by apache.

the class PagesList method handlePageFull.

/**
 * @param pageId Page ID.
 * @param page Page pointer.
 * @param pageAddr Page address.
 * @param io IO.
 * @param dataId Data page ID.
 * @param data Data page pointer.
 * @param dataAddr Data page address.
 * @param bucket Bucket index.
 * @throws IgniteCheckedException If failed.
 */
private void handlePageFull(final long pageId, final long page, final long pageAddr, PagesListNodeIO io, final long dataId, final long data, final long dataAddr, int bucket) throws IgniteCheckedException {
    AbstractDataPageIO dataIO = PageIO.getPageIO(dataAddr);
    // Attempt to add page failed: the node page is full.
    if (isReuseBucket(bucket)) {
        // We can put only empty data pages to reuse bucket.
        assert dataIO.isEmpty(dataAddr);
        // Change page type to index and add it as next node page to this list.
        long newDataId = PageIdUtils.changeType(dataId, FLAG_IDX);
        setupNextPage(io, pageId, pageAddr, newDataId, dataAddr);
        if (needWalDeltaRecord(pageId, page, null))
            wal.log(new PagesListSetNextRecord(grpId, pageId, newDataId));
        if (needWalDeltaRecord(dataId, data, null))
            wal.log(new PagesListInitNewPageRecord(grpId, dataId, io.getType(), io.getVersion(), newDataId, pageId, 0L));
        // In reuse bucket the page itself can be used as a free page.
        incrementBucketSize(bucket);
        updateTail(bucket, pageId, newDataId);
    } else {
        // Just allocate a new node page and add our data page there.
        final long nextId = allocatePage(null);
        final long nextPage = acquirePage(nextId);
        try {
            // Newly allocated page.
            long nextPageAddr = writeLock(nextId, nextPage);
            assert nextPageAddr != 0L;
            // Here we should never write full page, because it is known to be new.
            Boolean nextWalPlc = FALSE;
            try {
                setupNextPage(io, pageId, pageAddr, nextId, nextPageAddr);
                if (needWalDeltaRecord(pageId, page, null))
                    wal.log(new PagesListSetNextRecord(grpId, pageId, nextId));
                int idx = io.addPage(nextPageAddr, dataId, pageSize());
                if (needWalDeltaRecord(nextId, nextPage, nextWalPlc))
                    wal.log(new PagesListInitNewPageRecord(grpId, nextId, io.getType(), io.getVersion(), nextId, pageId, dataId));
                assert idx != -1;
                dataIO.setFreeListPageId(dataAddr, nextId);
                if (needWalDeltaRecord(dataId, data, null))
                    wal.log(new DataPageSetFreeListPageRecord(grpId, dataId, nextId));
                incrementBucketSize(bucket);
                updateTail(bucket, pageId, nextId);
            } finally {
                writeUnlock(nextId, nextPage, nextPageAddr, nextWalPlc, true);
            }
        } finally {
            releasePage(nextId, nextPage);
        }
    }
}
Also used : AbstractDataPageIO(org.apache.ignite.internal.processors.cache.persistence.tree.io.AbstractDataPageIO) DataPageSetFreeListPageRecord(org.apache.ignite.internal.pagemem.wal.record.delta.DataPageSetFreeListPageRecord) PagesListSetNextRecord(org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord) PagesListInitNewPageRecord(org.apache.ignite.internal.pagemem.wal.record.delta.PagesListInitNewPageRecord)

Example 14 with PagesListSetNextRecord

use of org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord in project ignite by apache.

the class PagesList method handlePageFull.

/**
 * @param pageId Page ID.
 * @param page Page pointer.
 * @param pageAddr Page address.
 * @param io IO.
 * @param dataId Data page ID.
 * @param data Data page pointer.
 * @param dataAddr Data page address.
 * @param bucket Bucket index.
 * @param statHolder Statistics holder to track IO operations.
 * @throws IgniteCheckedException If failed.
 */
private void handlePageFull(final long pageId, final long page, final long pageAddr, PagesListNodeIO io, final long dataId, final long data, final long dataAddr, int bucket, IoStatisticsHolder statHolder) throws IgniteCheckedException {
    AbstractDataPageIO dataIO = PageIO.getPageIO(dataAddr);
    // Attempt to add page failed: the node page is full.
    if (isReuseBucket(bucket)) {
        // We can put only empty data pages to reuse bucket.
        assert dataIO.isEmpty(dataAddr);
        // Change page type to index and add it as next node page to this list.
        long newDataId = PageIdUtils.changeType(dataId, FLAG_IDX);
        setupNextPage(io, pageId, pageAddr, newDataId, dataAddr);
        if (needWalDeltaRecord(pageId, page, null))
            wal.log(new PagesListSetNextRecord(grpId, pageId, newDataId));
        if (needWalDeltaRecord(dataId, data, null))
            wal.log(new PagesListInitNewPageRecord(grpId, dataId, io.getType(), io.getVersion(), newDataId, pageId, 0L));
        // In reuse bucket the page itself can be used as a free page.
        incrementBucketSize(bucket);
        updateTail(bucket, pageId, newDataId);
    } else {
        // Just allocate a new node page and add our data page there.
        final long nextId = allocatePage(null);
        final long nextPage = acquirePage(nextId, statHolder);
        try {
            // Newly allocated page.
            long nextPageAddr = writeLock(nextId, nextPage);
            assert nextPageAddr != 0L;
            // Here we should never write full page, because it is known to be new.
            Boolean nextWalPlc = FALSE;
            try {
                setupNextPage(io, pageId, pageAddr, nextId, nextPageAddr);
                if (needWalDeltaRecord(pageId, page, null))
                    wal.log(new PagesListSetNextRecord(grpId, pageId, nextId));
                int idx = io.addPage(nextPageAddr, dataId, pageSize());
                if (needWalDeltaRecord(nextId, nextPage, nextWalPlc))
                    wal.log(new PagesListInitNewPageRecord(grpId, nextId, io.getType(), io.getVersion(), nextId, pageId, dataId));
                assert idx != -1;
                dataIO.setFreeListPageId(dataAddr, nextId);
                if (needWalDeltaRecord(dataId, data, null))
                    wal.log(new DataPageSetFreeListPageRecord(grpId, dataId, nextId));
                incrementBucketSize(bucket);
                updateTail(bucket, pageId, nextId);
            } finally {
                writeUnlock(nextId, nextPage, nextPageAddr, nextWalPlc, true);
            }
        } finally {
            releasePage(nextId, nextPage);
        }
    }
}
Also used : AbstractDataPageIO(org.apache.ignite.internal.processors.cache.persistence.tree.io.AbstractDataPageIO) DataPageSetFreeListPageRecord(org.apache.ignite.internal.pagemem.wal.record.delta.DataPageSetFreeListPageRecord) PagesListSetNextRecord(org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord) PagesListInitNewPageRecord(org.apache.ignite.internal.pagemem.wal.record.delta.PagesListInitNewPageRecord)

Example 15 with PagesListSetNextRecord

use of org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord in project ignite by apache.

the class PagesList method putReuseBag.

/**
 * @param pageId Page ID.
 * @param page Page pointer.
 * @param pageAddr Page address.
 * @param io IO.
 * @param bag Reuse bag.
 * @param bucket Bucket.
 * @param statHolder Statistics holder to track IO operations.
 * @return {@code true} If succeeded.
 * @throws IgniteCheckedException if failed.
 */
private boolean putReuseBag(final long pageId, final long page, final long pageAddr, PagesListNodeIO io, ReuseBag bag, int bucket, IoStatisticsHolder statHolder) throws IgniteCheckedException {
    assert bag != null : "bag is null";
    assert !bag.isEmpty() : "bag is empty";
    if (io.getNextId(pageAddr) != 0L)
        // Splitted.
        return false;
    long nextId;
    long prevId = pageId;
    long prevPage = page;
    long prevAddr = pageAddr;
    Boolean walPlc = null;
    // TODO may be unlock right away and do not keep all these pages locked?
    GridLongList locked = null;
    try {
        while ((nextId = bag.pollFreePage()) != 0L) {
            assert PageIdUtils.itemId(nextId) > 0 && PageIdUtils.itemId(nextId) <= MAX_ITEMID_NUM : U.hexLong(nextId);
            int idx = io.addPage(prevAddr, nextId, pageSize());
            if (idx == -1) {
                // Attempt to add page failed: the node page is full.
                final long nextPage = acquirePage(nextId, statHolder);
                try {
                    // Page from reuse bag can't be concurrently recycled.
                    long nextPageAddr = writeLock(nextId, nextPage);
                    assert nextPageAddr != 0L;
                    if (locked == null)
                        locked = new GridLongList(6);
                    locked.add(nextId);
                    locked.add(nextPage);
                    locked.add(nextPageAddr);
                    setupNextPage(io, prevId, prevAddr, nextId, nextPageAddr);
                    if (needWalDeltaRecord(prevId, prevPage, walPlc))
                        wal.log(new PagesListSetNextRecord(grpId, prevId, nextId));
                    // Here we should never write full page, because it is known to be new.
                    if (needWalDeltaRecord(nextId, nextPage, FALSE))
                        wal.log(new PagesListInitNewPageRecord(grpId, nextId, io.getType(), io.getVersion(), nextId, prevId, 0L));
                    // In reuse bucket the page itself can be used as a free page.
                    if (isReuseBucket(bucket))
                        incrementBucketSize(bucket);
                    // Switch to this new page, which is now a part of our list
                    // to add the rest of the bag to the new page.
                    prevAddr = nextPageAddr;
                    prevId = nextId;
                    prevPage = nextPage;
                    // Starting from tis point all wal records are written for reused pages from the bag.
                    // This mean that we use delta records only.
                    walPlc = FALSE;
                } finally {
                    releasePage(nextId, nextPage);
                }
            } else {
                // TODO: use single WAL record for bag?
                if (needWalDeltaRecord(prevId, prevPage, walPlc))
                    wal.log(new PagesListAddPageRecord(grpId, prevId, nextId));
                incrementBucketSize(bucket);
            }
        }
    } finally {
        if (locked != null) {
            // We have to update our bucket with the new tail.
            updateTail(bucket, pageId, prevId);
            // Release write.
            for (int i = 0; i < locked.size(); i += 3) writeUnlock(locked.get(i), locked.get(i + 1), locked.get(i + 2), FALSE, true);
        }
    }
    return true;
}
Also used : PagesListAddPageRecord(org.apache.ignite.internal.pagemem.wal.record.delta.PagesListAddPageRecord) GridLongList(org.apache.ignite.internal.util.GridLongList) PagesListSetNextRecord(org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord) PagesListInitNewPageRecord(org.apache.ignite.internal.pagemem.wal.record.delta.PagesListInitNewPageRecord)

Aggregations

PagesListSetNextRecord (org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetNextRecord)17 PagesListInitNewPageRecord (org.apache.ignite.internal.pagemem.wal.record.delta.PagesListInitNewPageRecord)13 DataPageSetFreeListPageRecord (org.apache.ignite.internal.pagemem.wal.record.delta.DataPageSetFreeListPageRecord)9 PagesListAddPageRecord (org.apache.ignite.internal.pagemem.wal.record.delta.PagesListAddPageRecord)9 PagesListSetPreviousRecord (org.apache.ignite.internal.pagemem.wal.record.delta.PagesListSetPreviousRecord)9 UUID (java.util.UUID)5 CheckpointRecord (org.apache.ignite.internal.pagemem.wal.record.CheckpointRecord)5 DataRecord (org.apache.ignite.internal.pagemem.wal.record.DataRecord)5 MemoryRecoveryRecord (org.apache.ignite.internal.pagemem.wal.record.MemoryRecoveryRecord)5 MetastoreDataRecord (org.apache.ignite.internal.pagemem.wal.record.MetastoreDataRecord)5 PageSnapshot (org.apache.ignite.internal.pagemem.wal.record.PageSnapshot)5 DataPageInsertFragmentRecord (org.apache.ignite.internal.pagemem.wal.record.delta.DataPageInsertFragmentRecord)5 DataPageInsertRecord (org.apache.ignite.internal.pagemem.wal.record.delta.DataPageInsertRecord)5 DataPageRemoveRecord (org.apache.ignite.internal.pagemem.wal.record.delta.DataPageRemoveRecord)5 DataPageUpdateRecord (org.apache.ignite.internal.pagemem.wal.record.delta.DataPageUpdateRecord)5 FixCountRecord (org.apache.ignite.internal.pagemem.wal.record.delta.FixCountRecord)5 FixLeftmostChildRecord (org.apache.ignite.internal.pagemem.wal.record.delta.FixLeftmostChildRecord)5 FixRemoveId (org.apache.ignite.internal.pagemem.wal.record.delta.FixRemoveId)5 InitNewPageRecord (org.apache.ignite.internal.pagemem.wal.record.delta.InitNewPageRecord)5 MetaPageAddRootRecord (org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageAddRootRecord)5