package org.corfudb.runtime.view.stream; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.corfudb.protocols.wireprotocol.ILogData; import org.corfudb.protocols.wireprotocol.TokenResponse; import org.corfudb.runtime.view.Address; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; import java.util.function.Function; import java.util.stream.Stream; import java.util.stream.StreamSupport; /** This interface represents a view on a stream. A stream is an ordered * set of log entries which can only be appended to and read in sequential * order. * * Created by mwei on 1/5/17. */ public interface IStreamView extends Iterator<ILogData> { /** Return the ID of the stream this view is for. * @return The ID of the stream. */ UUID getID(); /** Reset the state of this stream view, causing the next read to * start from the beginning of this stream. */ void reset(); /** Seek to the requested maxGlobal address. The next read will * begin at the given global address, inclusive. * @param globalAddress */ void seek(long globalAddress); /** An enum representing search directions. */ @RequiredArgsConstructor enum SearchDirection { /** Search forward. */ FORWARD(false, true), /** Search forward, including address given. */ FORWARD_INCLUSIVE(true, true), /** Search backwards. */ REVERSE(false, false), /** Search backwards, including address given. */ REVERSE_INCLUSIVE(true, false); /** Whether the address given should be included * in the search. */ @Getter final boolean inclusive; /** True if the search is forward, false otherwise. */ @Getter final boolean forward; } /** Find the global address of the next entry in this stream, * in the direction given. * * @param globalAddress The global address to start searching from. * @param direction The direction to search. * @return The global address of the next entry in the * stream, or Address.NOT_FOUND if no entry * was found. */ long find(long globalAddress, SearchDirection direction); /** Append an object to the stream, returning the global address * it was written at. * <p> * Optionally, provide a method to be called when an address is acquired, * and also a method to be called when an address is released (due to * an unsuccessful append). * </p> * @param object The object to append. * @param acquisitionCallback A function to call when an address is * acquired. * It should return true to continue with the * append. * @param deacquisitionCallback A function to call when an address is * released. It should return true to retry * writing. * @return The (global) address the object was written at. */ long append(Object object, Function<TokenResponse, Boolean> acquisitionCallback, Function<TokenResponse, Boolean> deacquisitionCallback); /** Append an object to the stream, returning the global address it was * written at. * @param object * @return The (global) address the object was written at. */ default long append(Object object) { return append(object, null, null); } /** Retrieve the next entry from this stream, up to the tail of the stream * If there are no entries present, this function will return NULL. If there * are holes present in the log, they will be filled. * @return The next entry in the stream, or NULL, if no entries are * available. */ @Nullable default ILogData next() { return nextUpTo(Long.MAX_VALUE); } /** Retrieve the previous entry in the stream. If there are no previous entries, * NULL will be returned. * @return The previous entry in the stream, or NULL, if no entries are * available. */ @Nullable ILogData previous(); /** Retrieve the current entry in the stream, which was the entry previously * returned by a call to next() or previous(). If the stream was never read * from, NULL will be returned. * * @return The current entry in the stream. */ @Nullable ILogData current(); /** Retrieve the next entry from this stream, up to the address given or the * tail of the stream. If there are no entries present, this function * will return NULL. If there are holes present in the log, they will * be filled. * @param maxGlobal The maximum global address to read up to. * @return The next entry in the stream, or NULL, if no entries * are available. */ @Nullable ILogData nextUpTo(long maxGlobal); /** Retrieve all of the entries from this stream, up to the tail of this * stream. If there are no entries present, this function * will return an empty list. If there are holes present in the log, * they will be filled. * * Note: the default implementation is thread-safe only if the * implementation of read is synchronized. * * @return The next entries in the stream, or an empty list, * if no entries are available. */ @Nonnull default List<ILogData> remaining() { return remainingUpTo(Address.MAX); } /** Retrieve all of the entries from this stream, up to the address given or * the tail of the stream. If there are no entries present, this function * will return an empty list. If there are holes present in the log, * they will be filled. * * @param maxGlobal The maximum global address to read up to. * @return The next entries in the stream, or an empty list, * if no entries are available. */ List<ILogData> remainingUpTo(long maxGlobal); /** Returns whether or not there are potentially more entries in this * stream - this function may return true even if there are no entries * remaining, as addresses may have been acquired by other clients * but not written yet, or the addresses were hole-filled, or just failed. * @return True, if there are potentially more entries in the stream. */ boolean hasNext(); /** Get the current position of the pointer in this stream (global address). * * @return The position of the pointer in this stream (global address), * or Address.NON_ADDRESS. */ long getCurrentGlobalPosition(); /** Get a spliterator for this stream view * @return A spliterator for this stream view. */ default Spliterator<ILogData> spliterator() { return new StreamSpliterator(this); } /** Get a spliterator for this stream view, limiting the return * values to a specified global address. * @param maxGlobal The maximum global address to read to * @return A spliterator for this stream view. */ default Spliterator<ILogData> spliteratorUpTo(long maxGlobal) { return new StreamSpliterator(this, maxGlobal); } /** Get a Java stream from this stream view. * @return A Java stream for this stream view. */ default Stream<ILogData> stream() { return StreamSupport.stream(spliterator(), false); } /** Get a Java stream from this stream view, limiting * reads to a specified global address. * @param maxGlobal The maximum global address to read to. * @return A spliterator for this stream view. */ default Stream<ILogData> streamUpTo(long maxGlobal) { return StreamSupport.stream(spliteratorUpTo(maxGlobal), false); } }