/** * 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 */ package org.corfudb.infrastructure.log; import org.corfudb.protocols.wireprotocol.DataType; import org.corfudb.protocols.wireprotocol.LogData; import org.corfudb.protocols.wireprotocol.ReadResponse; import org.corfudb.runtime.exceptions.DataOutrankedException; import org.corfudb.runtime.exceptions.OverwriteException; import org.corfudb.runtime.exceptions.ValueAdoptedException; /** * Stream log that is able to compare the data on the same log address using the rank and type. * * Created by Konstantin Spirov on 3/15/2017. */ public interface StreamLogWithRankedAddressSpace extends StreamLog { /** * Check whether the data can be appended to a given log address. * Note that it is not permitted multiple threads to access the same log address * concurrently through this method, this method does not lock or synchronize. * This method needs * @param logAddress * @param newEntry * @throws DataOutrankedException if the log entry cannot be assigned to this log address as there is a data with higher rank * @throws ValueAdoptedException if the new message is a proposal during the two phase recovery write and there is an existing * data at this log address already. * @throw OverwriteException if the new data is with rank 0 (not from recovery write). This can happen only if there is a bug in the client implementation. */ default void assertAppendPermittedUnsafe(LogAddress logAddress, LogData newEntry) throws DataOutrankedException, ValueAdoptedException { LogData oldEntry = read(logAddress); if (oldEntry.getType()==DataType.EMPTY) { return; } if (newEntry.getRank().getRank()==0) { // data consistency in danger throw new OverwriteException(); } int compare = newEntry.getRank().compareTo(oldEntry.getRank()); if (compare<0) { throw new DataOutrankedException(); } if (compare>0) { if (newEntry.getType()==DataType.RANK_ONLY && oldEntry.getType() != DataType.RANK_ONLY) { // the new data is a proposal, the other data is not, so the old value should be adopted ReadResponse resp = new ReadResponse(); resp.put(logAddress.getAddress(), oldEntry); throw new ValueAdoptedException(resp); } else { return; } } } }