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