Search in sources :

Example 6 with LedgerEntries

use of org.apache.bookkeeper.client.api.LedgerEntries in project herddb by diennea.

the class BookkeeperCommitLog method recovery.

@Override
public void recovery(LogSequenceNumber snapshotSequenceNumber, BiConsumer<LogSequenceNumber, LogEntry> consumer, boolean fencing) throws LogNotAvailableException {
    String tableSpaceDescription = tableSpaceDescription();
    this.actualLedgersList = metadataManager.getActualLedgersList(tableSpaceUUID);
    LOGGER.log(Level.INFO, "Actual ledgers list:{0} tableSpace {1}", new Object[] { actualLedgersList, tableSpaceDescription });
    this.lastLedgerId = snapshotSequenceNumber.ledgerId;
    this.currentLedgerId = snapshotSequenceNumber.ledgerId;
    this.lastSequenceNumber.set(snapshotSequenceNumber.offset);
    LOGGER.log(Level.INFO, "recovery from latest snapshotSequenceNumber:{0} tableSpace {1}, node {2}, fencing {3}", new Object[] { snapshotSequenceNumber, tableSpaceDescription, localNodeId, fencing });
    if (!isRecoveryAvailable(snapshotSequenceNumber, actualLedgersList, tableSpaceDescription)) {
        throw new FullRecoveryNeededException("Cannot recover from BookKeeper, not enough data, plese check the logs");
    }
    for (long ledgerId : actualLedgersList.getActiveLedgers()) {
        try {
            Versioned<LedgerMetadata> result = FutureUtils.result(bookKeeper.getLedgerManager().readLedgerMetadata(ledgerId));
            LedgerMetadata metadata = result.getValue();
            String ledgerLeader = extractLeaderFromMetadata(metadata.getCustomMetadata());
            LOGGER.log(Level.INFO, "Ledger {0}: {1} {2} created by {3}, LastEntryId {4} Length {5}", new Object[] { String.valueOf(ledgerId), metadata.getState(), metadata.getAllEnsembles(), ledgerLeader, metadata.getLastEntryId(), metadata.getLength() });
        } catch (BKException.BKNoSuchLedgerExistsException | BKException.BKNoSuchLedgerExistsOnMetadataServerException e) {
            if (ledgerId < snapshotSequenceNumber.ledgerId) {
                LOGGER.log(Level.INFO, "Actual ledgers list includes a not existing ledgerid:" + ledgerId + " tablespace " + tableSpaceDescription + ", but this ledger is not useful for recovery (snapshotSequenceNumber.ledgerId is " + snapshotSequenceNumber.ledgerId);
            } else {
                throw new FullRecoveryNeededException(new Exception("Actual ledgers list includes a not existing ledgerid:" + ledgerId + " tablespace " + tableSpaceDescription));
            }
        } catch (LogNotAvailableException e) {
            throw e;
        } catch (Exception e) {
            throw new LogNotAvailableException(e);
        }
    }
    try {
        for (long ledgerId : actualLedgersList.getActiveLedgers()) {
            if (ledgerId < snapshotSequenceNumber.ledgerId) {
                LOGGER.log(Level.FINER, "Skipping ledger {0}", ledgerId);
                continue;
            }
            ReadHandle handle;
            try {
                if (fencing) {
                    handle = bookKeeper.openLedger(ledgerId, BookKeeper.DigestType.CRC32C, SHARED_SECRET.getBytes(StandardCharsets.UTF_8));
                } else {
                    handle = bookKeeper.openLedgerNoRecovery(ledgerId, BookKeeper.DigestType.CRC32C, SHARED_SECRET.getBytes(StandardCharsets.UTF_8));
                }
            } catch (org.apache.bookkeeper.client.api.BKException errorDuringOpen) {
                throw new LogNotAvailableException("Cannot open ledger " + ledgerId + " (fencing " + fencing + "): " + errorDuringOpen, errorDuringOpen);
            }
            try {
                long first;
                if (ledgerId == snapshotSequenceNumber.ledgerId) {
                    first = snapshotSequenceNumber.offset;
                    if (first == -1) {
                        // this can happen if checkpoint  happened while starting to follow a new ledger but actually no entry was ever read
                        LOGGER.log(Level.INFO, "Tablespace " + tableSpaceDescription + ", recovering from latest snapshot ledger " + ledgerId + ", first entry " + first + " is not valid. Adjusting to 0");
                        first = 0;
                    }
                    if (LOGGER.isLoggable(Level.FINE)) {
                        LOGGER.log(Level.FINE, "Tablespace " + tableSpaceDescription + ", recovering from latest snapshot ledger " + ledgerId + ", starting from entry " + first);
                    }
                } else {
                    first = 0;
                    if (LOGGER.isLoggable(Level.FINE)) {
                        LOGGER.log(Level.FINE, "Tablespace " + tableSpaceDescription + ", recovering from ledger " + ledgerId + ", starting from entry " + first);
                    }
                }
                long lastAddConfirmed = handle.getLastAddConfirmed();
                String ledgerLeader = extractLeaderFromMetadata(handle.getLedgerMetadata().getCustomMetadata());
                LOGGER.log(Level.INFO, "Tablespace " + tableSpaceDescription + ", Recovering from ledger " + ledgerId + ", first=" + first + " lastAddConfirmed=" + lastAddConfirmed + " written by " + ledgerLeader);
                if (lastAddConfirmed >= 0) {
                    for (long b = first; b <= lastAddConfirmed; ) {
                        long start = b;
                        long end = b + RECOVERY_BATCH_SIZE;
                        if (end > lastAddConfirmed) {
                            end = lastAddConfirmed;
                        }
                        b = end + 1;
                        double percent = ((start - first) * 100.0 / (lastAddConfirmed + 1));
                        int entriesToRead = (int) (1 + end - start);
                        if (LOGGER.isLoggable(Level.FINE)) {
                            LOGGER.log(Level.FINE, "{3} From entry {0}, to entry {1} ({2} %)", new Object[] { start, end, percent, tableSpaceDescription });
                        }
                        long _start = System.currentTimeMillis();
                        int localEntryCount = 0;
                        try (LedgerEntries entries = handle.read(start, end)) {
                            for (org.apache.bookkeeper.client.api.LedgerEntry entry : entries) {
                                long entryId = entry.getEntryId();
                                LogSequenceNumber number = new LogSequenceNumber(ledgerId, entryId);
                                LogEntry statusEdit = readLogEntry(entry);
                                lastLedgerId = ledgerId;
                                currentLedgerId = ledgerId;
                                lastSequenceNumber.set(entryId);
                                if (number.after(snapshotSequenceNumber)) {
                                    if (LOGGER.isLoggable(Level.FINEST)) {
                                        LOGGER.log(Level.FINEST, "rec " + tableSpaceName + " #" + localEntryCount + " {0}, {1}", new Object[] { number, statusEdit });
                                    }
                                    consumer.accept(number, statusEdit);
                                } else {
                                    if (LOGGER.isLoggable(Level.FINEST)) {
                                        LOGGER.log(Level.FINEST, "skip " + tableSpaceName + " #" + localEntryCount + " {0}<{1}, {2}", new Object[] { number, snapshotSequenceNumber, statusEdit });
                                    }
                                }
                                localEntryCount++;
                            }
                        }
                        LOGGER.log(Level.FINER, tableSpaceDescription() + " read " + localEntryCount + " entries from ledger " + ledgerId + ", expected " + entriesToRead);
                        if (localEntryCount != entriesToRead) {
                            throw new LogNotAvailableException(tableSpaceDescription() + " Read " + localEntryCount + " entries, expected " + entriesToRead);
                        }
                        lastLedgerId = ledgerId;
                        lastSequenceNumber.set(end);
                        long _stop = System.currentTimeMillis();
                        LOGGER.log(Level.INFO, "{4} From entry {0}, to entry {1} ({2} %) read time {3}", new Object[] { start, end, percent, (_stop - _start) + " ms", tableSpaceDescription });
                    }
                }
            } catch (RuntimeException err) {
                LOGGER.log(Level.SEVERE, "Internal error while recovering tablespace " + tableSpaceDescription() + ": " + err, err);
                throw err;
            } finally {
                handle.close();
            }
        }
        LOGGER.log(Level.INFO, "After recovery of {0} lastSequenceNumber {1}", new Object[] { tableSpaceDescription, getLastSequenceNumber() });
    } catch (IOException | InterruptedException | org.apache.bookkeeper.client.api.BKException err) {
        LOGGER.log(Level.SEVERE, "Fatal error during recovery of " + tableSpaceDescription(), err);
        signalLogFailed();
        throw new LogNotAvailableException(err);
    } catch (LogNotAvailableException err) {
        LOGGER.log(Level.SEVERE, "Fatal error during recovery of " + tableSpaceDescription(), err);
        signalLogFailed();
        throw err;
    }
}
Also used : ReadHandle(org.apache.bookkeeper.client.api.ReadHandle) FullRecoveryNeededException(herddb.log.FullRecoveryNeededException) LogEntry(herddb.log.LogEntry) LogSequenceNumber(herddb.log.LogSequenceNumber) IOException(java.io.IOException) BKNotEnoughBookiesException(org.apache.bookkeeper.client.BKException.BKNotEnoughBookiesException) LogNotAvailableException(herddb.log.LogNotAvailableException) IOException(java.io.IOException) CompletionException(java.util.concurrent.CompletionException) BKException(org.apache.bookkeeper.client.BKException) FullRecoveryNeededException(herddb.log.FullRecoveryNeededException) BKClientClosedException(org.apache.bookkeeper.client.BKException.BKClientClosedException) LedgerMetadata(org.apache.bookkeeper.client.api.LedgerMetadata) LedgerEntries(org.apache.bookkeeper.client.api.LedgerEntries) BKException(org.apache.bookkeeper.client.BKException) LogNotAvailableException(herddb.log.LogNotAvailableException)

Aggregations

LedgerEntries (org.apache.bookkeeper.client.api.LedgerEntries)6 ReadHandle (org.apache.bookkeeper.client.api.ReadHandle)5 IOException (java.io.IOException)4 BKException (org.apache.bookkeeper.client.BKException)4 FullRecoveryNeededException (herddb.log.FullRecoveryNeededException)2 LogEntry (herddb.log.LogEntry)2 LogNotAvailableException (herddb.log.LogNotAvailableException)2 LogSequenceNumber (herddb.log.LogSequenceNumber)2 DataPageDoesNotExistException (herddb.storage.DataPageDoesNotExistException)2 DataStorageManagerException (herddb.storage.DataStorageManagerException)2 CompletionException (java.util.concurrent.CompletionException)2 BKClientClosedException (org.apache.bookkeeper.client.BKException.BKClientClosedException)2 BKNoSuchLedgerExistsOnMetadataServerException (org.apache.bookkeeper.client.BKException.BKNoSuchLedgerExistsOnMetadataServerException)2 BKNotEnoughBookiesException (org.apache.bookkeeper.client.BKException.BKNotEnoughBookiesException)2 Record (herddb.model.Record)1 ByteBuf (io.netty.buffer.ByteBuf)1 LastConfirmedAndEntry (org.apache.bookkeeper.client.api.LastConfirmedAndEntry)1 LedgerEntry (org.apache.bookkeeper.client.api.LedgerEntry)1 LedgerMetadata (org.apache.bookkeeper.client.api.LedgerMetadata)1 ClientConfiguration (org.apache.bookkeeper.conf.ClientConfiguration)1