use of herddb.log.FullRecoveryNeededException in project herddb by diennea.
the class TableSpaceManager method recover.
void recover(TableSpace tableSpaceInfo) throws DataStorageManagerException, LogNotAvailableException, MetadataStorageManagerException {
LogSequenceNumber logSequenceNumber = dataStorageManager.getLastcheckpointSequenceNumber(tableSpaceUUID);
actualLogSequenceNumber = logSequenceNumber;
LOGGER.log(Level.INFO, "{0} recover {1}, logSequenceNumber from DataStorage: {2}", new Object[] { nodeId, tableSpaceName, logSequenceNumber });
List<Table> tablesAtBoot = dataStorageManager.loadTables(logSequenceNumber, tableSpaceUUID);
List<Index> indexesAtBoot = dataStorageManager.loadIndexes(logSequenceNumber, tableSpaceUUID);
String tableNames = tablesAtBoot.stream().map(t -> {
return t.name;
}).collect(Collectors.joining(","));
String indexNames = indexesAtBoot.stream().map(t -> {
return t.name + " on table " + t.table;
}).collect(Collectors.joining(","));
LOGGER.log(Level.INFO, "{0} {1} tablesAtBoot {2}, indexesAtBoot {3}", new Object[] { nodeId, tableSpaceName, tableNames, indexNames });
for (Table table : tablesAtBoot) {
TableManager tableManager = bootTable(table, 0, null);
for (Index index : indexesAtBoot) {
if (index.table.equals(table.name)) {
bootIndex(index, tableManager, 0, false);
}
}
}
dataStorageManager.loadTransactions(logSequenceNumber, tableSpaceUUID, t -> {
transactions.put(t.transactionId, t);
LOGGER.log(Level.FINER, "{0} {1} tx {2} at boot", new Object[] { nodeId, tableSpaceName, t.transactionId });
try {
if (t.newTables != null) {
for (Table table : t.newTables.values()) {
if (!tables.containsKey(table.name)) {
bootTable(table, t.transactionId, null);
}
}
}
if (t.newIndexes != null) {
for (Index index : t.newIndexes.values()) {
if (!indexes.containsKey(index.name)) {
AbstractTableManager tableManager = tables.get(index.table);
bootIndex(index, tableManager, t.transactionId, false);
}
}
}
} catch (Exception err) {
LOGGER.log(Level.SEVERE, "error while booting tmp tables " + err, err);
throw new RuntimeException(err);
}
});
try {
log.recovery(logSequenceNumber, new ApplyEntryOnRecovery(), false);
} catch (FullRecoveryNeededException fullRecoveryNeeded) {
LOGGER.log(Level.SEVERE, nodeId + " full recovery of data is needed for tableSpace " + tableSpaceName, fullRecoveryNeeded);
downloadTableSpaceData();
log.recovery(actualLogSequenceNumber, new ApplyEntryOnRecovery(), false);
}
checkpoint(false, false);
}
use of herddb.log.FullRecoveryNeededException in project herddb by diennea.
the class BookkeeperCommitLog method recovery.
@Override
public void recovery(LogSequenceNumber snapshotSequenceNumber, BiConsumer<LogSequenceNumber, LogEntry> consumer, boolean fencing) throws LogNotAvailableException {
this.actualLedgersList = metadataManager.getActualLedgersList(tableSpaceUUID);
LOGGER.log(Level.SEVERE, "Actual ledgers list:" + actualLedgersList + " tableSpace " + tableSpaceUUID);
this.lastLedgerId = snapshotSequenceNumber.ledgerId;
this.currentLedgerId = snapshotSequenceNumber.ledgerId;
this.lastSequenceNumber.set(snapshotSequenceNumber.offset);
LOGGER.log(Level.SEVERE, "recovery from latest snapshotSequenceNumber:" + snapshotSequenceNumber);
if (currentLedgerId > 0 && !this.actualLedgersList.getActiveLedgers().contains(currentLedgerId) && !this.actualLedgersList.getActiveLedgers().isEmpty()) {
// TODO: download snapshot from another remote broker
throw new FullRecoveryNeededException(new Exception("Actual ledgers list does not include latest snapshot ledgerid:" + currentLedgerId));
}
if (snapshotSequenceNumber.isStartOfTime() && !this.actualLedgersList.getActiveLedgers().isEmpty() && !this.actualLedgersList.getActiveLedgers().contains(this.actualLedgersList.getFirstLedger())) {
throw new FullRecoveryNeededException(new Exception("Local data is absent, and actual ledger list " + this.actualLedgersList.getActiveLedgers() + " does not contain first ledger of ever: " + this.actualLedgersList.getFirstLedger()));
}
try {
for (long ledgerId : actualLedgersList.getActiveLedgers()) {
if (ledgerId < snapshotSequenceNumber.ledgerId) {
LOGGER.log(Level.SEVERE, "Skipping ledger " + ledgerId);
continue;
}
LedgerHandle handle;
if (fencing) {
handle = bookKeeper.openLedger(ledgerId, BookKeeper.DigestType.CRC32, sharedSecret.getBytes(StandardCharsets.UTF_8));
} else {
handle = bookKeeper.openLedgerNoRecovery(ledgerId, BookKeeper.DigestType.CRC32, sharedSecret.getBytes(StandardCharsets.UTF_8));
}
try {
long first;
if (ledgerId == snapshotSequenceNumber.ledgerId) {
first = snapshotSequenceNumber.offset;
LOGGER.log(Level.SEVERE, "Recovering from latest snapshot ledger " + ledgerId + ", starting from entry " + first);
} else {
first = 0;
LOGGER.log(Level.SEVERE, "Recovering from ledger " + ledgerId + ", starting from entry " + first);
}
long lastAddConfirmed = handle.getLastAddConfirmed();
LOGGER.log(Level.SEVERE, "Recovering from ledger " + ledgerId + ", first=" + first + " lastAddConfirmed=" + lastAddConfirmed);
final int BATCH_SIZE = 10000;
if (lastAddConfirmed >= 0) {
for (long b = first; b <= lastAddConfirmed; ) {
long start = b;
long end = b + BATCH_SIZE;
if (end > lastAddConfirmed) {
end = lastAddConfirmed;
}
b = end + 1;
double percent = ((start - first) * 100.0 / (lastAddConfirmed + 1));
int entriesToRead = (int) (1 + end - start);
LOGGER.log(Level.SEVERE, "From entry {0}, to entry {1} ({2} %)", new Object[] { start, end, percent });
long _start = System.currentTimeMillis();
Enumeration<LedgerEntry> entries = handle.readEntries(start, end);
int localEntryCount = 0;
while (entries.hasMoreElements()) {
LedgerEntry entry = entries.nextElement();
long entryId = entry.getEntryId();
LogSequenceNumber number = new LogSequenceNumber(ledgerId, entryId);
LogEntry statusEdit = LogEntry.deserialize(entry.getEntry());
lastLedgerId = ledgerId;
currentLedgerId = ledgerId;
lastSequenceNumber.set(entryId);
if (number.after(snapshotSequenceNumber)) {
LOGGER.log(Level.FINEST, "RECOVER ENTRY #" + localEntryCount + " {0}, {1}", new Object[] { number, statusEdit });
consumer.accept(number, statusEdit);
} else {
LOGGER.log(Level.FINEST, "SKIP ENTRY #" + localEntryCount + " {0}<{1}, {2}", new Object[] { number, snapshotSequenceNumber, statusEdit });
}
localEntryCount++;
}
LOGGER.log(Level.SEVERE, "read " + localEntryCount + " entries from ledger " + ledgerId + ", expected " + entriesToRead);
LOGGER.log(Level.SEVERE, "finished waiting for " + entriesToRead + " entries to be read from ledger " + ledgerId);
if (localEntryCount != entriesToRead) {
throw new LogNotAvailableException("Read " + localEntryCount + " entries, expected " + entriesToRead);
}
lastLedgerId = ledgerId;
lastSequenceNumber.set(end);
long _stop = System.currentTimeMillis();
LOGGER.log(Level.SEVERE, "From entry {0}, to entry {1} ({2} %) read time {3}", new Object[] { start, end, percent, (_stop - _start) + " ms" });
}
}
} finally {
handle.close();
}
}
LOGGER.severe("After recovery of " + tableSpaceUUID + " lastSequenceNumber " + getLastSequenceNumber());
} catch (InterruptedException | EOFException | RuntimeException | BKException err) {
LOGGER.log(Level.SEVERE, "Fatal error during recovery", err);
signalLogFailed();
throw new LogNotAvailableException(err);
}
}
Aggregations