Search in sources :

Example 46 with LedgerEntry

use of org.apache.bookkeeper.client.LedgerEntry in project incubator-pulsar by apache.

the class ManagedLedgerOfflineBacklog method tryGetMDPosition.

private PositionImpl tryGetMDPosition(BookKeeper bookKeeper, long ledgerId, String cursorName) {
    BookKeeperAdmin bookKeeperAdmin = null;
    long lastEntry = LedgerHandle.INVALID_ENTRY_ID;
    PositionImpl lastAckedMessagePosition = null;
    try {
        bookKeeperAdmin = new BookKeeperAdmin(bookKeeper);
        Iterator<LedgerEntry> entries = bookKeeperAdmin.readEntries(ledgerId, 0, lastEntry).iterator();
        while (entries.hasNext()) {
            LedgerEntry ledgerEntry = entries.next();
            lastEntry = ledgerEntry.getEntryId();
            if (log.isDebugEnabled()) {
                log.debug(" Read entry {} from ledger {} for cursor {}", lastEntry, ledgerId, cursorName);
            }
            MLDataFormats.PositionInfo positionInfo = MLDataFormats.PositionInfo.parseFrom(ledgerEntry.getEntry());
            lastAckedMessagePosition = new PositionImpl(positionInfo);
            if (log.isDebugEnabled()) {
                log.debug("Cursor {} read position {}", cursorName, lastAckedMessagePosition);
            }
        }
    } catch (Exception e) {
        log.warn("Unable to determine LAC for ledgerId {} for cursor {}: {}", ledgerId, cursorName, e);
    } finally {
        if (bookKeeperAdmin != null) {
            try {
                bookKeeperAdmin.close();
            } catch (Exception e) {
                log.warn("Unable to close bk admin for ledgerId {} for cursor {}", ledgerId, cursorName, e);
            }
        }
    }
    return lastAckedMessagePosition;
}
Also used : MLDataFormats(org.apache.bookkeeper.mledger.proto.MLDataFormats) LedgerEntry(org.apache.bookkeeper.client.LedgerEntry) BookKeeperAdmin(org.apache.bookkeeper.client.BookKeeperAdmin) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) BKException(org.apache.bookkeeper.client.BKException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException)

Example 47 with LedgerEntry

use of org.apache.bookkeeper.client.LedgerEntry in project incubator-pulsar by apache.

the class ManagedCursorTest method testOutOfOrderDeletePersistenceIntoLedgerWithClose.

/**
 * Verifies cursor persists individually unack range into cursor-ledger if range count is higher than
 * MaxUnackedRangesToPersistInZk
 *
 * @throws Exception
 */
@Test(timeOut = 20000)
public void testOutOfOrderDeletePersistenceIntoLedgerWithClose() throws Exception {
    final int totalAddEntries = 100;
    String ledgerName = "my_test_ledger";
    String cursorName = "c1";
    ManagedLedgerConfig managedLedgerConfig = new ManagedLedgerConfig();
    // metaStore is allowed to store only up to 10 deleted entries range
    managedLedgerConfig.setMaxUnackedRangesToPersistInZk(10);
    ManagedLedgerImpl ledger = (ManagedLedgerImpl) factory.open(ledgerName, managedLedgerConfig);
    ManagedCursorImpl c1 = (ManagedCursorImpl) ledger.openCursor(cursorName);
    List<Position> addedPositions = new ArrayList<>();
    for (int i = 0; i < totalAddEntries; i++) {
        Position p = ledger.addEntry(("dummy-entry-" + i).getBytes(Encoding));
        addedPositions.add(p);
        if (i % 2 == 0) {
            // Acknowledge alternative message to create totalEntries/2 holes
            c1.delete(addedPositions.get(i));
        }
    }
    assertEquals(c1.getNumberOfEntriesInBacklog(), totalAddEntries / 2);
    // Close ledger to persist individual-deleted positions into cursor-ledger
    ledger.close();
    // verify cursor-ledgerId is updated properly into cursor-metaStore
    CountDownLatch cursorLedgerLatch = new CountDownLatch(1);
    AtomicLong cursorLedgerId = new AtomicLong(0);
    ledger.getStore().asyncGetCursorInfo(ledger.getName(), cursorName, new MetaStoreCallback<ManagedCursorInfo>() {

        @Override
        public void operationComplete(ManagedCursorInfo result, Stat stat) {
            cursorLedgerId.set(result.getCursorsLedgerId());
            cursorLedgerLatch.countDown();
        }

        @Override
        public void operationFailed(MetaStoreException e) {
            cursorLedgerLatch.countDown();
        }
    });
    cursorLedgerLatch.await();
    assertEquals(cursorLedgerId.get(), c1.getCursorLedger());
    // verify cursor-ledger's last entry has individual-deleted positions
    final CountDownLatch latch = new CountDownLatch(1);
    final AtomicInteger individualDeletedMessagesCount = new AtomicInteger(0);
    bkc.asyncOpenLedger(c1.getCursorLedger(), DigestType.CRC32C, "".getBytes(), (rc, lh, ctx) -> {
        if (rc == BKException.Code.OK) {
            long lastEntry = lh.getLastAddConfirmed();
            lh.asyncReadEntries(lastEntry, lastEntry, (rc1, lh1, seq, ctx1) -> {
                try {
                    LedgerEntry entry = seq.nextElement();
                    PositionInfo positionInfo;
                    positionInfo = PositionInfo.parseFrom(entry.getEntry());
                    individualDeletedMessagesCount.set(positionInfo.getIndividualDeletedMessagesCount());
                } catch (Exception e) {
                }
                latch.countDown();
            }, null);
        } else {
            latch.countDown();
        }
    }, null);
    latch.await();
    assertEquals(individualDeletedMessagesCount.get(), totalAddEntries / 2 - 1);
    // Re-Open
    factory = new ManagedLedgerFactoryImpl(bkc, bkc.getZkHandle());
    ledger = (ManagedLedgerImpl) factory.open(ledgerName, managedLedgerConfig);
    c1 = (ManagedCursorImpl) ledger.openCursor("c1");
    // verify cursor has been recovered
    assertEquals(c1.getNumberOfEntriesInBacklog(), totalAddEntries / 2);
    // try to read entries which should only read non-deleted positions
    List<Entry> entries = c1.readEntries(totalAddEntries);
    assertEquals(entries.size(), totalAddEntries / 2);
}
Also used : Position(org.apache.bookkeeper.mledger.Position) ArrayList(java.util.ArrayList) CountDownLatch(java.util.concurrent.CountDownLatch) BKException(org.apache.bookkeeper.client.BKException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) MetaStoreException(org.apache.bookkeeper.mledger.ManagedLedgerException.MetaStoreException) MetaStoreException(org.apache.bookkeeper.mledger.ManagedLedgerException.MetaStoreException) AtomicLong(java.util.concurrent.atomic.AtomicLong) Entry(org.apache.bookkeeper.mledger.Entry) LedgerEntry(org.apache.bookkeeper.client.LedgerEntry) Stat(org.apache.bookkeeper.mledger.impl.MetaStore.Stat) ManagedCursorInfo(org.apache.bookkeeper.mledger.proto.MLDataFormats.ManagedCursorInfo) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) LedgerEntry(org.apache.bookkeeper.client.LedgerEntry) PositionInfo(org.apache.bookkeeper.mledger.proto.MLDataFormats.PositionInfo) ManagedLedgerConfig(org.apache.bookkeeper.mledger.ManagedLedgerConfig) Test(org.testng.annotations.Test)

Example 48 with LedgerEntry

use of org.apache.bookkeeper.client.LedgerEntry in project incubator-pulsar by apache.

the class EntryCacheImpl method asyncReadEntry.

@Override
public void asyncReadEntry(LedgerHandle lh, PositionImpl position, final ReadEntryCallback callback, final Object ctx) {
    if (log.isDebugEnabled()) {
        log.debug("[{}] Reading entry ledger {}: {}", ml.getName(), lh.getId(), position.getEntryId());
    }
    EntryImpl entry = entries.get(position);
    if (entry != null) {
        EntryImpl cachedEntry = EntryImpl.create(entry);
        entry.release();
        manager.mlFactoryMBean.recordCacheHit(cachedEntry.getLength());
        callback.readEntryComplete(cachedEntry, ctx);
    } else {
        lh.asyncReadEntries(position.getEntryId(), position.getEntryId(), (rc, ledgerHandle, sequence, obj) -> {
            if (rc != BKException.Code.OK) {
                ml.invalidateLedgerHandle(ledgerHandle, rc);
                callback.readEntryFailed(createManagedLedgerException(rc), obj);
                return;
            }
            if (sequence.hasMoreElements()) {
                LedgerEntry ledgerEntry = sequence.nextElement();
                EntryImpl returnEntry = EntryImpl.create(ledgerEntry);
                // The EntryImpl is now the owner of the buffer, so we can release the original one
                ledgerEntry.getEntryBuffer().release();
                manager.mlFactoryMBean.recordCacheMiss(1, returnEntry.getLength());
                ml.mbean.addReadEntriesSample(1, returnEntry.getLength());
                ml.getExecutor().submitOrdered(ml.getName(), safeRun(() -> {
                    callback.readEntryComplete(returnEntry, obj);
                }));
            } else {
                // got an empty sequence
                callback.readEntryFailed(new ManagedLedgerException("Could not read given position"), obj);
            }
        }, ctx);
    }
}
Also used : ManagedLedgerImpl.createManagedLedgerException(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.createManagedLedgerException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) LedgerEntry(org.apache.bookkeeper.client.LedgerEntry)

Example 49 with LedgerEntry

use of org.apache.bookkeeper.client.LedgerEntry in project incubator-pulsar by apache.

the class EntryCacheImpl method asyncReadEntry.

@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void asyncReadEntry(LedgerHandle lh, long firstEntry, long lastEntry, boolean isSlowestReader, final ReadEntriesCallback callback, Object ctx) {
    final long ledgerId = lh.getId();
    final int entriesToRead = (int) (lastEntry - firstEntry) + 1;
    final PositionImpl firstPosition = PositionImpl.get(lh.getId(), firstEntry);
    final PositionImpl lastPosition = PositionImpl.get(lh.getId(), lastEntry);
    if (log.isDebugEnabled()) {
        log.debug("[{}] Reading entries range ledger {}: {} to {}", ml.getName(), ledgerId, firstEntry, lastEntry);
    }
    Collection<EntryImpl> cachedEntries = entries.getRange(firstPosition, lastPosition);
    if (cachedEntries.size() == entriesToRead) {
        long totalCachedSize = 0;
        final List<EntryImpl> entriesToReturn = Lists.newArrayListWithExpectedSize(entriesToRead);
        // All entries found in cache
        for (EntryImpl entry : cachedEntries) {
            entriesToReturn.add(EntryImpl.create(entry));
            totalCachedSize += entry.getLength();
            entry.release();
        }
        manager.mlFactoryMBean.recordCacheHits(entriesToReturn.size(), totalCachedSize);
        if (log.isDebugEnabled()) {
            log.debug("[{}] Ledger {} -- Found in cache entries: {}-{}", ml.getName(), ledgerId, firstEntry, lastEntry);
        }
        callback.readEntriesComplete((List) entriesToReturn, ctx);
    } else {
        if (!cachedEntries.isEmpty()) {
            cachedEntries.forEach(entry -> entry.release());
        }
        // Read all the entries from bookkeeper
        lh.asyncReadEntries(firstEntry, lastEntry, (rc, lh1, sequence, cb) -> {
            if (rc != BKException.Code.OK) {
                if (rc == BKException.Code.TooManyRequestsException) {
                    callback.readEntriesFailed(createManagedLedgerException(rc), ctx);
                } else {
                    ml.invalidateLedgerHandle(lh1, rc);
                    ManagedLedgerException mlException = createManagedLedgerException(rc);
                    callback.readEntriesFailed(mlException, ctx);
                }
                return;
            }
            checkNotNull(ml.getName());
            checkNotNull(ml.getExecutor());
            ml.getExecutor().submitOrdered(ml.getName(), safeRun(() -> {
                // We got the entries, we need to transform them to a List<> type
                long totalSize = 0;
                final List<EntryImpl> entriesToReturn = Lists.newArrayListWithExpectedSize(entriesToRead);
                while (sequence.hasMoreElements()) {
                    // Insert the entries at the end of the list (they will be unsorted for now)
                    LedgerEntry ledgerEntry = sequence.nextElement();
                    EntryImpl entry = EntryImpl.create(ledgerEntry);
                    ledgerEntry.getEntryBuffer().release();
                    entriesToReturn.add(entry);
                    totalSize += entry.getLength();
                }
                manager.mlFactoryMBean.recordCacheMiss(entriesToReturn.size(), totalSize);
                ml.getMBean().addReadEntriesSample(entriesToReturn.size(), totalSize);
                callback.readEntriesComplete((List) entriesToReturn, ctx);
            }));
        }, callback);
    }
}
Also used : ManagedLedgerImpl.createManagedLedgerException(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.createManagedLedgerException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) LedgerEntry(org.apache.bookkeeper.client.LedgerEntry) List(java.util.List)

Example 50 with LedgerEntry

use of org.apache.bookkeeper.client.LedgerEntry in project incubator-pulsar by apache.

the class ManagedCursorImpl method recoverFromLedger.

protected void recoverFromLedger(final ManagedCursorInfo info, final VoidCallback callback) {
    // Read the acknowledged position from the metadata ledger, then create
    // a new ledger and write the position into it
    ledger.mbean.startCursorLedgerOpenOp();
    long ledgerId = info.getCursorsLedgerId();
    bookkeeper.asyncOpenLedger(ledgerId, config.getDigestType(), config.getPassword(), (rc, lh, ctx) -> {
        if (log.isDebugEnabled()) {
            log.debug("[{}] Opened ledger {} for consumer {}. rc={}", ledger.getName(), ledgerId, name, rc);
        }
        if (isBkErrorNotRecoverable(rc)) {
            log.error("[{}] Error opening metadata ledger {} for consumer {}: {}", ledger.getName(), ledgerId, name, BKException.getMessage(rc));
            // Rewind to oldest entry available
            initialize(getRollbackPosition(info), callback);
            return;
        } else if (rc != BKException.Code.OK) {
            log.warn("[{}] Error opening metadata ledger {} for consumer {}: {}", ledger.getName(), ledgerId, name, BKException.getMessage(rc));
            callback.operationFailed(new ManagedLedgerException(BKException.getMessage(rc)));
            return;
        }
        // Read the last entry in the ledger
        long lastEntryInLedger = lh.getLastAddConfirmed();
        lh.asyncReadEntries(lastEntryInLedger, lastEntryInLedger, (rc1, lh1, seq, ctx1) -> {
            if (log.isDebugEnabled()) {
                log.debug("[{}} readComplete rc={} entryId={}", ledger.getName(), rc1, lh1.getLastAddConfirmed());
            }
            if (isBkErrorNotRecoverable(rc1)) {
                log.error("[{}] Error reading from metadata ledger {} for consumer {}: {}", ledger.getName(), ledgerId, name, BKException.getMessage(rc1));
                // Rewind to oldest entry available
                initialize(getRollbackPosition(info), callback);
                return;
            } else if (rc1 != BKException.Code.OK) {
                log.warn("[{}] Error reading from metadata ledger {} for consumer {}: {}", ledger.getName(), ledgerId, name, BKException.getMessage(rc1));
                callback.operationFailed(createManagedLedgerException(rc1));
                return;
            }
            LedgerEntry entry = seq.nextElement();
            PositionInfo positionInfo;
            try {
                positionInfo = PositionInfo.parseFrom(entry.getEntry());
            } catch (InvalidProtocolBufferException e) {
                callback.operationFailed(new ManagedLedgerException(e));
                return;
            }
            Map<String, Long> recoveredProperties = Collections.emptyMap();
            if (positionInfo.getPropertiesCount() > 0) {
                // Recover properties map
                recoveredProperties = Maps.newHashMap();
                for (int i = 0; i < positionInfo.getPropertiesCount(); i++) {
                    LongProperty property = positionInfo.getProperties(i);
                    recoveredProperties.put(property.getName(), property.getValue());
                }
            }
            PositionImpl position = new PositionImpl(positionInfo);
            if (positionInfo.getIndividualDeletedMessagesCount() > 0) {
                recoverIndividualDeletedMessages(positionInfo.getIndividualDeletedMessagesList());
            }
            recoveredCursor(position, recoveredProperties, lh);
            callback.operationComplete();
        }, null);
    }, null);
}
Also used : ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) ManagedLedgerException.getManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException.getManagedLedgerException) ManagedLedgerImpl.createManagedLedgerException(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.createManagedLedgerException) LongProperty(org.apache.bookkeeper.mledger.proto.MLDataFormats.LongProperty) LedgerEntry(org.apache.bookkeeper.client.LedgerEntry) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) PositionInfo(org.apache.bookkeeper.mledger.proto.MLDataFormats.PositionInfo)

Aggregations

LedgerEntry (org.apache.bookkeeper.client.LedgerEntry)53 LedgerHandle (org.apache.bookkeeper.client.LedgerHandle)37 BKException (org.apache.bookkeeper.client.BKException)20 Test (org.junit.Test)20 BookKeeper (org.apache.bookkeeper.client.BookKeeper)10 ManagedLedgerException (org.apache.bookkeeper.mledger.ManagedLedgerException)9 IOException (java.io.IOException)8 ByteBuffer (java.nio.ByteBuffer)7 InvalidProtocolBufferException (com.google.protobuf.InvalidProtocolBufferException)6 File (java.io.File)5 ArrayList (java.util.ArrayList)5 List (java.util.List)5 CountDownLatch (java.util.concurrent.CountDownLatch)5 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)5 Bookie (org.apache.bookkeeper.bookie.Bookie)4 LedgerDirsManager (org.apache.bookkeeper.bookie.LedgerDirsManager)4 MLDataFormats (org.apache.bookkeeper.mledger.proto.MLDataFormats)4 ServerConfiguration (org.apache.bookkeeper.conf.ServerConfiguration)3 ManagedLedgerImpl.createManagedLedgerException (org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.createManagedLedgerException)3 Versioned (org.apache.bookkeeper.versioning.Versioned)3