com.kolibrifx.plovercrest.server.internal.streams.RangeStreamUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of plovercrest-server Show documentation
Show all versions of plovercrest-server Show documentation
Plovercrest server library.
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();
}
}