package org.corfudb.runtime.view.replication; import lombok.extern.slf4j.Slf4j; import org.corfudb.protocols.wireprotocol.ILogData; import org.corfudb.runtime.exceptions.HoleFillRequiredException; import org.corfudb.runtime.view.Layout; import javax.annotation.Nonnull; /** * Created by mwei on 4/6/17. */ @Slf4j public abstract class AbstractReplicationProtocol implements IReplicationProtocol { /** The hole fill policy to apply. */ final protected IHoleFillPolicy holeFillPolicy; /** Build the replication protocol using the given hole filling policy. * * @param holeFillPolicy The hole filling policy to be applied when * a read returns uncommitted data. */ public AbstractReplicationProtocol(IHoleFillPolicy holeFillPolicy) { this.holeFillPolicy = holeFillPolicy; } /** {@inheritDoc} * * In the base implementation, we attempt to read data * using the peek method. If data is returned by peek, * we use it. Otherwise, we invoke the hole filling * protocol. * **/ @Nonnull @Override public ILogData read(Layout layout, long globalAddress) { try { return holeFillPolicy .peekUntilHoleFillRequired(globalAddress, a -> peek(layout, a)); } catch (HoleFillRequiredException e) { log.debug("HoleFill[{}] due to {}", globalAddress, e.getMessage()); holeFill(layout, globalAddress); return peek(layout, globalAddress); } } /** * Write a special hole filling entry using the * given address. When this call returns, either * the hole filling write has been committed * or the result of another client's write * has committed (you WILL need to -read- the * address to find out which write was adopted). * * @param globalAddress The address to hole fill. */ abstract protected void holeFill(Layout layout, long globalAddress); }