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

com.kolibrifx.plovercrest.server.internal.streams.RangeStreamUtils Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010-2017, KolibriFX AS. Licensed under the Apache License, version 2.0.
 */

package com.kolibrifx.plovercrest.server.internal.streams;

import java.util.concurrent.atomic.AtomicBoolean;
import com.kolibrifx.plovercrest.client.RangeQuery;
import com.kolibrifx.plovercrest.server.internal.streams.RangeStreamObserver.EndOfRangeException;
import com.kolibrifx.plovercrest.server.streams.PollableReader;
import com.kolibrifx.plovercrest.server.streams.ReaderPosition;
import com.kolibrifx.plovercrest.server.streams.Stream;
import com.kolibrifx.plovercrest.server.streams.StreamObserver;

/**
 * Helper for reading a range of elements.
 */
public final class RangeStreamUtils {
    private RangeStreamUtils() {
    }

    public static  RangeStreamObserver createRangeObserver(final RangeQuery.RangeType rangeType,
                                                                 final long startTimestampOrIndex,
                                                                 final long endTimestampOrIndex, final int skipCount,
                                                                 final StreamObserver observer) {
        switch (rangeType) {
            case OVERLAPPING_TIME_RANGE:
                return new OverlappingRangeObserver(observer, endTimestampOrIndex, skipCount);
            case NON_OVERLAPPING_TIME_RANGE:
                return new NonOverlappingRangeObserver(observer, startTimestampOrIndex, endTimestampOrIndex,
                                                          skipCount);
            case ELEMENT_INDEX_RANGE:
                return new EntryIndexRangeObserver(observer, endTimestampOrIndex);
            default:
                throw new IllegalStateException("Unknown range type " + rangeType);
        }
    }

    public static  RuntimeReadContinuation doRead(final PollableReader reader, final int maxCount,
                                                        final RangeStreamObserver rangeObserver,
                                                        final AtomicBoolean timedOut) {
        boolean atEndOfRange = false;
        try {
            final int initialCount = rangeObserver.getObservedCount();
            while (rangeObserver.getObservedCount() - initialCount < maxCount) {
                if (!reader.poll()) {
                    break;
                }
                if (rangeObserver.getObservedCount() > initialCount && timedOut.get()) {
                    // we read at least one element, and can abort a slow read operation
                    break;
                }
            }
        } catch (final EndOfRangeException e) {
            // normal control flow
            atEndOfRange = true;
        }
        final RangeReadInfo info =
                new RangeReadInfo(rangeObserver.getObservedCount(), rangeObserver.isAtEndOfStream(),
                                  rangeObserver.getLastValidTimestamp(), reader.getReaderPosition(), atEndOfRange);
        return new RuntimeReadContinuation<>(reader, rangeObserver, info);
    }

    public static  RuntimeReadContinuation readRange(final Stream stream, final int maxCount,
                                                           final RangeQuery query, final StreamObserver observer,
                                                           final AtomicBoolean timedOut) {
        final RangeStreamObserver rangeObserver =
                createRangeObserver(query.getRangeType(), query.getStart(), query.getEnd(), 0, observer);
        PollableReader reader;
        switch (query.getRangeType()) {
            case ELEMENT_INDEX_RANGE:
                reader = stream.createReaderFromIndex(query.getStart(), rangeObserver);
                break;
            case NON_OVERLAPPING_TIME_RANGE:
                reader = stream.createReaderFromTimestamp(query.getStart(), rangeObserver);
                break;
            case OVERLAPPING_TIME_RANGE:
                reader = stream.createReaderFromTimestamp(query.getStart(), rangeObserver);
                break;
            default:
                throw new IllegalStateException("Unknown range type " + query.getRangeType());
        }
        return doRead(reader, maxCount, rangeObserver, timedOut);
    }

    public static  RangeReadInfo
            continueReadRange(final Stream stream, final int maxCount, final RangeQuery.RangeType rangeType,
                              final long end, final StreamObserver observer, final ReaderPosition readerPosition,
                              final AtomicBoolean timedOut) {
        final long start = readerPosition.getTimestampOrIndex(); // only used for NON_OVERLAPPING_TIME_RANGE
        final RangeStreamObserver rangeObserver =
                createRangeObserver(rangeType, start, end, readerPosition.getSkipCount(), observer);
        final PollableReader reader;
        switch (readerPosition.getPositionType()) {
            case INDEX:
                reader = stream.createReaderFromIndex(readerPosition.getTimestampOrIndex(), rangeObserver);
                break;
            case TIMESTAMP:
                reader = stream.createReaderFromTimestamp(readerPosition.getTimestampOrIndex(), rangeObserver);
                break;
            default:
                throw new IllegalStateException("Unknown position type " + readerPosition.getPositionType());
        }
        return doRead(reader, maxCount, rangeObserver, timedOut).getInfo();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy