diff --git a/exist-core/src/main/java/org/exist/storage/btree/Paged.java b/exist-core/src/main/java/org/exist/storage/btree/Paged.java index 60938a9f1b2..048371e5604 100644 --- a/exist-core/src/main/java/org/exist/storage/btree/Paged.java +++ b/exist-core/src/main/java/org/exist/storage/btree/Paged.java @@ -91,6 +91,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; +import java.util.function.Supplier; /** * Paged is a paged file foundation that is used by the BTree class and @@ -290,7 +291,7 @@ protected final Page getFreePage(final boolean reuseDeleted) throws IOException long pageNum = fileHeader.firstFreePage; if (reuseDeleted && pageNum != Page.NO_PAGE) { // Steal a deleted page - page = new Page(pageNum); + page = new Page(file, raf, fileHeader, this::createPageHeader, pageNum, tempPageData, tempHeaderData); page.read(); fileHeader.firstFreePage = page.header.nextPage; if (fileHeader.firstFreePage == Page.NO_PAGE) { @@ -303,7 +304,7 @@ protected final Page getFreePage(final boolean reuseDeleted) throws IOException throw new IOException("page limit reached: " + pageNum); } fileHeader.setTotalCount(pageNum + 1); - page = new Page(pageNum); + page = new Page(file, raf, fileHeader, this::createPageHeader, pageNum, tempPageData, tempHeaderData); page.read(); } } @@ -324,8 +325,8 @@ protected final Page getFreePage(final boolean reuseDeleted) throws IOException * @return The requested Page * @throws IOException if an exception occurs */ - protected final Page getPage(final long pageNum) throws IOException { - return new Page(pageNum); + protected static final Page getPage(final long pageNum) throws IOException { + return new Page(file, raf, fileHeader, this::createPageHeader, pageNum, tempPageData, tempHeaderData); } /** @@ -858,13 +859,21 @@ public final synchronized void write() throws IOException { /** * Page */ - public final class Page implements Comparable { + public static final class Page implements Comparable { public static final long NO_PAGE = -1; + private final Path file; + private final RandomAccessFile raf; + + private final FileHeader fileHeader; + /** The Header for this Page */ private final PageHeader header; + private final byte[] tempPageData; + private final byte[] tempHeaderData; + /** The offset into the file that this page starts */ private long offset; /** This page number */ @@ -872,19 +881,30 @@ public final class Page implements Comparable { private int refCount = 0; - public Page() { - this.header = createPageHeader(); + public Page(final Path file, final RandomAccessFile raf, final FileHeader fileHeader, final Supplier pageHeaderSupplier, final byte[] tempPageData, final byte[] tempHeaderData) { + this.file = file; + this.raf = raf; + this.fileHeader = fileHeader; + this.header = pageHeaderSupplier.get(); + this.tempPageData = tempPageData; + this.tempHeaderData = tempHeaderData; } /** * Constructor for the Page object * + * @param file the file. + * @param raf random access to the file. + * @param fileHeader the file header. + * @param pageHeaderSupplier a function that supplies a page header. * @param pageNum Description of the Parameter + * @param tempPageData an array of temporary storage for page data. + * @param tempHeaderData an array of temporary storage for header data. * * @throws IOException Description of the Exception */ - public Page(final long pageNum) throws IOException { - this(); + public Page(final Path file, final RandomAccessFile raf, final FileHeader fileHeader, final Supplier pageHeaderSupplier, final long pageNum, final byte[] tempPageData, final byte[] tempHeaderData) throws IOException { + this(file, raf, fileHeader, pageHeaderSupplier, tempPageData, tempHeaderData); if(pageNum == Page.NO_PAGE) { throw new IOException("Illegal page num: " + pageNum); } @@ -920,7 +940,7 @@ public PageHeader getPageHeader() { */ public String getPageInfo() { return "page: " + pageNum + - "; file = " + FileUtils.fileName(getFile()) + + "; file = " + FileUtils.fileName(file) + "; address = " + Long.toHexString(offset) + "; page header = " + fileHeader.getPageHeaderSize() + "; data start = " + Long.toHexString(offset + fileHeader.getPageHeaderSize()); diff --git a/exist-core/src/main/java/org/exist/storage/dom/DOMFile.java b/exist-core/src/main/java/org/exist/storage/dom/DOMFile.java index 7577d051a41..3f09f39eab8 100644 --- a/exist-core/src/main/java/org/exist/storage/dom/DOMFile.java +++ b/exist-core/src/main/java/org/exist/storage/dom/DOMFile.java @@ -3034,7 +3034,7 @@ void setRecordCount(final short recs) { } } - protected final class DOMPage implements Cacheable { + protected static final class DOMPage implements Cacheable { // the raw working data (without page header) of this page byte[] data; @@ -3042,6 +3042,8 @@ protected final class DOMPage implements Cacheable { // the current size of the used data int len = 0; + private final FileHeader fileHeader; + // the low-level page Page page; @@ -3058,17 +3060,19 @@ protected final class DOMPage implements Cacheable { // set to true if the page has been removed from the cache boolean invalidated = false; - AtomicInteger lastFound = new AtomicInteger(0); + private static final ThreadLocal LAST_FOUND = ThreadLocal.withInitial(() -> 0); - DOMPage() { + DOMPage(final FileHeader fileHeader) { + this.fileHeader = fileHeader; this.page = createNewPage(); this.pageHeader = (DOMFilePageHeader) page.getPageHeader(); this.data = new byte[fileHeader.getWorkSize()]; this.len = 0; } - DOMPage(final long pos) { + DOMPage(final FileHeader fileHeader, final long pos) { try { + this.fileHeader = fileHeader; this.page = getPage(pos); load(page); } catch (final IOException ioe) { @@ -3078,7 +3082,8 @@ protected final class DOMPage implements Cacheable { } } - DOMPage(final Page page) { + DOMPage(final FileHeader fileHeader, final Page page) { + this.fileHeader = fileHeader; this.page = page; load(page); }