Search in sources :

Example 1 with ReadHandle

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

the class BookKeeperDataStorageManager method readIndexPage.

@Override
public <X> X readIndexPage(String tableSpace, String indexName, Long pageId, DataReader<X> reader) throws DataStorageManagerException {
    long _start = System.currentTimeMillis();
    TableSpacePagesMapping tableSpacePagesMapping = getTableSpacePagesMapping(tableSpace);
    Long ledgerId = tableSpacePagesMapping.getIndexPagesMapping(indexName).getLedgerIdForPage(pageId);
    if (ledgerId == null) {
        throw new DataPageDoesNotExistException("No such page for index : " + tableSpace + "_" + indexName + "." + pageId);
    }
    byte[] data;
    try (ReadHandle read = FutureUtils.result(bk.getBookKeeper().newOpenLedgerOp().withLedgerId(ledgerId).withPassword(EMPTY_ARRAY).execute(), BKException.HANDLER)) {
        try (LedgerEntries entries = read.readUnconfirmed(0, 0)) {
            data = entries.getEntry(0).getEntryBytes();
        }
        X result = readIndexPage(data, reader);
        long _stop = System.currentTimeMillis();
        long delta = _stop - _start;
        LOGGER.log(Level.FINE, "readIndexPage {0}.{1} {2} ms", new Object[] { tableSpace, indexName, delta + "" });
        indexPageReads.registerSuccessfulEvent(delta, TimeUnit.MILLISECONDS);
        return result;
    } catch (BKException.BKNoSuchLedgerExistsException err) {
        throw new DataStorageManagerException(err);
    } catch (BKException.BKNoSuchLedgerExistsOnMetadataServerException err) {
        throw new DataStorageManagerException(err);
    } catch (org.apache.bookkeeper.client.api.BKException err) {
        throw new DataStorageManagerException(err);
    } catch (IOException err) {
        throw new DataStorageManagerException(err);
    } catch (InterruptedException err) {
        Thread.currentThread().interrupt();
        throw new DataStorageManagerException(err);
    }
}
Also used : DataStorageManagerException(herddb.storage.DataStorageManagerException) IOException(java.io.IOException) DataPageDoesNotExistException(herddb.storage.DataPageDoesNotExistException) ReadHandle(org.apache.bookkeeper.client.api.ReadHandle) LedgerEntries(org.apache.bookkeeper.client.api.LedgerEntries) BKNoSuchLedgerExistsOnMetadataServerException(org.apache.bookkeeper.client.BKException.BKNoSuchLedgerExistsOnMetadataServerException) BKException(org.apache.bookkeeper.client.BKException)

Example 2 with ReadHandle

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

the class BookkeeperCommitLogManager method scanRawLedger.

public static void scanRawLedger(long ledgerId, long fromId, long toId, herddb.client.ClientConfiguration clientConfiguration, ZookeeperMetadataStorageManager metadataStorageManager, Consumer<LogEntryWithSequenceNumber> consumer) throws Exception {
    ClientConfiguration config = new ClientConfiguration();
    config.setZkServers(metadataStorageManager.getZkAddress());
    config.setZkTimeout(metadataStorageManager.getZkSessionTimeout());
    config.setZkLedgersRootPath(clientConfiguration.getString(ServerConfiguration.PROPERTY_BOOKKEEPER_LEDGERS_PATH, ServerConfiguration.PROPERTY_BOOKKEEPER_LEDGERS_PATH_DEFAULT));
    config.setEnableParallelRecoveryRead(true);
    config.setEnableDigestTypeAutodetection(true);
    try (org.apache.bookkeeper.client.api.BookKeeper bookKeeper = org.apache.bookkeeper.client.api.BookKeeper.newBuilder(config).build()) {
        try (ReadHandle lh = bookKeeper.newOpenLedgerOp().withRecovery(false).withLedgerId(ledgerId).withPassword(BookkeeperCommitLog.SHARED_SECRET.getBytes(StandardCharsets.UTF_8)).execute().get()) {
            long lastAddConfirmed = lh.readLastAddConfirmed();
            if (toId < 0) {
                toId = lastAddConfirmed;
            }
            LOG.log(Level.INFO, "Scanning Ledger {0} from {1} to {2} LAC {3}", new Object[] { ledgerId, fromId, toId, lastAddConfirmed });
            for (long id = fromId; id <= toId; id++) {
                try (LedgerEntries entries = lh.readUnconfirmed(id, id)) {
                    LedgerEntry entry = entries.getEntry(id);
                    LogEntry lEntry = LogEntry.deserialize(entry.getEntryBytes());
                    LogEntryWithSequenceNumber e = new LogEntryWithSequenceNumber(new LogSequenceNumber(ledgerId, id), lEntry);
                    consumer.accept(e);
                }
            }
        }
    }
}
Also used : ReadHandle(org.apache.bookkeeper.client.api.ReadHandle) LedgerEntries(org.apache.bookkeeper.client.api.LedgerEntries) LedgerEntry(org.apache.bookkeeper.client.api.LedgerEntry) LogSequenceNumber(herddb.log.LogSequenceNumber) ClientConfiguration(org.apache.bookkeeper.conf.ClientConfiguration) LogEntry(herddb.log.LogEntry)

Example 3 with ReadHandle

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

the class BookkeeperCommitLog method followTheLeader.

@Override
public void followTheLeader(LogSequenceNumber lastPosition, EntryAcceptor consumer, FollowerContext context) throws LogNotAvailableException {
    if (LOGGER.isLoggable(Level.FINER)) {
        LOGGER.finer(tableSpaceDescription() + " followTheLeader lastPosition:" + lastPosition);
    }
    BKFollowerContext fContext = (BKFollowerContext) context;
    try {
        fContext.ensureOpenReader(lastPosition);
        if (fContext.currentLedger == null) {
            // no data to read
            if (LOGGER.isLoggable(Level.FINER)) {
                LOGGER.finer(tableSpaceDescription() + " no more data to read for now");
            }
            return;
        }
        long nextEntry = fContext.nextEntryToRead;
        long lastAddConfirmed = fContext.currentLedger.getLastAddConfirmed();
        if (LOGGER.isLoggable(Level.FINER)) {
            LOGGER.finer(tableSpaceDescription() + " next entry to read " + nextEntry + " from ledger " + fContext.currentLedger.getId() + " lastAddConfiremd " + lastAddConfirmed);
        }
        if (lastAddConfirmed < nextEntry) {
            if (LOGGER.isLoggable(Level.FINER)) {
                LOGGER.finer(tableSpaceDescription() + " ledger not closed but there is nothing to read by now");
            }
            return;
        }
        ReadHandle lh = fContext.currentLedger;
        try (LastConfirmedAndEntry entryAndLac = lh.readLastAddConfirmedAndEntry(nextEntry, LONG_POLL_TIMEOUT, false)) {
            if (entryAndLac.hasEntry()) {
                org.apache.bookkeeper.client.api.LedgerEntry e = entryAndLac.getEntry();
                boolean canContinue = acceptEntryForFollower(e, consumer);
                if (!canContinue) {
                    LOGGER.log(Level.INFO, "exit follower {0}", tableSpaceDescription());
                    return;
                }
                long startEntry = nextEntry + 1;
                long endEntry = entryAndLac.getLastAddConfirmed();
                if (startEntry > endEntry) {
                    return;
                }
                // to be read then read them
                if (endEntry - startEntry > MAX_ENTRY_TO_TAIL) {
                    // put a bound on the max entries to read per round
                    endEntry = startEntry + MAX_ENTRY_TO_TAIL;
                }
                try (LedgerEntries entries = lh.read(startEntry, endEntry)) {
                    for (org.apache.bookkeeper.client.api.LedgerEntry ee : entries) {
                        acceptEntryForFollower(ee, consumer);
                    }
                }
            }
        }
    } catch (BKClientClosedException err) {
        LOGGER.log(Level.FINE, "stop following " + tableSpaceDescription(), err);
    } catch (org.apache.bookkeeper.client.api.BKException err) {
        LOGGER.log(Level.SEVERE, tableSpaceDescription() + " internal BK error", err);
        throw new LogNotAvailableException(err);
    } catch (InterruptedException err) {
        LOGGER.log(Level.SEVERE, tableSpaceDescription() + " interrupted", err);
        Thread.currentThread().interrupt();
        throw new LogNotAvailableException(err);
    } catch (LogNotAvailableException err) {
        LOGGER.log(Level.SEVERE, tableSpaceDescription() + " internal error", err);
        throw err;
    } catch (Exception err) {
        LOGGER.log(Level.SEVERE, tableSpaceDescription() + " internal error", err);
        throw new LogNotAvailableException(err);
    }
}
Also used : LastConfirmedAndEntry(org.apache.bookkeeper.client.api.LastConfirmedAndEntry) 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) ReadHandle(org.apache.bookkeeper.client.api.ReadHandle) LedgerEntries(org.apache.bookkeeper.client.api.LedgerEntries) BKClientClosedException(org.apache.bookkeeper.client.BKException.BKClientClosedException) LogNotAvailableException(herddb.log.LogNotAvailableException)

Example 4 with ReadHandle

use of org.apache.bookkeeper.client.api.ReadHandle in project pravega by pravega.

the class BookKeeperLogReconcileCommand method execute.

@Override
public void execute() throws Exception {
    ensureArgCount(1);
    int logId = getIntArg(0);
    // Ensure that the Bookkeeper log is disabled; abort otherwise.
    @Cleanup val context = createContext();
    @Cleanup val log = context.logFactory.createDebugLogWrapper(logId);
    // Display a summary of the BookKeeperLog.
    val m = log.fetchMetadata();
    outputLogSummary(logId, m);
    if (m == null || m.isEnabled()) {
        String message = (m == null) ? "BookKeeperLog '%s' does not exist." : "BookKeeperLog '%s' is enabled. Please, disable it before executing this command.";
        output(message, logId);
        return;
    }
    // Once the Bookkeeper log is disabled, list all ledgers from this log. This implies to query all the ledgers
    // in Bookkeeper and filter out the ones related to BookkeeperLog id passed by parameter.
    ClientConfiguration config = new ClientConfiguration().setMetadataServiceUri("zk://" + this.getServiceConfig().getZkURL() + context.bookKeeperConfig.getBkLedgerPath());
    @Cleanup BookKeeper bkClient = BookKeeper.forConfig(config).build();
    @Cleanup LedgerManager manager = bkClient.getLedgerManager();
    LedgerManager.LedgerRangeIterator ledgerRangeIterator = manager.getLedgerRanges(Long.MAX_VALUE);
    List<ReadHandle> candidateLedgers = new ArrayList<>();
    try {
        while (ledgerRangeIterator.hasNext()) {
            LedgerManager.LedgerRange lr = ledgerRangeIterator.next();
            for (long ledgerId : lr.getLedgers()) {
                ReadHandle readHandle = Ledgers.openRead(ledgerId, bkClient, context.bookKeeperConfig);
                if (Ledgers.getBookKeeperLogId(readHandle) == logId) {
                    candidateLedgers.add(readHandle);
                }
            }
        }
        // If there are no candidate ledgers, just return.
        if (candidateLedgers.isEmpty()) {
            output("No candidate ledgers to reconcile.");
            return;
        }
        // Confirm with user prior executing the command.
        output("Candidate ledgers for reconciliation: %s", candidateLedgers.stream().map(String::valueOf).collect(Collectors.joining(",")));
        output("BookKeeperLog '%s' reconciliation is about to be executed.", logId);
        if (!confirmContinue()) {
            output("Not reconciling anything at this time.");
            return;
        }
        // Executing BookkeeperLog reconciliation.
        output("BookKeeperLog '%s': starting ledger reconciliation.", logId);
        log.reconcileLedgers(candidateLedgers);
        output("BookKeeperLog '%s': ledger reconciliation completed.", logId);
    } finally {
        // Closing opened ledgers.
        closeBookkeeperReadHandles(candidateLedgers);
    }
}
Also used : lombok.val(lombok.val) LedgerManager(org.apache.bookkeeper.meta.LedgerManager) ArrayList(java.util.ArrayList) BookKeeper(org.apache.bookkeeper.client.BookKeeper) Cleanup(lombok.Cleanup) ReadHandle(org.apache.bookkeeper.client.api.ReadHandle) ClientConfiguration(org.apache.bookkeeper.conf.ClientConfiguration)

Example 5 with ReadHandle

use of org.apache.bookkeeper.client.api.ReadHandle in project pravega by pravega.

the class DebugBookKeeperLogWrapper method reconcileLedgers.

/**
 * Performs a {@link BookKeeperLog}-{@link LedgerHandle} reconciliation for this {@link BookKeeperLog} subject to the
 * following rules:
 * - Any {@link LedgerHandle}s that list this {@link BookKeeperLog} as their owner will be added to this {@link BookKeeperLog}'s
 * list of ledgers (if they're non-empty and haven't been truncated out).
 * - Any {@link LedgerMetadata} instances in this {@link BookKeeperLog} that point to inexistent {@link LedgerHandle}s
 * will be removed.
 *
 * @param candidateLedgers A List of {@link LedgerHandle}s that contain all the Ledgers that this {@link BookKeeperLog}
 *                         should contain. This could be the list of all BookKeeper Ledgers or a subset, as long as
 *                         it contains all Ledgers that list this {@link BookKeeperLog} as their owner.
 * @return True if something changed (and the metadata is updated), false otherwise.
 * @throws IllegalStateException   If this BookKeeperLog is not disabled.
 * @throws DurableDataLogException If an exception occurred while updating the metadata.
 */
public boolean reconcileLedgers(List<? extends ReadHandle> candidateLedgers) throws DurableDataLogException {
    // Load metadata and verify if disabled (metadata may be null if it doesn't exist).
    LogMetadata metadata = this.log.loadMetadata();
    final long highestLedgerId;
    if (metadata != null) {
        Preconditions.checkState(!metadata.isEnabled(), "BookKeeperLog is enabled; cannot reconcile ledgers.");
        int ledgerCount = metadata.getLedgers().size();
        if (ledgerCount > 0) {
            // Get the highest Ledger id from the list of ledgers.
            highestLedgerId = metadata.getLedgers().get(ledgerCount - 1).getLedgerId();
        } else if (metadata.getTruncationAddress() != null) {
            // All Ledgers have been truncated out. Get it from the Truncation Address.
            highestLedgerId = metadata.getTruncationAddress().getLedgerId();
        } else {
            // No information.
            highestLedgerId = Ledgers.NO_LEDGER_ID;
        }
    } else {
        // No metadata.
        highestLedgerId = Ledgers.NO_LEDGER_ID;
    }
    // First, we filter out any Ledger that does not reference this Log as their owner or that are empty.
    candidateLedgers = candidateLedgers.stream().filter(lh -> Ledgers.getBookKeeperLogId(lh) == this.log.getLogId() && lh.getLength() > 0).collect(Collectors.toList());
    // Begin reconstructing the Ledger List by eliminating references to inexistent ledgers.
    val newLedgerList = new ArrayList<LedgerMetadata>();
    if (metadata != null) {
        val candidateLedgerIds = candidateLedgers.stream().map(Handle::getId).collect(Collectors.toSet());
        metadata.getLedgers().stream().filter(lm -> candidateLedgerIds.contains(lm.getLedgerId())).forEach(newLedgerList::add);
    }
    // Find ledgers that should be in the log but are not referenced. Only select ledgers which have their Id greater
    // than the Id of the last ledger used in this Log (Id are assigned monotonically increasing, and we don't want
    // to add already truncated out ledgers).
    val seq = new AtomicInteger(newLedgerList.isEmpty() ? 0 : newLedgerList.get(newLedgerList.size() - 1).getSequence());
    candidateLedgers.stream().filter(lh -> lh.getId() > highestLedgerId).forEach(lh -> newLedgerList.add(new LedgerMetadata(lh.getId(), seq.incrementAndGet())));
    // Make sure the ledgers are properly sorted.
    newLedgerList.sort(Comparator.comparingLong(LedgerMetadata::getLedgerId));
    // Determine if anything changed.
    boolean changed = metadata == null || metadata.getLedgers().size() != newLedgerList.size();
    if (!changed) {
        for (int i = 0; i < newLedgerList.size(); i++) {
            if (metadata.getLedgers().get(i).getLedgerId() != newLedgerList.get(i).getLedgerId()) {
                changed = true;
                break;
            }
        }
    }
    // Update metadata in ZooKeeper, but only if it has changed.
    if (changed) {
        val newMetadata = LogMetadata.builder().enabled(false).epoch(getOrDefault(metadata, LogMetadata::getEpoch, LogMetadata.INITIAL_EPOCH) + 1).truncationAddress(getOrDefault(metadata, LogMetadata::getTruncationAddress, LogMetadata.INITIAL_TRUNCATION_ADDRESS)).updateVersion(getOrDefault(metadata, LogMetadata::getUpdateVersion, LogMetadata.INITIAL_VERSION)).ledgers(newLedgerList).build();
        this.log.overWriteMetadata(newMetadata);
    }
    return changed;
}
Also used : lombok.val(lombok.val) ThrottleSourceListener(io.pravega.segmentstore.storage.ThrottleSourceListener) RequiredArgsConstructor(lombok.RequiredArgsConstructor) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) LogAddress(io.pravega.segmentstore.storage.LogAddress) Function(java.util.function.Function) ArrayList(java.util.ArrayList) AccessLevel(lombok.AccessLevel) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Duration(java.time.Duration) DataLogInitializationException(io.pravega.segmentstore.storage.DataLogInitializationException) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) DurableDataLogException(io.pravega.segmentstore.storage.DurableDataLogException) BookKeeper(org.apache.bookkeeper.client.api.BookKeeper) DebugDurableDataLogWrapper(io.pravega.segmentstore.storage.DebugDurableDataLogWrapper) LedgerHandle(org.apache.bookkeeper.client.LedgerHandle) CloseableIterator(io.pravega.common.util.CloseableIterator) Handle(org.apache.bookkeeper.client.api.Handle) DurableDataLog(io.pravega.segmentstore.storage.DurableDataLog) lombok.val(lombok.val) ReadOnlyLogMetadata(io.pravega.segmentstore.storage.ReadOnlyLogMetadata) Collectors(java.util.stream.Collectors) ReadHandle(org.apache.bookkeeper.client.api.ReadHandle) List(java.util.List) CuratorFramework(org.apache.curator.framework.CuratorFramework) QueueStats(io.pravega.segmentstore.storage.QueueStats) Preconditions(com.google.common.base.Preconditions) Comparator(java.util.Comparator) WriteSettings(io.pravega.segmentstore.storage.WriteSettings) CompositeArrayView(io.pravega.common.util.CompositeArrayView) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ArrayList(java.util.ArrayList) ReadOnlyLogMetadata(io.pravega.segmentstore.storage.ReadOnlyLogMetadata)

Aggregations

ReadHandle (org.apache.bookkeeper.client.api.ReadHandle)10 lombok.val (lombok.val)5 LedgerEntries (org.apache.bookkeeper.client.api.LedgerEntries)5 IOException (java.io.IOException)4 BKException (org.apache.bookkeeper.client.BKException)4 DurableDataLogException (io.pravega.segmentstore.storage.DurableDataLogException)3 ArrayList (java.util.ArrayList)3 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 Cleanup (lombok.Cleanup)2 ClientConfiguration (org.apache.bookkeeper.conf.ClientConfiguration)2 Preconditions (com.google.common.base.Preconditions)1 Record (herddb.model.Record)1 CloseableIterator (io.pravega.common.util.CloseableIterator)1 CompositeArrayView (io.pravega.common.util.CompositeArrayView)1