Skip to content

Fix DbLedgerStorage checkpoint losing ledger metadata when write cache is empty#4843

Open
void-ptr974 wants to merge 1 commit into
apache:masterfrom
void-ptr974:fix/dbledger-checkpoint-metadata
Open

Fix DbLedgerStorage checkpoint losing ledger metadata when write cache is empty#4843
void-ptr974 wants to merge 1 commit into
apache:masterfrom
void-ptr974:fix/dbledger-checkpoint-metadata

Conversation

@void-ptr974

Copy link
Copy Markdown
Contributor

Motivation

DbLedgerStorage checkpoint returned early when the write cache was empty, which skipped ledgerIndex.flush(). Ledger metadata updates such as fenced state and explicitLac can be journaled without pending entry data, so checkpointComplete could advance the journal lastMark before those metadata updates were persisted.

Changes

  • Flush the ledger metadata index before returning from an empty-write-cache checkpoint.
  • Update the shard checkpoint after the metadata-only flush completes.
  • Add regression tests for fenced state and explicitLac persistence after flush/restart with no pending entries.

Tests

  • mvn -pl bookkeeper-server -Dtest=DbLedgerStorageTest#testFlushPersistsFencedMetadataWithoutPendingEntries,DbLedgerStorageTest#testFlushPersistsExplicitLacMetadataWithoutPendingEntries test
  • mvn -pl bookkeeper-server -Dtest=DbLedgerStorageTest test
  • mvn -pl bookkeeper-server -DskipTests checkstyle:checkstyle

@void-ptr974 void-ptr974 changed the title Fix DbLedgerStorage metadata checkpoint flush Prevent DbLedgerStorage checkpoint from losing ledger metadata Jul 18, 2026
@void-ptr974 void-ptr974 changed the title Prevent DbLedgerStorage checkpoint from losing ledger metadata Fix DbLedgerStorage checkpoint losing ledger metadata Jul 18, 2026
@void-ptr974 void-ptr974 changed the title Fix DbLedgerStorage checkpoint losing ledger metadata Fix DbLedgerStorage checkpoint losing ledger metadata when write cache is empty Jul 18, 2026
@StevenLuMT
StevenLuMT requested a review from Copilot July 18, 2026 15:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a durability gap in SingleDirectoryDbLedgerStorage.checkpoint() where an empty write cache caused an early return that could skip persisting ledger-metadata updates (e.g., fenced state, explicitLac), potentially allowing journal checkpoint advancement before those metadata changes were flushed.

Changes:

  • Flush ledger metadata index even when the write cache is empty during checkpoint.
  • Ensure shard checkpoint (lastCheckpoint) is advanced after metadata-only flush.
  • Add regression tests covering fenced state and explicitLac persistence across flush/restart with no pending entries.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/SingleDirectoryDbLedgerStorage.java Ensures ledger metadata index is flushed during metadata-only checkpoints; refactors ledger index flush into a helper.
bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/storage/ldb/DbLedgerStorageTest.java Adds regression tests for fenced and explicitLac metadata persistence when no entry data is pending.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 809 to +813
if (writeCache.isEmpty()) {
// Ledger metadata updates can be journaled without any pending entry data.
// Persist them before allowing the journal checkpoint mark to advance.
flushLedgerIndex();
lastCheckpoint = thisCheckpoint;
Comment on lines +261 to +267
Bookie restartedBookie = new TestBookieImpl(conf);
DbLedgerStorage restartedStorage = (DbLedgerStorage) restartedBookie.getLedgerStorage();
try {
assertTrue(restartedStorage.isFenced(ledgerId));
} finally {
restartedStorage.shutdown();
}
Comment on lines +277 to +296
ByteBuf explicitLac = Unpooled.buffer(Long.BYTES * 2);
explicitLac.writeLong(ledgerId);
explicitLac.writeLong(0);
storage.setExplicitLac(ledgerId, explicitLac);
assertFalse(storage.isFlushRequired());

storage.flush();
storage.shutdown();

Bookie restartedBookie = new TestBookieImpl(conf);
DbLedgerStorage restartedStorage = (DbLedgerStorage) restartedBookie.getLedgerStorage();
ByteBuf recoveredExplicitLac = null;
try {
recoveredExplicitLac = restartedStorage.getExplicitLac(ledgerId);
Assert.assertNotNull(recoveredExplicitLac);
assertEquals(0, ByteBufUtil.compare(explicitLac, recoveredExplicitLac));
} finally {
ReferenceCountUtil.release(recoveredExplicitLac);
restartedStorage.shutdown();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants