@Override public CompletableFuture<LedgerEntries> readAsync(long firstEntry, long lastEntry) { return readHandle.readAsync(firstEntry, lastEntry); }
@Override public CompletableFuture<Long> readLastAddConfirmedAsync() { return readHandle.readLastAddConfirmedAsync(); }
MockOffloadReadHandle(ReadHandle toCopy) throws Exception { id = toCopy.getId(); long lac = toCopy.getLastAddConfirmed(); try (LedgerEntries entries = toCopy.read(0, lac)) { for (LedgerEntry e : entries) { this.entries.add(e.getEntryBuffer().retainedSlice()); } } metadata = new MockMetadata(toCopy.getLedgerMetadata()); }
if (ledger.getId() == lastPosition.getLedgerId()) { } else { lastEntryInLedger = ledger.getLastAddConfirmed(); if (log.isDebugEnabled()) { log.debug("[{}] No more messages to read from ledger={} lastEntry={} readEntry={}", name, ledger.getId(), lastEntryInLedger, firstEntry); if (currentLedger == null || ledger.getId() != currentLedger.getId()) { Long nextLedgerId = ledgers.ceilingKey(ledger.getId() + 1); if (nextLedgerId != null) { opReadEntry.updateReadPosition(new PositionImpl(nextLedgerId, 0)); } else { opReadEntry.updateReadPosition(new PositionImpl(ledger.getId() + 1, 0)); log.debug("[{}] Reading entries from ledger {} - first={} last={}", name, ledger.getId(), firstEntry, lastEntry); final PositionImpl lastReadPosition = PositionImpl.get(ledger.getId(), lastEntry); discardEntriesFromCache(cursor, lastReadPosition);
@SuppressWarnings({ "unchecked", "rawtypes" }) private void asyncReadEntry0(ReadHandle 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); lh.readAsync(firstEntry, lastEntry).whenCompleteAsync( (ledgerEntries, exception) -> { if (exception != null) {
void invalidateLedgerHandle(ReadHandle ledgerHandle, Throwable t) { long ledgerId = ledgerHandle.getId(); if (currentLedger != null && ledgerId != currentLedger.getId()) { // remove handle from ledger cache since we got a (read) error ledgerCache.remove(ledgerId); if (log.isDebugEnabled()) { log.debug("[{}] Removed ledger {} from cache (after read error)", name, ledgerId, t); } } else { if (log.isDebugEnabled()) { log.debug("[{}] Ledger that encountered read error is current ledger", name, t); } } }
.withDigestType(config.getDigestType()).withPassword(config.getPassword()).execute() .thenAccept(readHandle -> { readHandle.readLastAddConfirmedAsync().thenAccept(lastAddConfirmed -> { LedgerInfo info = LedgerInfo.newBuilder().setLedgerId(lastLedgerId) .setEntries(lastAddConfirmed + 1).setSize(readHandle.getLength()) .setTimestamp(clock.millis()).build(); ledgers.put(lastLedgerId, info);
@Override public CompletableFuture<LastConfirmedAndEntry> readLastAddConfirmedAndEntryAsync(long entryId, long timeOutInMillis, boolean parallel) { return readHandle.readLastAddConfirmedAndEntryAsync(entryId, timeOutInMillis, parallel); }
@Override public CompletableFuture<LedgerEntries> readUnconfirmedAsync(long firstEntry, long lastEntry) { return readHandle.readUnconfirmedAsync(firstEntry, lastEntry); }
@Override public CompletableFuture<Long> tryReadLastAddConfirmedAsync() { return readHandle.tryReadLastAddConfirmedAsync(); }
@Test(timeOut = 5000) void testRead() throws Exception { ReadHandle lh = getLedgerHandle(); when(lh.getId()).thenReturn((long) 0); EntryCacheManager cacheManager = factory.getEntryCacheManager(); EntryCache entryCache = cacheManager.getEntryCache(ml); byte[] data = new byte[10]; for (int i = 0; i < 10; i++) { entryCache.insert(EntryImpl.create(0, i, data)); } final CountDownLatch counter = new CountDownLatch(1); entryCache.asyncReadEntry(lh, 0, 9, false, new ReadEntriesCallback() { public void readEntriesComplete(List<Entry> entries, Object ctx) { assertEquals(entries.size(), 10); entries.forEach(e -> e.release()); counter.countDown(); } public void readEntriesFailed(ManagedLedgerException exception, Object ctx) { Assert.fail("should not have failed"); } }, null); counter.await(); // Verify no entries were read from bookkeeper verify(lh, never()).readAsync(anyLong(), anyLong()); }
@Override public void asyncReadEntry(ReadHandle lh, long firstEntry, long lastEntry, boolean isSlowestReader, final ReadEntriesCallback callback, Object ctx) { try { asyncReadEntry0(lh, firstEntry, lastEntry, isSlowestReader, callback, ctx); } catch (Throwable t) { log.warn("failed to read entries for {}--{}-{}", lh.getId(), firstEntry, lastEntry, t); // invalidate all entries related to ledger from the cache (it might happen if entry gets corrupt // (entry.data is already deallocate due to any race-condition) so, invalidate cache and next time read from // the bookie) invalidateAllEntries(lh.getId()); callback.readEntriesFailed(createManagedLedgerException(t), ctx); } }
if (ledger.getId() == lastPosition.getLedgerId()) { } else { lastEntryInLedger = ledger.getLastAddConfirmed(); if (log.isDebugEnabled()) { log.debug("[{}] No more messages to read from ledger={} lastEntry={} readEntry={}", name, ledger.getId(), lastEntryInLedger, firstEntry); if (currentLedger == null || ledger.getId() != currentLedger.getId()) { Long nextLedgerId = ledgers.ceilingKey(ledger.getId() + 1); if (nextLedgerId != null) { opReadEntry.updateReadPosition(new PositionImpl(nextLedgerId, 0)); } else { opReadEntry.updateReadPosition(new PositionImpl(ledger.getId() + 1, 0)); log.debug("[{}] Reading entries from ledger {} - first={} last={}", name, ledger.getId(), firstEntry, lastEntry); final PositionImpl lastReadPosition = PositionImpl.get(ledger.getId(), lastEntry); discardEntriesFromCache(cursor, lastReadPosition);
.withDigestType(config.getDigestType()).withPassword(config.getPassword()).execute() .thenAccept(readHandle -> { readHandle.readLastAddConfirmedAsync().thenAccept(lastAddConfirmed -> { LedgerInfo info = LedgerInfo.newBuilder().setLedgerId(lastLedgerId) .setEntries(lastAddConfirmed + 1).setSize(readHandle.getLength()) .setTimestamp(clock.millis()).build(); ledgers.put(lastLedgerId, info);
/** * Asynchronous read specific entry and the latest last add confirmed. * * @param entryId * next entry id to read * @param timeOutInMillis * timeout period to wait for the entry id to be available (for long poll only) * if timeout for get the entry, it will return null entry. * @param parallel * whether to issue the long poll reads in parallel * @return the result of the operation * @see #readLastAddConfirmedAndEntry(long, long, boolean) */ default LastConfirmedAndEntry readLastAddConfirmedAndEntry(long entryId, long timeOutInMillis, boolean parallel) throws BKException, InterruptedException { return FutureUtils.<LastConfirmedAndEntry, BKException>result( readLastAddConfirmedAndEntryAsync(entryId, timeOutInMillis, parallel), BKException.HANDLER); }
/** * Read a sequence of entries synchronously. * * @param firstEntry * id of first entry of sequence * @param lastEntry * id of last entry of sequence, inclusive * @return an handle to the result of the operation * * @see #readUnconfirmedAsync(long, long) */ default LedgerEntries readUnconfirmed(long firstEntry, long lastEntry) throws BKException, InterruptedException { return FutureUtils.<LedgerEntries, BKException>result(readUnconfirmedAsync(firstEntry, lastEntry), BKException.HANDLER); }
/** * Obtains asynchronously the last confirmed write from a quorum of bookies * but it doesn't wait all the responses from the quorum. * * @return the result of the operation * @see #tryReadLastAddConfirmedAsync() */ default long tryReadLastAddConfirmed() throws BKException, InterruptedException { return FutureUtils.<Long, BKException>result(tryReadLastAddConfirmedAsync(), BKException.HANDLER); }
@Test(timeOut = 5000) void testReadWithError() throws Exception { final ReadHandle lh = getLedgerHandle(); when(lh.getId()).thenReturn((long) 0); doAnswer((invocation) -> { CompletableFuture<LedgerEntries> future = new CompletableFuture<>(); future.completeExceptionally(new BKNoSuchLedgerExistsException()); return future; }).when(lh).readAsync(anyLong(), anyLong()); EntryCacheManager cacheManager = factory.getEntryCacheManager(); EntryCache entryCache = cacheManager.getEntryCache(ml); byte[] data = new byte[10]; entryCache.insert(EntryImpl.create(0, 2, data)); final CountDownLatch counter = new CountDownLatch(1); entryCache.asyncReadEntry(lh, 0, 9, false, new ReadEntriesCallback() { public void readEntriesComplete(List<Entry> entries, Object ctx) { Assert.fail("should not complete"); } public void readEntriesFailed(ManagedLedgerException exception, Object ctx) { counter.countDown(); } }, null); counter.await(); }
@Override public void asyncReadEntry(ReadHandle lh, PositionImpl position, final ReadEntryCallback callback, final Object ctx) { try { asyncReadEntry0(lh, position, callback, ctx); } catch (Throwable t) { log.warn("failed to read entries for {}-{}", lh.getId(), position, t); // invalidate all entries related to ledger from the cache (it might happen if entry gets corrupt // (entry.data is already deallocate due to any race-condition) so, invalidate cache and next time read from // the bookie) invalidateAllEntries(lh.getId()); callback.readEntryFailed(createManagedLedgerException(t), ctx); } }
@Override public void asyncReadEntry(ReadHandle lh, long firstEntry, long lastEntry, boolean isSlowestReader, final ReadEntriesCallback callback, Object ctx) { lh.readAsync(firstEntry, lastEntry).whenComplete( (ledgerEntries, exception) -> { if (exception != null) { callback.readEntriesFailed(createManagedLedgerException(exception), ctx); return; } List<Entry> entries = Lists.newArrayList(); long totalSize = 0; try { for (LedgerEntry e : ledgerEntries) { // Insert the entries at the end of the list (they will be unsorted for now) EntryImpl entry = EntryImpl.create(e); entries.add(entry); totalSize += entry.getLength(); } } finally { ledgerEntries.close(); } mlFactoryMBean.recordCacheMiss(entries.size(), totalSize); ml.mbean.addReadEntriesSample(entries.size(), totalSize); callback.readEntriesComplete(entries, null); }); }