use of io.pravega.segmentstore.storage.DataLogCorruptedException in project pravega by pravega.
the class DurableLog method performRecovery.
@SneakyThrows(Exception.class)
private boolean performRecovery() {
// Make sure we are in the correct state. We do not want to do recovery while we are in full swing.
Preconditions.checkState(state() == State.STARTING || (state() == State.RUNNING && isOffline()), "Invalid State for recovery.");
Timer timer = new Timer();
try {
// Initialize the DurableDataLog, which will acquire its lock and ensure we are the only active users of it.
this.durableDataLog.initialize(DEFAULT_TIMEOUT);
// Initiate the recovery.
RecoveryProcessor p = new RecoveryProcessor(this.metadata, this.durableDataLog, this.memoryStateUpdater);
int recoveredItemCount = p.performRecovery();
this.operationProcessor.getMetrics().operationsCompleted(recoveredItemCount, timer.getElapsed());
this.operationProcessor.getMetrics().reportOperationLogSize(recoveredItemCount, this.getId());
// Verify that the Recovery Processor has left the metadata in a non-recovery mode.
Preconditions.checkState(!this.metadata.isRecoveryMode(), "Recovery completed but Metadata is still in Recovery Mode.");
return recoveredItemCount > 0;
} catch (Exception ex) {
log.error("{} Recovery FAILED.", this.traceObjectId, ex);
Throwable cause = Exceptions.unwrap(ex);
if (cause instanceof ServiceHaltException || cause instanceof DataLogCorruptedException) {
// debugging information before someone can manually fix the problem).
try {
this.durableDataLog.disable();
log.info("{} Log disabled due to {} during recovery.", this.traceObjectId, cause.getClass().getSimpleName());
} catch (Exception disableEx) {
log.warn("{}: Unable to disable log after DataCorruptionException during recovery.", this.traceObjectId, disableEx);
ex.addSuppressed(disableEx);
}
}
throw ex;
}
}
use of io.pravega.segmentstore.storage.DataLogCorruptedException in project pravega by pravega.
the class BookKeeperLogTests method testReadWithBadLogId.
/**
* Tests the ability to reject reading from a Log if it has been found it contains Ledgers that do not belong to it.
*/
@Test
public void testReadWithBadLogId() throws Exception {
final BookKeeper bk = this.factory.get().getBookKeeperClient();
try (val log = (BookKeeperLog) createDurableDataLog()) {
log.initialize(TIMEOUT);
log.append(new CompositeByteArraySegment(new byte[100]), TIMEOUT).join();
}
// Add some bad ledgers to the log's metadata.
val writeLog = (BookKeeperLog) createDurableDataLog();
val wrapper = this.factory.get().createDebugLogWrapper(writeLog.getLogId());
wrapper.disable();
val ledgerNoLogId = createCustomLedger(null);
val corruptedId = new HashMap<>(Ledgers.createLedgerCustomMetadata(CONTAINER_ID));
corruptedId.put(Ledgers.PROPERTY_LOG_ID, "abc".getBytes());
val ledgerBadLogId = createCustomLedger(corruptedId);
val ledgerOtherLogId = createCustomLedger(Ledgers.createLedgerCustomMetadata(CONTAINER_ID + 1));
val ledgerGoodLogId = Ledgers.create(bk, this.config.get(), CONTAINER_ID);
val candidateLedgers = Arrays.asList(ledgerNoLogId, ledgerBadLogId, ledgerOtherLogId, ledgerGoodLogId);
for (val lh : candidateLedgers) {
lh.append(new byte[100]);
}
// Persist the metadata with bad ledgers.
val initialMetadata = wrapper.fetchMetadata();
val newLedgers = new ArrayList<LedgerMetadata>();
newLedgers.addAll(initialMetadata.getLedgers());
candidateLedgers.forEach(l -> newLedgers.add(new LedgerMetadata(l.getId(), newLedgers.size() + 1)));
val badMetadata = LogMetadata.builder().enabled(false).epoch(initialMetadata.getEpoch() + 1).truncationAddress(LogMetadata.INITIAL_TRUNCATION_ADDRESS).updateVersion(wrapper.fetchMetadata().getUpdateVersion()).ledgers(newLedgers).build();
writeLog.overWriteMetadata(badMetadata);
// Perform an initial read. This should fail.
val readLog = (BookKeeperLog) createDurableDataLog();
readLog.enable();
readLog.initialize(TIMEOUT);
@Cleanup val reader = readLog.getReader();
AssertExtensions.assertThrows("No read exception thrown.", () -> {
while (reader.getNext() != null) {
// This is intentionally left blank. We do not care what we read back.
}
}, ex -> ex instanceof DataLogCorruptedException);
// Perform reconciliation.
BookKeeperLog reconcileLog = (BookKeeperLog) createDurableDataLog();
DebugBookKeeperLogWrapper reconcileWrapper = this.factory.get().createDebugLogWrapper(reconcileLog.getLogId());
reconcileWrapper.disable();
val allLedgers = new ArrayList<ReadHandle>();
for (LedgerMetadata lm : reconcileWrapper.fetchMetadata().getLedgers()) {
allLedgers.add(reconcileWrapper.openLedgerNoFencing(lm));
}
boolean isChanged = reconcileWrapper.reconcileLedgers(allLedgers);
Assert.assertTrue("Expected something to change.", isChanged);
// There should only be two ledgers that survived: the one where we wrote to the original log and ledgerGoodLogId.
checkLogReadAfterReconciliation(2);
}
Aggregations