@BeforeMethod public void setUp(Method method) throws Exception { super.setUp(method); ml = mock(ManagedLedgerImpl.class); when(ml.getName()).thenReturn("name"); when(ml.getExecutor()).thenReturn(executor); when(ml.getMBean()).thenReturn(new ManagedLedgerMBeanImpl(ml)); }
/** * It handles add failure on the given ledger. it can be triggered when add-entry fails or times out. * * @param ledger */ void handleAddFailure(final LedgerHandle ledger) { // If we get a write error, we will try to create a new ledger and re-submit the pending writes. If the // ledger creation fails (persistent bk failure, another instanche owning the ML, ...), then the writes will // be marked as failed. ml.mbean.recordAddEntryError(); ml.getExecutor().executeOrdered(ml.getName(), SafeRun.safeRun(() -> { // Force the creation of a new ledger. Doing it in a background thread to avoid acquiring ML lock // from a BK callback. ml.ledgerClosed(ledger); })); }
@Override public void addComplete(int rc, final LedgerHandle lh, long entryId, Object ctx) { if (ledger.getId() != lh.getId()) { log.warn("[{}] ledgerId {} doesn't match with acked ledgerId {}", ml.getName(), ledger.getId(), lh.getId()); } checkArgument(ledger.getId() == lh.getId(), "ledgerId %s doesn't match with acked ledgerId %s", ledger.getId(), lh.getId()); checkArgument(this.ctx == ctx); this.entryId = entryId; if (log.isDebugEnabled()) { log.debug("[{}] [{}] write-complete: ledger-id={} entry-id={} size={} rc={}", this, ml.getName(), lh.getId(), entryId, dataLength, rc); } if (rc != BKException.Code.OK) { handleAddFailure(lh); } else { if(!checkAndCompleteTimeoutTask()) { return; } // Trigger addComplete callback in a thread hashed on the managed ledger name ml.getExecutor().executeOrdered(ml.getName(), this); } }
void checkReadCompletion() { if (entries.size() < count && cursor.hasMoreEntries()) { // We still have more entries to read from the next ledger, schedule a new async operation if (nextReadPosition.getLedgerId() != readPosition.getLedgerId()) { cursor.ledger.startReadOperationOnLedger(nextReadPosition); } // Schedule next read in a different thread cursor.ledger.getExecutor().execute(safeRun(() -> { readPosition = cursor.ledger.startReadOperationOnLedger(nextReadPosition); cursor.ledger.asyncReadEntries(OpReadEntry.this); })); } else { // The reading was already completed, release resources and trigger callback try { cursor.readOperationCompleted(); } finally { cursor.ledger.getExecutor().executeOrdered(cursor.ledger.getName(), safeRun(() -> { callback.readEntriesComplete(entries, ctx); recycle(); })); } } }
checkNotNull(ml.getExecutor()); ledgerEntries.close(); }, ml.getExecutor().chooseThread(ml.getName()));
@Override public void asyncResetCursor(Position newPos, AsyncCallbacks.ResetCursorCallback callback) { checkArgument(newPos instanceof PositionImpl); final PositionImpl newPosition = (PositionImpl) newPos; // order trim and reset operations on a ledger ledger.getExecutor().executeOrdered(ledger.getName(), safeRun(() -> { if (ledger.isValidPosition(newPosition) || newPosition.equals(PositionImpl.earliest) || newPosition.equals(PositionImpl.latest)) { internalResetCursor(newPosition, callback); } else { // caller (replay) should handle this error and retry cursor reset callback.resetFailed(new ManagedLedgerException.InvalidCursorPositionException(newPosition.toString()), newPosition); } })); }
ledger.getExecutor().execute(safeRun(() -> { ledger.mbean.endCursorLedgerCreateOp(); if (rc != BKException.Code.OK) {
cursor.ledger.getExecutor().execute(safeRun(() -> { callback.readEntriesComplete(entries, ctx); recycle();
ledgerEntries.close(); }, ml.getExecutor().chooseThread(ml.getName()));
@Override public void addComplete(int rc, final LedgerHandle lh, long entryId, Object ctx) { checkArgument(ledger.getId() == lh.getId()); checkArgument(this.ctx == ctx); this.entryId = entryId; if (log.isDebugEnabled()) { log.debug("[{}] [{}] write-complete: ledger-id={} entry-id={} size={} rc={}", this, ml.getName(), lh.getId(), entryId, dataLength, rc); } if (rc != BKException.Code.OK) { // If we get a write error, we will try to create a new ledger and re-submit the pending writes. If the // ledger creation fails (persistent bk failure, another instanche owning the ML, ...), then the writes will // be marked as failed. ml.mbean.recordAddEntryError(); ml.getExecutor().submitOrdered(ml.getName(), SafeRun.safeRun(() -> { // Force the creation of a new ledger. Doing it in a background thread to avoid acquiring ML lock // from a BK callback. ml.ledgerClosed(lh); })); } else { // Trigger addComplete callback in a thread hashed on the managed ledger name ml.getExecutor().submitOrdered(ml.getName(), this); } }
@Override public void asyncResetCursor(Position newPos, AsyncCallbacks.ResetCursorCallback callback) { checkArgument(newPos instanceof PositionImpl); final PositionImpl newPosition = (PositionImpl) newPos; // order trim and reset operations on a ledger ledger.getExecutor().submitOrdered(ledger.getName(), safeRun(() -> { if (ledger.isValidPosition(newPosition)) { internalResetCursor(newPosition, callback); } else { // caller (replay) should handle this error and retry cursor reset callback.resetFailed(new ManagedLedgerException.InvalidCursorPositionException(newPosition.toString()), newPosition); } })); }
void asyncDeleteLedger(final LedgerHandle lh) { if (lh == null) { return; } ledger.mbean.startCursorLedgerDeleteOp(); bookkeeper.asyncDeleteLedger(lh.getId(), (rc, ctx) -> { ledger.getExecutor().submit(safeRun(() -> { ledger.mbean.endCursorLedgerDeleteOp(); if (rc != BKException.Code.OK) { log.warn("[{}] Failed to delete ledger {}: {}", ledger.getName(), lh.getId(), BKException.getMessage(rc)); return; } else { if (log.isDebugEnabled()) { log.debug("[{}][{}] Successfully closed&deleted ledger {} in cursor", ledger.getName(), name, lh.getId()); } } })); }, null); }
void checkReadCompletion() { if (entries.size() < count && cursor.hasMoreEntries()) { // We still have more entries to read from the next ledger, schedule a new async operation if (nextReadPosition.getLedgerId() != readPosition.getLedgerId()) { cursor.ledger.startReadOperationOnLedger(nextReadPosition); } // Schedule next read in a different thread cursor.ledger.getExecutor().submit(safeRun(() -> { readPosition = cursor.ledger.startReadOperationOnLedger(nextReadPosition); cursor.ledger.asyncReadEntries(OpReadEntry.this); })); } else { // The reading was already completed, release resources and trigger callback cursor.readOperationCompleted(); cursor.ledger.getExecutor().submit(safeRun(() -> { callback.readEntriesComplete(entries, ctx); recycle(); })); } }
@Override public void addComplete(int rc, final LedgerHandle lh, long entryId, Object ctx) { if (ledger.getId() != lh.getId()) { log.warn("[{}] ledgerId {} doesn't match with acked ledgerId {}", ml.getName(), ledger.getId(), lh.getId()); } checkArgument(ledger.getId() == lh.getId(), "ledgerId %s doesn't match with acked ledgerId %s", ledger.getId(), lh.getId()); checkArgument(this.ctx == ctx); this.entryId = entryId; if (log.isDebugEnabled()) { log.debug("[{}] [{}] write-complete: ledger-id={} entry-id={} size={} rc={}", this, ml.getName(), lh.getId(), entryId, dataLength, rc); } if (rc != BKException.Code.OK) { // If we get a write error, we will try to create a new ledger and re-submit the pending writes. If the // ledger creation fails (persistent bk failure, another instanche owning the ML, ...), then the writes will // be marked as failed. ml.mbean.recordAddEntryError(); ml.getExecutor().executeOrdered(ml.getName(), SafeRun.safeRun(() -> { // Force the creation of a new ledger. Doing it in a background thread to avoid acquiring ML lock // from a BK callback. ml.ledgerClosed(lh); })); } else { // Trigger addComplete callback in a thread hashed on the managed ledger name ml.getExecutor().executeOrdered(ml.getName(), this); } }
@Override public void readEntriesFailed(ManagedLedgerException status, Object ctx) { cursor.readOperationCompleted(); if (!entries.isEmpty()) { // There were already some entries that were read before, we can return them cursor.ledger.getExecutor().submit(safeRun(() -> { callback.readEntriesComplete(entries, ctx); recycle(); })); } else { if (!(status instanceof TooManyRequestsException)) { log.warn("[{}][{}] read failed from ledger at position:{} : {}", cursor.ledger.getName(), cursor.getName(), readPosition, status.getMessage()); } else { if (log.isDebugEnabled()) { log.debug("[{}][{}] read throttled failed from ledger at position:{}", cursor.ledger.getName(), cursor.getName(), readPosition); } } callback.readEntriesFailed(status, ctx); cursor.ledger.mbean.recordReadEntriesError(); recycle(); } }
void asyncDeleteCursorLedger() { STATE_UPDATER.set(this, State.Closed); if (cursorLedger == null) { // No ledger was created return; } ledger.mbean.startCursorLedgerDeleteOp(); bookkeeper.asyncDeleteLedger(cursorLedger.getId(), (rc, ctx) -> { ledger.getExecutor().submit(safeRun(() -> { ledger.mbean.endCursorLedgerDeleteOp(); if (rc == BKException.Code.OK) { log.debug("[{}][{}] Deleted cursor ledger", cursorLedger.getId()); } else { log.warn("[{}][{}] Failed to delete ledger {}: {}", ledger.getName(), name, cursorLedger.getId(), BKException.getMessage(rc)); } })); }, null); }
void checkReadCompletion() { if (entries.size() < count && cursor.hasMoreEntries()) { // We still have more entries to read from the next ledger, schedule a new async operation if (nextReadPosition.getLedgerId() != readPosition.getLedgerId()) { cursor.ledger.startReadOperationOnLedger(nextReadPosition); } // Schedule next read in a different thread cursor.ledger.getExecutor().execute(safeRun(() -> { readPosition = cursor.ledger.startReadOperationOnLedger(nextReadPosition); cursor.ledger.asyncReadEntries(OpReadEntry.this); })); } else { // The reading was already completed, release resources and trigger callback try { cursor.readOperationCompleted(); } finally { cursor.ledger.getExecutor().executeOrdered(cursor.ledger.getName(), safeRun(() -> { callback.readEntriesComplete(entries, ctx); recycle(); })); } } }
@Override public void asyncResetCursor(Position newPos, AsyncCallbacks.ResetCursorCallback callback) { checkArgument(newPos instanceof PositionImpl); final PositionImpl newPosition = (PositionImpl) newPos; // order trim and reset operations on a ledger ledger.getExecutor().executeOrdered(ledger.getName(), safeRun(() -> { if (ledger.isValidPosition(newPosition) || newPosition.equals(PositionImpl.earliest) || newPosition.equals(PositionImpl.latest)) { internalResetCursor(newPosition, callback); } else { // caller (replay) should handle this error and retry cursor reset callback.resetFailed(new ManagedLedgerException.InvalidCursorPositionException(newPosition.toString()), newPosition); } })); }
ml.mbean.addReadEntriesSample(1, returnEntry.getLength()); ml.getExecutor().submitOrdered(ml.getName(), safeRun(() -> { callback.readEntryComplete(returnEntry, obj); }));
ledgerEntries.close(); }, ml.getExecutor().chooseThread(ml.getName()));