use of org.corfudb.runtime.exceptions.LogUnitException 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.runtime.exceptions.LogUnitException 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;
}
}
Aggregations