/** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.aurora.scheduler.log; import java.io.IOException; import java.util.Iterator; /** * Represents an append only log that can be read after and truncated before a known * {@link Position}. * * <p>Logs are accessed by {@link #open() opening} a {@link Stream}. All stream * access occurs with references to log entry {@link Position positions} in the stream. */ public interface Log { /** * An opaque ordered handle to a log entry's position in the log stream. */ interface Position extends Comparable<Position> { } /** * Represents a single entry in the log stream. */ interface Entry { /** * Gets the contents of the log entry. * * @return the data stored in this log entry */ byte[] contents(); } /** * An interface to the live {@link Log} stream that allows for appending, reading and writing * entries. */ interface Stream { /** * Indicates a {@link Position} that is not (currently) contained in this log stream. * This might indicate the position id from a different log or that the position was from this * log but has been truncated. */ class InvalidPositionException extends RuntimeException { public InvalidPositionException(String message) { super(message); } public InvalidPositionException(String message, Throwable cause) { super(message, cause); } } /** * Indicates a {@link Stream} could not be read from, written to or truncated due to some * underlying IO error. */ class StreamAccessException extends RuntimeException { public StreamAccessException(String message, Throwable cause) { super(message, cause); } } /** * Appends an {@link Entry} to the end of the log stream. * * @param contents the data to store in the appended entry * @return the posiiton of the appended entry * @throws StreamAccessException if contents could not be appended to the stream */ Position append(byte[] contents) throws StreamAccessException; /** * Allows reading all entries from the log stream. Implementations may * materialize all entries at once or the may provide some form of streaming to back the * returned entry iterator. If the implementation does use some form of streaming or batching, * it may throw a * {@code StreamAccessException} on any call to {@link Iterator#hasNext()} or * {@link Iterator#next()}. * * @return an iterator that ranges from the entry from the given {@code position} to the last * entry in the log. * @throws InvalidPositionException if the specified position does not exist in this log * @throws StreamAccessException if the stream could not be read from */ Iterator<Entry> readAll() throws InvalidPositionException, StreamAccessException; /** * Removes all log entries preceding the log entry at the given {@code position}. * * @param position the position of the latest entry to remove * @throws InvalidPositionException if the specified position does not exist in this log * @throws StreamAccessException if the stream could not be truncated */ void truncateBefore(Position position) throws InvalidPositionException, StreamAccessException; } /** * Opens the log stream for reading writing and truncation. Clients should ensure the stream is * closed when they are done using it. * * @return the log stream * @throws IOException if there was a problem opening the log stream */ Stream open() throws IOException; }