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

io.deephaven.engine.page.PageStore Maven / Gradle / Ivy

There is a newer version: 0.37.1
Show newest version
/**
 * Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending
 */
package io.deephaven.engine.page;

import io.deephaven.chunk.attributes.Any;
import io.deephaven.engine.table.ChunkSource;
import io.deephaven.engine.table.impl.DefaultChunkSource;
import io.deephaven.engine.table.impl.DefaultGetContext;
import io.deephaven.chunk.*;
import io.deephaven.engine.rowset.RowSequence;
import io.deephaven.engine.rowset.RowSequenceFactory;
import io.deephaven.util.annotations.FinalDefault;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * PageStores are a collection of non-overlapping {@link Page Pages}, providing a single {@link PagingChunkSource}
 * across all the pages. PageStores are responsible for mapping row keys to pages. PageStores may themselves be Pages
 * nested within other PageStores.
 */
public interface PageStore>
        extends PagingChunkSource, DefaultChunkSource.SupportsContiguousGet {

    /**
     * @param fillContext The fill context to use; may be {@code null} if the calling code does not have a fill context
     * @param rowKey The row key to get the page for
     * @return The page containing {@code rowKey}, after applying {@link #mask()}.
     */
    @NotNull
    PAGE getPageContaining(@Nullable FillContext fillContext, long rowKey);

    @Override
    default Chunk getChunk(@NotNull final GetContext context, @NotNull final RowSequence rowSequence) {
        if (rowSequence.isEmpty()) {
            return getChunkType().getEmptyChunk();
        }

        final long firstKey = rowSequence.firstRowKey();
        final FillContext fillContext = DefaultGetContext.getFillContext(context);
        final PAGE page = getPageContaining(fillContext, firstKey);
        final long pageMaxRow = page.maxRow(firstKey);

        if (rowSequence.lastRowKey() <= pageMaxRow) {
            return page.getChunk(context, rowSequence);
        } else {
            final WritableChunk destination = DefaultGetContext.getWritableChunk(context);
            doFillChunkAppend(fillContext, destination, rowSequence, page);
            return destination;
        }
    }

    @Override
    @NotNull
    default Chunk getChunk(@NotNull final GetContext context, final long firstKey, final long lastKey) {
        final FillContext fillContext = DefaultGetContext.getFillContext(context);
        final PAGE page = getPageContaining(fillContext, firstKey);
        final long pageMaxRow = page.maxRow(firstKey);

        if (lastKey <= pageMaxRow) {
            return page.getChunk(context, firstKey, lastKey);
        } else {
            try (final RowSequence rowSequence = RowSequenceFactory.forRange(firstKey, lastKey)) {
                final WritableChunk destination = DefaultGetContext.getWritableChunk(context);
                doFillChunkAppend(fillContext, destination, rowSequence, page);
                return destination;
            }
        }
    }

    @Override
    default void fillChunk(
            @NotNull final FillContext context,
            @NotNull final WritableChunk destination,
            @NotNull final RowSequence rowSequence) {
        if (rowSequence.isEmpty()) {
            return;
        }

        final long firstKey = rowSequence.firstRowKey();
        final PAGE page = getPageContaining(context, firstKey);
        final long pageMaxRow = page.maxRow(firstKey);

        if (rowSequence.lastRowKey() <= pageMaxRow) {
            page.fillChunk(context, destination, rowSequence);
        } else {
            doFillChunkAppend(context, destination, rowSequence, page);
        }
    }

    @Override
    default void fillChunkAppend(
            @NotNull final FillContext context,
            @NotNull final WritableChunk destination,
            @NotNull final RowSequence.Iterator rowSequenceIterator) {
        long firstKey = rowSequenceIterator.peekNextKey();
        final long pageStoreMaxKey = maxRow(firstKey);

        do {
            final PAGE page = getPageContaining(context, firstKey);
            page.fillChunkAppend(context, destination, rowSequenceIterator);
        } while (rowSequenceIterator.hasMore() &&
                (firstKey = rowSequenceIterator.peekNextKey()) <= pageStoreMaxKey);
    }

    /**
     * This is a helper which is the same as a call to {@link #fillChunkAppend}, except that some of the initial work
     * has already been done for the first call to
     * {@link Page#fillChunkAppend(FillContext, WritableChunk, RowSequence.Iterator)} which we don't want to repeat.
     */
    // Should be private
    @FinalDefault
    default void doFillChunkAppend(
            @NotNull final FillContext context,
            @NotNull final WritableChunk destination,
            @NotNull final RowSequence rowSequence,
            @NotNull final Page page) {
        destination.setSize(0);
        try (final RowSequence.Iterator rowSequenceIterator = rowSequence.getRowSequenceIterator()) {
            page.fillChunkAppend(context, destination, rowSequenceIterator);
            fillChunkAppend(context, destination, rowSequenceIterator);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy