use of org.corfudb.runtime.exceptions.OverwriteException 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.OverwriteException in project CorfuDB by CorfuDB.
the class InMemoryStreamLog method append.
@Override
public synchronized void append(long address, LogData entry) {
try {
checkRange(address);
} catch (TrimmedException e) {
throw new OverwriteException();
}
if (logCache.containsKey(address)) {
throwLogUnitExceptionsIfNecessary(address, entry);
}
logCache.put(address, entry);
globalTail.getAndUpdate(maxTail -> entry.getGlobalAddress() > maxTail ? entry.getGlobalAddress() : maxTail);
}
use of org.corfudb.runtime.exceptions.OverwriteException in project CorfuDB by CorfuDB.
the class StreamsView method copy.
/**
* Make a copy-on-append copy of a stream.
*
* @param source The UUID of the stream to make a copy of.
* @param destination The UUID of the destination stream. It must not exist.
* @return A view
*/
public IStreamView copy(UUID source, UUID destination, long timestamp) {
boolean written = false;
while (!written) {
TokenResponse tokenResponse = runtime.getSequencerView().nextToken(Collections.singleton(destination), 1);
if (tokenResponse.getBackpointerMap().get(destination) != null && Address.isAddress(tokenResponse.getBackpointerMap().get(destination))) {
// Reading from this address will cause a hole fill
runtime.getAddressSpaceView().read(tokenResponse.getTokenValue());
throw new RuntimeException("Stream already exists!");
}
StreamCOWEntry entry = new StreamCOWEntry(source, timestamp);
TokenResponse cowToken = new TokenResponse(tokenResponse.getTokenValue(), tokenResponse.getEpoch(), Collections.singletonMap(destination, Address.COW_BACKPOINTER));
try {
runtime.getAddressSpaceView().write(cowToken, entry);
written = true;
} catch (OverwriteException oe) {
log.debug("hole fill during COW entry append, retrying...");
}
}
return get(destination);
}
use of org.corfudb.runtime.exceptions.OverwriteException in project CorfuDB by CorfuDB.
the class ChainReplicationProtocol method recover.
/** Recover a failed write at the given global address,
* driving it to completion by invoking the recovery
* protocol.
*
* When this function returns the given globalAddress
* is guaranteed to contain a committed value.
*
* If there was no data previously written at the address,
* this function will throw a runtime exception. The
* recovery protocol should -only- be invoked if we
* previously were overwritten.
*
* @oaram layout The layout to use for the recovery.
* @param globalAddress The global address to drive
* the recovery protocol
*
*/
protected void recover(Layout layout, long globalAddress) {
// In chain replication, we started writing from the head,
// and propagated down to the tail. To recover, we start
// reading from the head, which should have the data
// we are trying to recover
int numUnits = layout.getSegmentLength(globalAddress);
log.debug("Recover[{}]: read chain head {}/{}", globalAddress, 1, numUnits);
ILogData ld = CFUtils.getUninterruptibly(layout.getLogUnitClient(globalAddress, 0).read(globalAddress)).getReadSet().getOrDefault(globalAddress, null);
// write was successful or not.
if (ld == null || ld.isEmpty()) {
throw new RecoveryException("Failed to read data during recovery at chain head.");
}
// now we go down the chain and write, ignoring any overwrite exception we get.
for (int i = 1; i < numUnits; i++) {
log.debug("Recover[{}]: write chain {}/{}", layout, i + 1, numUnits);
// in the chain.
try {
CFUtils.getUninterruptibly(layout.getLogUnitClient(globalAddress, i).write(ld), OverwriteException.class);
// We successfully recovered a write to this member of the chain
log.debug("Recover[{}]: recovered write at chain {}/{}", layout, i + 1, numUnits);
} catch (OverwriteException oe) {
// This member already had this data (in some cases, the write might have
// been committed to all members, so this is normal).
log.debug("Recover[{}]: overwritten at chain {}/{}", layout, i + 1, numUnits);
}
}
}
use of org.corfudb.runtime.exceptions.OverwriteException in project CorfuDB by CorfuDB.
the class StreamLogFiles method append.
@Override
public void append(long address, LogData entry) {
//evict the data by getting the next pointer.
try {
// make sure the entry doesn't currently exist...
// (probably need a faster way to do this - high watermark?)
SegmentHandle fh = getSegmentHandleForAddress(address);
if (fh.getKnownAddresses().containsKey(address) || fh.getTrimmedAddresses().contains(address)) {
if (entry.getRank() == null) {
throw new OverwriteException();
} else {
// the method below might throw DataOutrankedException or ValueAdoptedException
assertAppendPermittedUnsafe(address, entry);
AddressMetaData addressMetaData = writeRecord(fh, address, entry);
fh.getKnownAddresses().put(address, addressMetaData);
}
} else {
AddressMetaData addressMetaData = writeRecord(fh, address, entry);
fh.getKnownAddresses().put(address, addressMetaData);
}
log.trace("Disk_write[{}]: Written to disk.", address);
} catch (IOException e) {
log.error("Disk_write[{}]: Exception", address, e);
throw new RuntimeException(e);
} catch (TrimmedException e) {
throw new OverwriteException();
}
}
Aggregations