Source:
<code>void doAsyncCloseInternal(final CloseCallback cb, final Object ctx, final int rc) { clientCtx.getMainWorkerPool().executeOrdered(ledgerId, new SafeRunnable() { @Override public void safeRun() { final long prevLastEntryId; final long prevLength; final State prevState; List<PendingAddOp> pendingAdds; if (isClosed()) { synchronized (LedgerHandle.this) { pendingAdds = drainPendingAddsToErrorOut(); } errorOutPendingAdds(rc, pendingAdds); cb.closeComplete(BKException.Code.OK, LedgerHandle.this, ctx); return; } else { long lastEntry; long finalLength; synchronized (LedgerHandle.this) { pendingAdds = drainPendingAddsToErrorOut(); lastEntry = lastAddPushed = LedgerHandle.this.lastAddConfirmed; finalLength = LedgerHandle.this.length; closing = true; } errorOutPendingAdds(rc, pendingAdds); if (LOG.isDebugEnabled()) { LOG.debug("Closing ledger: at entryId with bytes", getId(), lastEntry, finalLength); } tearDownWriteHandleState(); new MetadataUpdateLoop( clientCtx.getLedgerManager(), getId(), LedgerHandle.this::getLedgerMetadata, (metadata) -> { if (metadata.isClosed()) { if (lastEntry == metadata.getLastEntryId() && finalLength == metadata.getLength()) { return false; } else { <START> throw new BKException.BKMetadataVersionException(); <END> } } else { return true; } }, (metadata) -> { return LedgerMetadataBuilder.from(metadata) .closingAt(lastEntry, finalLength).build(); }, LedgerHandle.this::setLedgerMetadata) .run().whenComplete((metadata, ex) -> { if (ex != null) { cb.closeComplete( BKException.getExceptionCode( ex, BKException.Code.UnexpectedConditionException), LedgerHandle.this, ctx); } else { cb.closeComplete(BKException.Code.OK, LedgerHandle.this, ctx); } }); } } }); }</code><technical_language>a log message error message in exception state difference useful for production</technical_language>

Target:
void doAsyncCloseInternal(final CloseCallback cb, final Object ctx, final int rc) { clientCtx.getMainWorkerPool().executeOrdered(ledgerId, new SafeRunnable() { @Override public void safeRun() { final HandleState prevHandleState; final List<PendingAddOp> pendingAdds; final long lastEntry; final long finalLength; synchronized (LedgerHandle.this) { prevHandleState = handleState; pendingAdds = drainPendingAddsAndAdjustLength(); lastEntry = lastAddPushed = LedgerHandle.this.lastAddConfirmed; finalLength = LedgerHandle.this.length; handleState = HandleState.CLOSED; } errorOutPendingAdds(rc, pendingAdds); if (prevHandleState == HandleState.CLOSED) { cb.closeComplete(BKException.Code.OK, LedgerHandle.this, ctx); } else { if (LOG.isDebugEnabled()) { LOG.debug("Closing ledger: at entryId with bytes", getId(), lastEntry, finalLength); } tearDownWriteHandleState(); new MetadataUpdateLoop( clientCtx.getLedgerManager(), getId(), LedgerHandle.this::getLedgerMetadata, (metadata) -> { if (metadata.isClosed()) { if (lastEntry == metadata.getLastEntryId() && finalLength == metadata.getLength()) { return false; } else { LOG.error("Metadata conflict when closing ledger {}." + " Another client may have recovered the ledger while there" + " were writes outstanding. (local lastEntry:{} length:{}) " + " (metadata lastEntry:{} length:{})", getId(), lastEntry, finalLength, metadata.getLastEntryId(), metadata.getLength()); throw new BKException.BKMetadataVersionException(); } } else { return true; } }, (metadata) -> { return LedgerMetadataBuilder.from(metadata) .closingAt(lastEntry, finalLength).build(); }, LedgerHandle.this::setLedgerMetadata) .run().whenComplete((metadata, ex) -> { if (ex != null) { cb.closeComplete( BKException.getExceptionCode( ex, BKException.Code.UnexpectedConditionException), LedgerHandle.this, ctx); } else { cb.closeComplete(BKException.Code.OK, LedgerHandle.this, ctx); } }); } } }); }