use of org.corfudb.protocols.wireprotocol.ILogData in project CorfuDB by CorfuDB.
the class QuorumReplicationProtocol method peek.
/** {@inheritDoc} */
@Override
public ILogData peek(Layout layout, long address) {
int numUnits = layout.getSegmentLength(address);
log.trace("Peek[{}]: quorum {}/{}", address, numUnits, numUnits);
try {
ReadResponse readResponse = null;
try {
CompletableFuture<ReadResponse>[] futures = new CompletableFuture[numUnits];
for (int i = 0; i < numUnits; i++) {
futures[i] = layout.getLogUnitClient(address, i).read(address);
}
QuorumFuturesFactory.CompositeFuture<ReadResponse> future = QuorumFuturesFactory.getQuorumFuture(new ReadResponseComparator(address), futures);
readResponse = CFUtils.getUninterruptibly(future, QuorumUnreachableException.class);
} catch (QuorumUnreachableException e) {
e.printStackTrace();
log.debug(e.getMessage(), e);
return null;
}
if (readResponse != null) {
LogData result = readResponse.getReadSet().get(address);
if (result != null && !isEmptyType(result.getType())) {
return result;
}
}
return null;
} catch (RuntimeException e) {
throw e;
}
}
use of org.corfudb.protocols.wireprotocol.ILogData in project CorfuDB by CorfuDB.
the class QuorumReplicationProtocol method write.
/** {@inheritDoc} */
@Override
public void write(Layout layout, ILogData data) throws OverwriteException {
final long globalAddress = data.getGlobalAddress();
log.debug("Write at {} " + globalAddress);
IMetadata.DataRank rank = new IMetadata.DataRank(0);
QuorumFuturesFactory.CompositeFuture<Boolean> future = null;
data.setRank(rank);
try {
try (ILogData.SerializationHandle sh = data.getSerializedForm()) {
future = getWriteFuture(layout, sh.getSerialized());
CFUtils.getUninterruptibly(future, QuorumUnreachableException.class, OverwriteException.class, DataOutrankedException.class);
}
} catch (OverwriteException e) {
log.error("Client implementation error, race in phase 1. Broken sequencer, data consistency in danger.");
throw e;
} catch (LogUnitException | QuorumUnreachableException e) {
if (future.containsThrowableFrom(DataOutrankedException.class) || future.containsThrowableFrom(ValueAdoptedException.class)) {
// we are competing with other client that writes the same data or fills a hole
boolean adopted = recoveryWrite(layout, data);
if (!adopted) {
return;
}
}
throw new OverwriteException();
}
}
use of org.corfudb.protocols.wireprotocol.ILogData in project CorfuDB by CorfuDB.
the class QuorumReplicationProtocol method recoveryWrite.
private boolean recoveryWrite(Layout layout, ILogData logData) {
long address = logData.getGlobalAddress();
log.debug("Recovery write at {} " + address);
Holder<ILogData> dh = new Holder<>(logData);
AtomicBoolean otherValueAdopted = new AtomicBoolean(false);
AtomicInteger retryCount = new AtomicInteger(0);
if (logData.getRank() == null) {
logData.setRank(new IMetadata.DataRank(0));
}
try {
IRetry.build(ExponentialBackoffRetry.class, () -> {
QuorumFuturesFactory.CompositeFuture<Boolean> future = null;
try {
log.debug("Recovery write loop for " + log);
// increment the rank
dh.getRef().releaseBuffer();
dh.getRef().setRank(dh.getRef().getRank().buildHigherRank());
// peek for existing
if (retryCount.getAndIncrement() > 0) {
try {
return holeFillPolicy.peekUntilHoleFillRequired(address, a -> peek(layout, a));
} catch (HoleFillRequiredException e) {
log.debug(e.getMessage(), e);
// continuing
}
}
// phase 1
try (ILogData.SerializationHandle ph1 = createEmptyData(dh.getRef().getGlobalAddress(), DataType.RANK_ONLY, dh.getRef().getRank())) {
future = getWriteFuture(layout, ph1.getSerialized());
CFUtils.getUninterruptibly(future, QuorumUnreachableException.class, OverwriteException.class, DataOutrankedException.class);
} catch (LogUnitException | QuorumUnreachableException e) {
e.printStackTrace();
ReadResponse rr = getAdoptedValueWithHighestRankIfPresent(address, future.getThrowables());
if (rr != null) {
// check
LogData logDataExisting = rr.getReadSet().get(address);
logDataExisting.releaseBuffer();
logDataExisting.setRank(dh.getRef().getRank());
dh.setRef(logDataExisting.getSerializedForm().getSerialized());
otherValueAdopted.set(true);
// value adopted - continue on phase 2
} else {
throw e;
}
}
// phase 2 - only if exception is not thrown from phase 1
future = getWriteFuture(layout, dh.getRef());
CFUtils.getUninterruptibly(future, QuorumUnreachableException.class, OverwriteException.class, DataOutrankedException.class);
log.trace("Write done[{}]: {}", address);
return dh.getRef();
} catch (QuorumUnreachableException | DataOutrankedException e) {
e.printStackTrace();
throw new RetryNeededException();
} catch (RuntimeException e) {
e.printStackTrace();
throw e;
}
}).setOptions(WRITE_RETRY_SETTINGS).run();
return otherValueAdopted.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("interrupted", e);
} catch (RuntimeException e) {
throw e;
}
}
use of org.corfudb.protocols.wireprotocol.ILogData in project CorfuDB by CorfuDB.
the class QuorumReplicationProtocol method createEmptyData.
private ILogData.SerializationHandle createEmptyData(long position, DataType type, IMetadata.DataRank rank) {
ILogData data = new LogData(type);
data.setRank(rank);
data.setGlobalAddress(position);
return data.getSerializedForm();
}
use of org.corfudb.protocols.wireprotocol.ILogData in project CorfuDB by CorfuDB.
the class AbstractContextStreamView method getNextEntries.
/** Retrieve the next entries in the stream, given the context.
*
* This function is designed to implement a bulk read. In a bulk read,
* one of the entries may cause the context to change - the implementation
* should check if the entry changes the context and stop reading
* if this occurs, returning the entry that caused contextCheckFn to return
* true.
*
* The default implementation simply calls getNextEntry.
*
* @param context The context to retrieve the next entry from.
* @param maxGlobal The maximum global address to read to.
* @param contextCheckFn A function which returns true if the entry changes the stream context.
* @return
*/
protected List<ILogData> getNextEntries(T context, long maxGlobal, Function<ILogData, Boolean> contextCheckFn) {
final List<ILogData> dataList = new ArrayList<>();
ILogData thisData;
while ((thisData = getNextEntry(context, maxGlobal)) != null) {
// Add this read to the list of reads to return.
dataList.add(thisData);
// Update the pointer, because the underlying implementation
// will expect it to be updated when we call getNextEntry() again.
updatePointer(thisData);
// If this entry changes the context, don't continue reading.
if (contextCheckFn.apply(thisData)) {
break;
}
}
return dataList;
}
Aggregations