Class ChainedCursor<T>
- java.lang.Object
-
- com.apple.foundationdb.record.cursors.ChainedCursor<T>
-
- Type Parameters:
T
- the type of elements of the cursor
- All Implemented Interfaces:
BaseCursor<T>
,RecordCursor<T>
,AutoCloseable
,Iterator<T>
@API(MAINTAINED) public class ChainedCursor<T> extends Object implements BaseCursor<T>
A cursor that iterates over a set of data that is dynamically generated a single value at a time. The cursor is driven by a value generation function. The function initially takes anOptional.empty()
as input, and from that produces an initial value. Upon subsequent iterations the function is given the value it previously returned and the next value is computed. For example, the following generator would produce the values from 1 to 10:maybePreviousValue -> { if (maybePreviousValue.isPresent()) { if (maybePreviousValue.get() < 10) { return Optional.of(maybePreviousValue.get() + 1); } else { return Optional.empty(); } } return Optional.of(1); }
Given this function, theChainedCursor
would iteratively generate the value from 1 to 10.In order to support continuations, the cursor must additionally be provided a functions that can encode and decode the values it produces into binary continuation form. So the fully defined cursor to perform our iteration from 1 to 10, would look like:
new ChainedCursor( // Value generator maybePreviousValue -> { if (maybePreviousValue.isPresent()) { if (maybePreviousValue.get() < 10) { return Optional.of(maybePreviousValue.get() + 1); } else { return Optional.empty(); } } return Optional.of(1); }, // Continuation encoder previousValue -> Tuple.from(previousValue).pack(), // Continuation decoder encodedContinuation -> Tuple.fromBytes(encodedContinuation).getLong(0) executor )
Resource Governing
When theChainedCursor
is created with a set ofScanProperties
it will attempt to count each iteration of the cursor against the limits that are indicated by the properties. This can lead to an interesting behavior if the same set ofScanProperties
are also used by cursors that are present in thenextGenerator
that is provided and can lead to double-counting. For example, if thenextGenerator
is driven by the read of a row key via theKeyValueCursor
, the cursor could end up counting that read, and theChainedCursor
would then, again, count that read. As such, the caller should take care when specifying theScanProperties
to the cursor and within thenextGenerator
.In addition, while the
ChainedCursor
can track and limit on scanned records and scan time, it has no visibility into any bytes that may have been read by cursor managed by thenextGenerator
and, thus, cannot enforce any byte scan limits.
-
-
Nested Class Summary
-
Nested classes/interfaces inherited from interface com.apple.foundationdb.record.RecordCursor
RecordCursor.NoNextReason
-
-
Constructor Summary
Constructors Constructor Description ChainedCursor(FDBRecordContext context, Function<Optional<T>,CompletableFuture<Optional<T>>> nextGenerator, Function<T,byte[]> continuationEncoder, Function<byte[],T> continuationDecoder, byte[] continuation, ScanProperties scanProperties)
Creates aChainedCursor
.ChainedCursor(Function<Optional<T>,CompletableFuture<Optional<T>>> nextGenerator, Function<T,byte[]> continuationEncoder, Function<byte[],T> continuationDecoder, byte[] continuation, Executor executor)
Creates a newChainedCursor
.
-
Method Summary
All Methods Instance Methods Concrete Methods Deprecated Methods Modifier and Type Method Description boolean
accept(RecordCursorVisitor visitor)
Accept a visit from hierarchical visitor, which implementsRecordCursorVisitor
.void
close()
byte[]
getContinuation()
Deprecated.Executor
getExecutor()
RecordCursor.NoNextReason
getNoNextReason()
Deprecated.T
next()
Deprecated.CompletableFuture<Boolean>
onHasNext()
Deprecated.CompletableFuture<RecordCursorResult<T>>
onNext()
Asynchronously return the next result from this cursor.-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface java.util.Iterator
forEachRemaining, remove
-
Methods inherited from interface com.apple.foundationdb.record.RecordCursor
asIterator, asList, filter, filterAsync, filterAsyncInstrumented, filterAsyncInstrumented, filterInstrumented, filterInstrumented, first, flatMapPipelined, forEach, forEachAsync, forEachResult, forEachResultAsync, getCount, getNext, hasNext, limitRowsTo, limitTo, map, mapEffect, mapEffect, mapPipelined, orElse, reduce, skip, skipThenLimit
-
-
-
-
Constructor Detail
-
ChainedCursor
public ChainedCursor(@Nonnull Function<Optional<T>,CompletableFuture<Optional<T>>> nextGenerator, @Nonnull Function<T,byte[]> continuationEncoder, @Nonnull Function<byte[],T> continuationDecoder, @Nullable byte[] continuation, @Nonnull Executor executor)
Creates a newChainedCursor
. When created in this fashion any resource limits that may be specified in cursors that are used within thenextGenerator
will be honored.- Parameters:
nextGenerator
- a function that that is called to perform iterationcontinuationEncoder
- a function that takes a value that was returned bynextGenerator
and encodes it as a continuation valuecontinuationDecoder
- a function that takes a continuation that was produced bycontinuationEncoder
and decodes it back to its original value as returned bynextGenerator
continuation
- the initial continuation for the iterationexecutor
- executor that will be returned bygetExecutor()
-
ChainedCursor
public ChainedCursor(@Nonnull FDBRecordContext context, @Nonnull Function<Optional<T>,CompletableFuture<Optional<T>>> nextGenerator, @Nonnull Function<T,byte[]> continuationEncoder, @Nonnull Function<byte[],T> continuationDecoder, @Nullable byte[] continuation, @Nonnull ScanProperties scanProperties)
Creates aChainedCursor
.The
ScanProperties.isReverse()
} cannot be honored by theChainedCursor
as the direction of iteration is strictly controlled by thenextGenerator
.- Parameters:
context
- a record contextnextGenerator
- a function that that is called to perform iterationcontinuationEncoder
- a function that takes a value that was returned bynextGenerator
and encodes it as a continuation valuecontinuationDecoder
- a function that takes a continuation that was produced bycontinuationEncoder
and decodes it back to its original value as returned bynextGenerator
continuation
- the initial continuation for the iterationscanProperties
- properties used to control the scanning behavior
-
-
Method Detail
-
onNext
@Nonnull public CompletableFuture<RecordCursorResult<T>> onNext()
Description copied from interface:RecordCursor
Asynchronously return the next result from this cursor. When complete, the future will contain aRecordCursorResult
, which represents exactly one of the following:-
The next object of type
T
produced by the cursor. In addition to the next record, this result includes aRecordCursorContinuation
that can be used to continue the cursor after the last record returned. The returned continuation is guaranteed not to be an "end continuation" representing the end of the cursor: specifically,RecordCursorContinuation.isEnd()
is alwaysfalse
on the returned continuation. -
The fact that the cursor is stopped and cannot produce another record and a
RecordCursor.NoNextReason
that explains why no record could be produced. The result include a continuation that can be used to continue the cursor after the last record returned. If the result'sNoNextReason
is anything other thanRecordCursor.NoNextReason.SOURCE_EXHAUSTED
, the returned continuation must not be an end continuation. Conversely, if the result'sNoNextReason
isSOURCE_EXHAUSTED
, then the returned continuation must be an an "end continuation".
RecordCursorContinuation
can be serialized to an opaque byte array usingRecordCursorContinuation.toBytes()
. This can be passed back into a new cursor of the same type, with all other parameters remaining the same.- Specified by:
onNext
in interfaceRecordCursor<T>
- Returns:
- a future for the next result from this cursor representing either the next record or an indication of why the cursor stopped
- See Also:
RecordCursorResult
,RecordCursorContinuation
-
The next object of type
-
onHasNext
@Nonnull @Deprecated public CompletableFuture<Boolean> onHasNext()
Deprecated.Description copied from interface:RecordCursor
Asynchronously check whether there are more records available from the cursor.- Specified by:
onHasNext
in interfaceRecordCursor<T>
- Returns:
- a future that when complete will hold
true
ifRecordCursor.next()
would return a record. - See Also:
AsyncIterator.onHasNext()
-
next
@Nullable @Deprecated public T next()
Deprecated.Description copied from interface:RecordCursor
Return the next value.
-
getContinuation
@Nullable @Deprecated public byte[] getContinuation()
Deprecated.Description copied from interface:RecordCursor
Get a byte string that can be used to continue a query after the last record returned.- Specified by:
getContinuation
in interfaceRecordCursor<T>
- Returns:
- opaque byte array denoting where the cursor should pick up. This can be passed back into a new
cursor of the same type, with all other parameters remaining the same.
Returns
null
if the underlying source is completely exhausted, independent of any limit passed to the cursor creator. Since such creators generally acceptnull
to mean no continuation, that is, start from the beginning, one must check fornull
fromgetContinuation
to keep from starting over. Result is not always defined if called beforeonHasNext
or beforenext
afteronHasNext
has returnedtrue
. That is, a continuation is only guaranteed when called "between" records from awhile (hasNext) next
loop or after its end.
-
getNoNextReason
@Nonnull @Deprecated public RecordCursor.NoNextReason getNoNextReason()
Deprecated.Description copied from interface:RecordCursor
Get the reason that the cursor has reached the end and returnedfalse
forRecordCursor.hasNext()
. IfhasNext
was not called or returnedtrue
last time, the result is undefined and may be an exception.- Specified by:
getNoNextReason
in interfaceRecordCursor<T>
- Returns:
- the reason that the cursor stopped
-
close
public void close()
- Specified by:
close
in interfaceAutoCloseable
- Specified by:
close
in interfaceRecordCursor<T>
-
getExecutor
@Nonnull public Executor getExecutor()
- Specified by:
getExecutor
in interfaceRecordCursor<T>
-
accept
public boolean accept(@Nonnull RecordCursorVisitor visitor)
Description copied from interface:RecordCursor
Accept a visit from hierarchical visitor, which implementsRecordCursorVisitor
. By contract, implementations of this method must return the value ofvisitor.visitLeave(this)
, which determines whether or not subsequent siblings of this cursor should be visited.- Specified by:
accept
in interfaceRecordCursor<T>
- Parameters:
visitor
- a hierarchical visitor- Returns:
true
if the subsequent siblings of thecursor
should be visited, andfalse
otherwise
-
-