All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.sirix.access.trx.page.NodePageReadOnlyTrx Maven / Gradle / Ivy

Go to download

SirixDB is a hybrid on-disk and in-memory document oriented, versioned database system. It has a lightweight buffer manager, stores everything in a huge persistent and durable tree and allows efficient reconstruction of every revision. Furthermore, SirixDB implements change tracking, diffing and supports time travel queries.

There is a newer version: 0.11.0
Show newest version
/*
 * Copyright (c) 2011, University of Konstanz, Distributed Systems Group All rights reserved.
 * 

* Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: * Redistributions of source code must retain the * above copyright notice, this list of conditions and the following disclaimer. * Redistributions * in binary form must reproduce the above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other materials provided with the distribution. * * Neither the name of the University of Konstanz nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written permission. *

* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package io.sirix.access.trx.page; import com.google.common.base.MoreObjects; import io.sirix.access.ResourceConfiguration; import io.sirix.access.trx.node.CommitCredentials; import io.sirix.access.trx.node.InternalResourceSession; import io.sirix.api.NodeReadOnlyTrx; import io.sirix.api.NodeTrx; import io.sirix.api.PageReadOnlyTrx; import io.sirix.api.ResourceSession; import io.sirix.cache.*; import io.sirix.exception.SirixIOException; import io.sirix.index.IndexType; import io.sirix.io.BytesUtils; import io.sirix.io.Reader; import io.sirix.node.DeletedNode; import io.sirix.node.NodeKind; import io.sirix.node.interfaces.DataRecord; import io.sirix.page.*; import io.sirix.page.interfaces.KeyValuePage; import io.sirix.page.interfaces.Page; import io.sirix.page.interfaces.PageFragmentKey; import io.sirix.settings.Constants; import io.sirix.settings.Fixed; import io.sirix.settings.VersioningType; import net.openhft.chronicle.bytes.Bytes; import org.checkerframework.checker.index.qual.NonNegative; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; import static java.util.Objects.requireNonNull; /** * Page read-only transaction. The only thing shared amongst transactions is the resource manager. * Everything else is exclusive to this transaction. It is required that only a single thread has * access to this transaction. */ public final class NodePageReadOnlyTrx implements PageReadOnlyTrx { private record RecordPage(int index, IndexType indexType, long recordPageKey, int revision, Page page) { } /** * Page reader exclusively assigned to this transaction. */ private final Reader pageReader; /** * Uber page this transaction is bound to. */ private final UberPage uberPage; /** * {@link InternalResourceSession} reference. */ final InternalResourceSession resourceSession; /** * The revision number, this page trx is bound to. */ private final int revisionNumber; /** * Determines if page reading transaction is closed or not. */ private volatile boolean isClosed; /** * {@link ResourceConfiguration} instance. */ private final ResourceConfiguration resourceConfig; /** * Caches in-memory reconstructed pages of a specific resource. */ private final BufferManager resourceBufferManager; /** * Transaction intent log. */ private final TransactionIntentLog trxIntentLog; /** * The transaction-ID. */ private final long trxId; /** * Cached name page of this revision. */ private final RevisionRootPage rootPage; /** * {@link NamePage} reference. */ private final NamePage namePage; /** * Caches the most recently read record page. */ private RecordPage mostRecentlyReadRecordPage; /** * Caches the second most recently read record page. */ private RecordPage secondMostRecentlyReadRecordPage; private RecordPage pathSummaryRecordPage; private final Bytes byteBufferForRecords = Bytes.elasticByteBuffer(40); /** * Standard constructor. * * @param trxId the transaction-ID. * @param resourceSession the resource manager * @param uberPage {@link UberPage} to start reading from * @param revision key of revision to read from uber page * @param reader to read stored pages for this transaction * @param resourceBufferManager caches in-memory reconstructed pages * @param trxIntentLog the transaction intent log (can be {@code null}) * @throws SirixIOException if reading of the persistent storage fails */ public NodePageReadOnlyTrx(final long trxId, final InternalResourceSession resourceSession, final UberPage uberPage, final @NonNegative int revision, final Reader reader, final BufferManager resourceBufferManager, final @NonNull RevisionRootPageReader revisionRootPageReader, final @Nullable TransactionIntentLog trxIntentLog) { checkArgument(trxId > 0, "Transaction-ID must be >= 0."); this.trxId = trxId; this.resourceBufferManager = resourceBufferManager; this.isClosed = false; this.resourceSession = requireNonNull(resourceSession); this.resourceConfig = resourceSession.getResourceConfig(); this.pageReader = requireNonNull(reader); this.uberPage = requireNonNull(uberPage); this.trxIntentLog = trxIntentLog; revisionNumber = revision; rootPage = revisionRootPageReader.loadRevisionRootPage(this, revision); namePage = revisionRootPageReader.getNamePage(this, rootPage); } private Page loadPage(final PageReference reference) { Page page = reference.getPage(); if (page != null) { return page; } if (trxIntentLog != null && reference.getLogKey() != Constants.NULL_ID_INT) { page = getFromTrxIntentLog(reference); if (page != null) { return page; } } if (trxIntentLog == null) { assert reference.getLogKey() == Constants.NULL_ID_INT; page = resourceBufferManager.getPageCache().get(reference); if (page != null) { reference.setPage(page); return page; } } if (reference.getKey() != Constants.NULL_ID_LONG || reference.getLogKey() != Constants.NULL_ID_INT) { page = pageReader.read(reference, this); } if (page != null) { reference.setPage(page); putIntoPageCacheIfItIsNotAWriteTrx(reference, page); } return page; } private void putIntoPageCacheIfItIsNotAWriteTrx(PageReference reference, Page page) { assert reference.getLogKey() == Constants.NULL_ID_INT; if (trxIntentLog == null && !(page instanceof UberPage)) { // Put page into buffer manager. resourceBufferManager.getPageCache().put(reference, page); } } @Override public boolean hasTrxIntentLog() { return trxIntentLog != null; } @Nullable private Page getFromTrxIntentLog(PageReference reference) { // Try to get it from the transaction log if it's present. final PageContainer cont = trxIntentLog.get(reference); return cont == null ? null : cont.getComplete(); } @Override public long getTrxId() { assertNotClosed(); return trxId; } @Override public ResourceSession getResourceSession() { assertNotClosed(); return resourceSession; } /** * Make sure that the transaction is not yet closed when calling this method. */ void assertNotClosed() { if (isClosed) { throw new IllegalStateException("Transaction is already closed."); } } @Override public V getRecord(final long recordKey, @NonNull final IndexType indexType, @NonNegative final int index) { requireNonNull(indexType); assertNotClosed(); if (recordKey == Fixed.NULL_NODE_KEY.getStandardProperty()) { return null; } final long recordPageKey = pageKey(recordKey, indexType); var indexLogKey = new IndexLogKey(indexType, recordPageKey, index, revisionNumber); // $CASES-OMITTED$ final Page page = switch (indexType) { case DOCUMENT, CHANGED_NODES, RECORD_TO_REVISIONS, PATH_SUMMARY, PATH, CAS, NAME -> getRecordPage(indexLogKey); default -> throw new IllegalStateException(); }; if (page == null) { return null; } final var dataRecord = getValue(((KeyValueLeafPage) page), recordKey); return (V) checkItemIfDeleted(dataRecord); } @Override public DataRecord getValue(final KeyValueLeafPage page, final long nodeKey) { final var offset = PageReadOnlyTrx.recordPageOffset(nodeKey); DataRecord record = page.getRecord(offset); if (record == null) { byte[] data = page.getSlot(offset); if (data != null) { record = getDataRecord(nodeKey, offset, data, page); } if (record != null) { return record; } try { final PageReference reference = page.getPageReference(nodeKey); if (reference != null && reference.getKey() != Constants.NULL_ID_LONG) { data = ((OverflowPage) pageReader.read(reference, this)).getData(); } else { return null; } } catch (final SirixIOException e) { return null; } record = getDataRecord(nodeKey, offset, data, page); } return record; } private DataRecord getDataRecord(long key, int offset, byte[] data, KeyValueLeafPage page) { byteBufferForRecords.clear(); BytesUtils.doWrite(byteBufferForRecords, data); var record = resourceConfig.recordPersister.deserialize(byteBufferForRecords, key, page.getDeweyId(offset), this); byteBufferForRecords.clear(); page.setRecord(record); return record; } /** * Method to check if an {@link DataRecord} is deleted. * * @param toCheck node to check * @return the {@code node} if it is valid, {@code null} otherwise */ V checkItemIfDeleted(final @Nullable V toCheck) { if (toCheck instanceof DeletedNode) { return null; } return toCheck; } @Override public String getName(final int nameKey, @NonNull final NodeKind nodeKind) { assertNotClosed(); return namePage.getName(nameKey, nodeKind, this); } @Override public byte[] getRawName(final int nameKey, @NonNull final NodeKind nodeKind) { assertNotClosed(); return namePage.getRawName(nameKey, nodeKind, this); } /** * Get revision root page belonging to revision key. * * @param revisionKey key of revision to find revision root page for * @return revision root page of this revision key * @throws SirixIOException if something odd happens within the creation process */ @Override public RevisionRootPage loadRevRoot(@NonNegative final int revisionKey) { assert revisionKey <= resourceSession.getMostRecentRevisionNumber(); if (trxIntentLog == null) { final Cache cache = resourceBufferManager.getRevisionRootPageCache(); RevisionRootPage revisionRootPage = cache.get(revisionKey); if (revisionRootPage == null) { revisionRootPage = pageReader.readRevisionRootPage(revisionKey, this); cache.put(revisionKey, revisionRootPage); } return revisionRootPage; } else { if (revisionKey == 0 && uberPage.getRevisionRootReference() != null) { final var revisionRootPageReference = uberPage.getRevisionRootReference(); final var pageContainer = trxIntentLog.get(revisionRootPageReference); return (RevisionRootPage) pageContainer.getModified(); } return pageReader.readRevisionRootPage(revisionKey, this); } } @Override public NamePage getNamePage(@NonNull final RevisionRootPage revisionRoot) { assertNotClosed(); return (NamePage) getPage(revisionRoot.getNamePageReference()); } @Override public PathSummaryPage getPathSummaryPage(@NonNull final RevisionRootPage revisionRoot) { assertNotClosed(); return (PathSummaryPage) getPage(revisionRoot.getPathSummaryPageReference()); } @Override public PathPage getPathPage(@NonNull final RevisionRootPage revisionRoot) { assertNotClosed(); return (PathPage) getPage(revisionRoot.getPathPageReference()); } @Override public CASPage getCASPage(@NonNull final RevisionRootPage revisionRoot) { assertNotClosed(); return (CASPage) getPage(revisionRoot.getCASPageReference()); } @Override public DeweyIDPage getDeweyIDPage(@NonNull final RevisionRootPage revisionRoot) { assertNotClosed(); return (DeweyIDPage) getPage(revisionRoot.getDeweyIdPageReference()); } @Override public BufferManager getBufferManager() { return resourceBufferManager; } /** * Set the page if it is not set already. * * @param reference page reference * @throws SirixIOException if an I/O error occurs */ private Page getPage(final PageReference reference) { var page = loadPage(reference); reference.setPage(page); return page; } @Override public UberPage getUberPage() { assertNotClosed(); return uberPage; } @Override public Page getRecordPage(@NonNull IndexLogKey indexLogKey) { assertNotClosed(); checkArgument(indexLogKey.getRecordPageKey() >= 0, "recordPageKey must not be negative!"); // First: Check most recent pages. if (indexLogKey.getIndexType() == IndexType.PATH_SUMMARY && isMostRecentlyReadPathSummaryPage(indexLogKey)) { return pathSummaryRecordPage.page(); } if (isMostRecentlyReadPage(indexLogKey)) { return mostRecentlyReadRecordPage.page(); } if (isSecondMostRecentlyReadPage(indexLogKey)) { return secondMostRecentlyReadRecordPage.page(); } // Second: Traverse trie. final var pageReferenceToRecordPage = getLeafPageReference(indexLogKey.getRecordPageKey(), indexLogKey.getIndexNumber(), requireNonNull(indexLogKey.getIndexType())); if (pageReferenceToRecordPage == null) { return null; } // Third: Try to get in-memory instance. var page = getInMemoryPageInstance(indexLogKey, pageReferenceToRecordPage); if (page != null) { return page; } // Fourth: Try to get from resource buffer manager. Page recordPageFromBuffer = getFromBufferManager(indexLogKey, pageReferenceToRecordPage); if (recordPageFromBuffer != null) { return recordPageFromBuffer; } if (pageReferenceToRecordPage.getKey() == Constants.NULL_ID_LONG) { // No persistent key set to load page from durable storage. return null; } return loadDataPageFromDurableStorageAndCombinePageFragments(indexLogKey, pageReferenceToRecordPage); } private boolean isMostRecentlyReadPathSummaryPage(IndexLogKey indexLogKey) { return pathSummaryRecordPage != null && pathSummaryRecordPage.recordPageKey == indexLogKey.getRecordPageKey() && pathSummaryRecordPage.index == indexLogKey.getIndexNumber() && pathSummaryRecordPage.revision == indexLogKey.getRevisionNumber(); } private boolean isMostRecentlyReadPage(IndexLogKey indexLogKey) { return mostRecentlyReadRecordPage != null && mostRecentlyReadRecordPage.recordPageKey == indexLogKey.getRecordPageKey() && mostRecentlyReadRecordPage.index == indexLogKey.getIndexNumber() && mostRecentlyReadRecordPage.indexType == indexLogKey.getIndexType() && mostRecentlyReadRecordPage.revision == indexLogKey.getRevisionNumber(); } private boolean isSecondMostRecentlyReadPage(IndexLogKey indexLogKey) { return secondMostRecentlyReadRecordPage != null && secondMostRecentlyReadRecordPage.recordPageKey == indexLogKey.getRecordPageKey() && secondMostRecentlyReadRecordPage.index == indexLogKey.getIndexNumber() && secondMostRecentlyReadRecordPage.indexType == indexLogKey.getIndexType() && secondMostRecentlyReadRecordPage.revision == indexLogKey.getRevisionNumber(); } @Nullable private Page getFromBufferManager(@NonNull IndexLogKey indexLogKey, PageReference pageReferenceToRecordPage) { //if (trxIntentLog == null) { final Page recordPageFromBuffer = resourceBufferManager.getRecordPageCache().get(pageReferenceToRecordPage); if (recordPageFromBuffer != null) { setMostRecentlyReadRecordPage(indexLogKey, recordPageFromBuffer); pageReferenceToRecordPage.setPage(recordPageFromBuffer); return recordPageFromBuffer; } //} return null; } private void setMostRecentlyReadRecordPage(@NonNull IndexLogKey indexLogKey, Page recordPageFromBuffer) { if (indexLogKey.getIndexType() == IndexType.PATH_SUMMARY) { pathSummaryRecordPage = new RecordPage(indexLogKey.getIndexNumber(), indexLogKey.getIndexType(), indexLogKey.getRecordPageKey(), indexLogKey.getRevisionNumber(), recordPageFromBuffer); } else { secondMostRecentlyReadRecordPage = mostRecentlyReadRecordPage; mostRecentlyReadRecordPage = new RecordPage(indexLogKey.getIndexNumber(), indexLogKey.getIndexType(), indexLogKey.getRecordPageKey(), indexLogKey.getRevisionNumber(), recordPageFromBuffer); } } @Nullable private Page loadDataPageFromDurableStorageAndCombinePageFragments(@NonNull IndexLogKey indexLogKey, PageReference pageReferenceToRecordPage) { // Load list of page "fragments" from persistent storage. final List> pages = getPageFragments(pageReferenceToRecordPage); if (pages.isEmpty()) { return null; } final int maxRevisionsToRestore = resourceConfig.maxNumberOfRevisionsToRestore; final VersioningType versioningApproach = resourceConfig.versioningType; final Page completePage = versioningApproach.combineRecordPages(pages, maxRevisionsToRestore, this); if (trxIntentLog == null) { resourceBufferManager.getRecordPageCache().put(pageReferenceToRecordPage, (KeyValueLeafPage) completePage); } pageReferenceToRecordPage.setPage(completePage); setMostRecentlyReadRecordPage(indexLogKey, completePage); return completePage; } @Nullable private Page getInMemoryPageInstance(@NonNull IndexLogKey indexLogKey, @NonNull PageReference pageReferenceToRecordPage) { Page page = pageReferenceToRecordPage.getPage(); if (page != null) { setMostRecentlyReadRecordPage(indexLogKey, page); return page; } return null; } PageReference getLeafPageReference(final @NonNegative long recordPageKey, final int indexNumber, final IndexType indexType) { final PageReference pageReferenceToSubtree = getPageReference(rootPage, indexType, indexNumber); return getReferenceToLeafOfSubtree(pageReferenceToSubtree, recordPageKey, indexNumber, indexType, rootPage); } PageReference getLeafPageReference(final PageReference pageReferenceToSubtree, final @NonNegative long recordPageKey, final int indexNumber, final IndexType indexType, final RevisionRootPage revisionRootPage) { return getReferenceToLeafOfSubtree(pageReferenceToSubtree, recordPageKey, indexNumber, indexType, revisionRootPage); } /** * Dereference key/value page reference and get all leaves, the {@link KeyValuePage}s from the * revision-trees. * * @param pageReference optional page reference pointing to the first page * @return dereferenced pages * @throws SirixIOException if an I/O-error occurs within the creation process */ List> getPageFragments(final PageReference pageReference) { assert pageReference != null; final ResourceConfiguration config = resourceSession.getResourceConfig(); final int revsToRestore = config.maxNumberOfRevisionsToRestore; final int[] revisionsToRead = config.versioningType.getRevisionRoots(rootPage.getRevision(), revsToRestore); final List> pages = new ArrayList<>(revisionsToRead.length); final var pageFragments = pageReference.getPageFragments(); final var pageReferenceWithKey = new PageReference().setKey(pageReference.getKey()); KeyValuePage page; if (trxIntentLog == null) { page = (KeyValuePage) resourceBufferManager.getPageCache().get(pageReferenceWithKey); //assert page == null || page.getRevision() == getRevisionNumber(); if (page == null) { page = (KeyValuePage) pageReader.read(pageReferenceWithKey, this); assert pageReferenceWithKey.getLogKey() == Constants.NULL_ID_INT; resourceBufferManager.getPageCache().put(pageReferenceWithKey, page); } } else { page = (KeyValuePage) pageReader.read(pageReferenceWithKey, this); } pages.add(page); if (pageFragments.isEmpty() || page.size() == Constants.NDP_NODE_COUNT) { return pages; } final List pageFragmentKeys = new ArrayList<>(pageFragments.size() + 1); pageFragmentKeys.addAll(pageFragments); pages.addAll(getPreviousPageFragments(pageFragmentKeys)); return pages; } private List> getPreviousPageFragments(final List pageFragments) { final var pages = pageFragments.stream().map(this::readPage).collect(Collectors.toList()); return sequence(pages).join() .stream() .sorted(Comparator., Integer>comparing(KeyValuePage::getRevision) .reversed()) .collect(Collectors.toList()); } private CompletableFuture> readPage(final PageFragmentKey pageFragmentKey) { final var pageReference = new PageReference().setKey(pageFragmentKey.key()); if (trxIntentLog == null) { final var pageFromBufferManager = resourceBufferManager.getPageCache().get(pageReference); if (pageFromBufferManager != null) { assert pageFragmentKey.revision() == ((KeyValuePage) pageFromBufferManager).getRevision(); return CompletableFuture.completedFuture((KeyValuePage) pageFromBufferManager); } } final var pageReadOnlyTrx = resourceSession.beginPageReadOnlyTrx(pageFragmentKey.revision()); return (CompletableFuture>) pageReadOnlyTrx.getReader() .readAsync(pageReference, pageReadOnlyTrx) .whenComplete((page, exception) -> { pageReadOnlyTrx.close(); if (trxIntentLog == null) { assert pageFragmentKey.revision() == ((KeyValuePage) page).getRevision(); resourceBufferManager.getPageCache() .put(pageReference, page); } }); } static CompletableFuture>> sequence( List>> listOfCompletableFutures) { return CompletableFuture.allOf(listOfCompletableFutures.toArray(new CompletableFuture[0])) .thenApply(v -> listOfCompletableFutures.stream() .map(CompletableFuture::join) .collect(Collectors.toList())); } /** * Get the page reference which points to the right subtree (nodes, path summary nodes, CAS index * nodes, Path index nodes or Name index nodes). * * @param revisionRoot {@link RevisionRootPage} instance * @param indexType the index type * @param index the index to use */ PageReference getPageReference(final RevisionRootPage revisionRoot, final IndexType indexType, final int index) { assert revisionRoot != null; // $CASES-OMITTED$ return switch (indexType) { case DOCUMENT -> revisionRoot.getIndirectDocumentIndexPageReference(); case CHANGED_NODES -> revisionRoot.getIndirectChangedNodesIndexPageReference(); case RECORD_TO_REVISIONS -> revisionRoot.getIndirectRecordToRevisionsIndexPageReference(); case DEWEYID_TO_RECORDID -> getDeweyIDPage(revisionRoot).getIndirectPageReference(); case CAS -> getCASPage(revisionRoot).getIndirectPageReference(index); case PATH -> getPathPage(revisionRoot).getIndirectPageReference(index); case NAME -> getNamePage(revisionRoot).getIndirectPageReference(index); case PATH_SUMMARY -> getPathSummaryPage(revisionRoot).getIndirectPageReference(index); default -> throw new IllegalStateException("Only defined for node, path summary, text value and attribute value pages!"); }; } /** * Dereference indirect page reference. * * @param reference reference to dereference * @return dereferenced page * @throws SirixIOException if something odd happens within the creation process * @throws NullPointerException if {@code reference} is {@code null} */ @Override public IndirectPage dereferenceIndirectPageReference(final PageReference reference) { return (IndirectPage) loadPage(reference); } /** * Find reference pointing to leaf page of an indirect tree. * * @param startReference start reference pointing to the indirect tree * @param pageKey key to look up in the indirect tree * @return reference denoted by key pointing to the leaf page * @throws SirixIOException if an I/O error occurs */ @Nullable @Override public PageReference getReferenceToLeafOfSubtree(final PageReference startReference, final @NonNegative long pageKey, final int indexNumber, final @NonNull IndexType indexType, final RevisionRootPage revisionRootPage) { assertNotClosed(); // Initial state pointing to the indirect page of level 0. PageReference reference = requireNonNull(startReference); int offset; long levelKey = pageKey; final int[] inpLevelPageCountExp = uberPage.getPageCountExp(indexType); final int maxHeight = getCurrentMaxIndirectPageTreeLevel(indexType, indexNumber, revisionRootPage); // Iterate through all levels. for (int level = inpLevelPageCountExp.length - maxHeight, height = inpLevelPageCountExp.length; level < height; level++) { final Page derefPage = dereferenceIndirectPageReference(reference); if (derefPage == null) { reference = null; break; } else { offset = (int) (levelKey >> inpLevelPageCountExp[level]); levelKey -= (long) offset << inpLevelPageCountExp[level]; try { reference = derefPage.getOrCreateReference(offset); } catch (final IndexOutOfBoundsException e) { throw new SirixIOException("Node key isn't supported, it's too big!"); } } } // Return reference to leaf of indirect tree. return reference; } @Override public long pageKey(@NonNegative final long recordKey, @NonNull final IndexType indexType) { assertNotClosed(); return switch (indexType) { case PATH_SUMMARY -> recordKey >> Constants.PATHINP_REFERENCE_COUNT_EXPONENT; case REVISIONS -> recordKey >> Constants.UBPINP_REFERENCE_COUNT_EXPONENT; case PATH, DOCUMENT, CAS, NAME -> recordKey >> Constants.INP_REFERENCE_COUNT_EXPONENT; default -> recordKey >> Constants.NDP_NODE_COUNT_EXPONENT; }; } @Override public int getCurrentMaxIndirectPageTreeLevel(final IndexType indexType, final int index, final RevisionRootPage revisionRootPage) { final int maxLevel; final RevisionRootPage currentRevisionRootPage = revisionRootPage == null ? rootPage : revisionRootPage; // $CASES-OMITTED$ maxLevel = switch (indexType) { case REVISIONS -> throw new IllegalStateException(); case DOCUMENT -> currentRevisionRootPage.getCurrentMaxLevelOfDocumentIndexIndirectPages(); case CHANGED_NODES -> currentRevisionRootPage.getCurrentMaxLevelOfChangedNodesIndexIndirectPages(); case RECORD_TO_REVISIONS -> currentRevisionRootPage.getCurrentMaxLevelOfRecordToRevisionsIndexIndirectPages(); case CAS -> getCASPage(currentRevisionRootPage).getCurrentMaxLevelOfIndirectPages(index); case PATH -> getPathPage(currentRevisionRootPage).getCurrentMaxLevelOfIndirectPages(index); case NAME -> getNamePage(currentRevisionRootPage).getCurrentMaxLevelOfIndirectPages(index); case PATH_SUMMARY -> getPathSummaryPage(currentRevisionRootPage).getCurrentMaxLevelOfIndirectPages(index); case DEWEYID_TO_RECORDID -> getDeweyIDPage(currentRevisionRootPage).getCurrentMaxLevelOfIndirectPages(); }; return maxLevel; } @Override public RevisionRootPage getActualRevisionRootPage() { assertNotClosed(); return rootPage; } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("Session", resourceSession) .add("PageReader", pageReader) .add("UberPage", uberPage) .add("RevRootPage", rootPage) .toString(); } @Override public synchronized void close() { if (!isClosed) { if (trxIntentLog == null) { pageReader.close(); } if (resourceSession.getNodeReadTrxByTrxId(trxId).isEmpty()) { resourceSession.closePageReadTransaction(trxId); } isClosed = true; } } @Override public int getNameCount(final int key, @NonNull final NodeKind kind) { assertNotClosed(); return namePage.getCount(key, kind, this); } @Override public boolean isClosed() { return isClosed; } @Override public int getRevisionNumber() { assertNotClosed(); return rootPage.getRevision(); } @Override public Reader getReader() { assertNotClosed(); return pageReader; } @Override public CommitCredentials getCommitCredentials() { assertNotClosed(); return rootPage.getCommitCredentials(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy