package org.corfudb.runtime.view.replication;
import org.corfudb.protocols.wireprotocol.ILogData;
import org.corfudb.runtime.exceptions.OverwriteException;
import org.corfudb.runtime.view.Layout;
import javax.annotation.Nonnull;
import java.util.*;
import java.util.stream.Collectors;
/** The public interface to a replication protocol.
*
* A replication protocol exposes three public functions, which
* permit reading and writing to the log.
*
* Created by mwei on 4/6/17.
*/
public interface IReplicationProtocol {
/** Write data to the log at the given address.
*
* This function blocks until -a- write at the global address
* is committed to the log.
*
* If the write which is committed to the log was this write,
* the function returns normally.
*
* If the write which was committed to the log was not the result
* of this call, an OverwriteException is thrown.
*
* @param layout The layout to use for the write.
* @param data The ILogData to write to the log.
* @throws OverwriteException If a write was committed to the log and
* it was not the result of this call.
*/
void write(Layout layout, ILogData data) throws OverwriteException;
/** Read data from a given address.
*
* This function only returns committed data. If the
* address given has not committed, the implementation may
* either block until it is committed, or commit a hole filling
* entry to that address.
*
* @param layout The layout to use for the read.
* @param globalAddress The global address to read the data from.
* @return The data that was committed at the
* given global address, committing a hole
* filling entry if necessary.
*/
@Nonnull ILogData read(Layout layout, long globalAddress);
/** Read data from all the given addresses.
*
* This method functions exactly like a read, except
* that it returns the result for multiple addresses.
*
* An implementation may optimize for this type of
* bulk request, but the default implementation
* just performs multiple reads (possible in parallel).
*
* @param layout The layout to use for the readAll.
* @param globalAddresses A set of addresses to read from.
* @return A map of addresses to committed
* addresses, hole filling if necessary.
*/
default @Nonnull Map<Long, ILogData> readAll(Layout layout, Set<Long> globalAddresses) {
return globalAddresses.parallelStream()
.map(a -> new AbstractMap.SimpleImmutableEntry<>(a, read(layout, a)))
.collect(Collectors.toMap(r -> r.getKey(), r -> r.getValue()));
}
/** Peek data from a given address.
*
* This function -may- return null if there was no entry
* committed at the given global address, otherwise it
* returns committed data at the given global address. It
* does not attempt to hole fill if there was no entry.
*
* @param layout The layout to use for the peek.
* @param globalAddress The global address to peek from.
* @return The data that was committed at the
* given global address, or NULL, if
* there was no entry committed.
*/
ILogData peek(Layout layout, long globalAddress);
/** Peek data from all the given addresses.
*
* This method functions exactly like a peek, except
* that it returns the result for multiple addresses.
*
* An implementation may optimize for this type of
* bulk request, but the default implementation
* just performs multiple peeks (possibly in parallel).
*
* @param layout The layout to use for the peekAll.
* @param globalAddresses A set of addresses to read from.
* @return A map of addresses to uncommitted
* addresses, without hole filling.
*/
default @Nonnull Map<Long, ILogData> peekAll(Layout layout, Set<Long> globalAddresses) {
return globalAddresses.parallelStream()
.map(a -> new AbstractMap.SimpleImmutableEntry<>(a, peek(layout, a)))
.collect(Collectors.toMap(r -> r.getKey(), r -> r.getValue()));
}
}