Skip to content

Issue 4900: Read an unflushed ledger LAC from the memtable - #4901

Open
kalayciburak wants to merge 1 commit into
apache:masterfrom
kalayciburak:fix/4900-unflushed-ledger-lac
Open

kalayciburak wants to merge 1 commit into
apache:masterfrom
kalayciburak:fix/4900-unflushed-ledger-lac

Conversation

@kalayciburak

Copy link
Copy Markdown

Descriptions of the changes in this PR:

Fix #4900

Motivation

SortedLedgerStorage.getLastAddConfirmed delegated entirely to the index. Until the memtable is flushed, that LAC lives only in a FileInfo cache entry. Once the cache evicts the ledger, the index file still does not exist, so a later read fails with NoLedgerException / NoEntryException even though the entry is still in the memtable. The bookie turns that into ENOLEDGER.

Changes

On those misses, read the LAC from the last memtable entry (the same offset addEntry stores). If the entry was flushed between the miss and the lookup, ask the index again. A ledger that is in neither place still fails.

Tests

mvn -pl bookkeeper-server -am test -Dtest=SortedLedgerStorageTest -Dsurefire.failIfNoSpecifiedTests=false

SortedLedgerStorageTest 6 tests, 0 failures. The new case expects LAC 3 and got NoEntryException: Entry 0 not found in 0 before the change.

mvn -pl bookkeeper-server checkstyle:check — 0 violations.

getLastAddConfirmed only asked the index. After the FileInfo cache
evicted an unflushed ledger, the read failed even though the entry
was still in the memtable.
@djsweet

djsweet commented Oct 4, 2026

Copy link
Copy Markdown

I have an alternative PR, #4902, that we've been using in production as a workaround for this bug.

It's worth pointing out that both of these PRs require a fix for #4895 to function correctly when ledger metadata is in use.

@djsweet

djsweet commented Oct 4, 2026

Copy link
Copy Markdown

Thinking a bit more on this, I'm not sure this is a fully correct fix. Consider the scenario posed by #4900, but where the first ledger already exists, and is committed into InterleavedLedgerStorage.

If you write to over 20,000 ledgers with small payloads below the skipListSizeLimit, then the call to interleavedLedgerStorage.getLastAddConfirmed will not be able to access the LAC from the Ledger Cache, but instead will read from the committed value in InterleavedLedgerStorage, which will be behind the LAC in the memTable. This means the LAC gets reset backwards, spuriously.

#4902 always reads from the entryMemTable before interleavedLedgerStorage, so it shouldn't be susceptible to the same problem.

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.

Reads in SortedLedgerStorage erroneously report ENOLEDGER for more unflushed ledgers in the memtable than openFileLimit

2 participants