use of org.corfudb.protocols.wireprotocol.LogData 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.LogData 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.LogData 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.LogData in project CorfuDB by CorfuDB.
the class StreamLogFilesTest method testSameAddressTrim.
@Test
public void testSameAddressTrim() throws Exception {
StreamLogFiles log = new StreamLogFiles(getContext(), false);
// Trim an unwritten address
long address = 0L;
log.trim(address);
// Verify that the unwritten address trim is not persisted
StreamLogFiles.SegmentHandle sh = log.getSegmentHandleForAddress(address);
assertThat(sh.getPendingTrims().size()).isEqualTo(0);
// Write to the same address
ByteBuf b = Unpooled.buffer();
byte[] streamEntry = "Payload".getBytes();
Serializers.CORFU.serialize(streamEntry, b);
log.append(address, new LogData(DataType.DATA, b));
// Verify that the address has been written
assertThat(log.read(address)).isNotNull();
// Trim the address
log.trim(address);
sh = log.getSegmentHandleForAddress(address);
assertThat(sh.getPendingTrims().contains(address)).isTrue();
// Write to a trimmed address
assertThatThrownBy(() -> log.append(address, new LogData(DataType.DATA, b))).isInstanceOf(OverwriteException.class);
// Read trimmed address
assertThatThrownBy(() -> log.read(address)).isInstanceOf(TrimmedException.class);
}
use of org.corfudb.protocols.wireprotocol.LogData in project CorfuDB by CorfuDB.
the class LogUnitServerAssertions method matchesDataAtAddress.
public LogUnitServerAssertions matchesDataAtAddress(long address, Object data) {
isNotNull();
if (actual.getDataCache().get(address) == null) {
failWithMessage("Expected address <%d> to contain data but was empty!", address);
} else {
ByteBuf b = Unpooled.buffer();
Serializers.CORFU.serialize(data, b);
byte[] expected = new byte[b.readableBytes()];
b.getBytes(0, expected);
org.assertj.core.api.Assertions.assertThat(((LogData) actual.getDataCache().get(address)).getData()).isEqualTo(expected);
}
return this;
}
Aggregations