use of org.corfudb.runtime.exceptions.HoleFillRequiredException 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.runtime.exceptions.HoleFillRequiredException in project CorfuDB by CorfuDB.
the class ReadWaitHoleFillPolicy method peekUntilHoleFillRequired.
/** {@inheritDoc} */
@Nonnull
@Override
public ILogData peekUntilHoleFillRequired(long address, Function<Long, ILogData> peekFunction) throws HoleFillRequiredException {
int tryNum = 0;
do {
// If this is not the first try, sleep before trying again
if (tryNum != 0) {
try {
Thread.sleep(waitMs);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// Try the read
ILogData data = peekFunction.apply(address);
// If it was not null, we can return it.
if (data != null) {
return data;
}
// Otherwise increment the counter and try again.
tryNum++;
} while (numRetries > tryNum);
throw new HoleFillRequiredException("No data after " + tryNum + " retries");
}
Aggregations