codelipenghui commented on code in PR #4901:
URL: https://github.com/apache/bookkeeper/pull/4901#discussion_r4261985126


##########
bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/SortedLedgerStorageTest.java:
##########
@@ -191,4 +196,89 @@ public void testGetListOfEntriesOfLedgerAfterFlush() 
throws IOException {
             }));
         }
     }
+
+    /**
+     * A newer memtable LAC must remain visible after an evicted FileInfo is 
flushed.
+     */
+    @Test
+    public void testGetLastAddConfirmedAfterFileInfoEviction() throws 
Exception {
+        File tmpDir = File.createTempFile("bkLac", ".dir");
+        tmpDir.delete();
+        tmpDir.mkdir();
+        
BookieImpl.checkDirectoryStructure(BookieImpl.getCurrentDirectory(tmpDir));
+
+        ServerConfiguration limited = 
TestBKConfiguration.newServerConfiguration();
+        limited.setEntryLogPerLedgerEnabled(conf.isEntryLogPerLedgerEnabled());
+        limited.setLedgerDirNames(new String[] { tmpDir.toString() });
+        limited.setOpenFileLimit(2);
+        limited.setNumAddWorkerThreads(1);
+        limited.setNumReadWorkerThreads(1);
+        limited.setSkipListSizeLimit(64 * 1024 * 1024);
+
+        LedgerDirsManager dirs = new LedgerDirsManager(limited, 
limited.getLedgerDirs(),
+                new DiskChecker(limited.getDiskUsageThreshold(), 
limited.getDiskUsageWarnThreshold()));
+        InterleavedLedgerStorage underlying = new InterleavedLedgerStorage();
+        SortedLedgerStorage storage = new SortedLedgerStorage(underlying);
+        storage.initialize(limited, null, dirs, dirs,
+                statsProvider.getStatsLogger(BOOKIE_SCOPE), 
UnpooledByteBufAllocator.DEFAULT);
+        storage.setCheckpointSource(CheckpointSource.DEFAULT);
+        storage.setCheckpointer(checkpointer);
+        try {
+            long ledgerId = 0L;
+            storage.setMasterKey(ledgerId, ("ledger-" + ledgerId).getBytes());
+            for (long entryId = 0; entryId < 5; entryId++) {
+                ByteBuf entry = Unpooled.buffer(128);
+                entry.writeLong(ledgerId);
+                entry.writeLong(entryId);
+                entry.writeLong(entryId - 1);
+                entry.writeByte(1);
+                storage.addEntry(entry);
+            }
+            storage.flush();

Review Comment:
   Since entries 0–4 are flushed here, the index lookup in 
`getLastAddConfirmed` succeeds (it returns 3), so this test only runs the try 
branch. The catch branch is the fix for #4900 itself: the index throws for an 
evicted ledger with nothing flushed. That branch isn't covered any more. The 
earlier version of this test was replaced, and 
`testGetLastAddConfirmedRetriesAfterIndexMiss` only reaches that branch with an 
empty memtable.
   
   I checked locally with two changes to 
`SortedLedgerStorage#getLastAddConfirmed`. All 8 tests in this class still pass 
with either one:
   - **The catch branch replaced by a plain index retry.** This brings #4900 
back: an end-to-end V3 read of an evicted, unflushed ledger fails with 
`BKNoSuchEntryException`.
   - **The catch branch returning the memtable LAC without the write-back.** A 
long poll after a LAC read then keeps waiting.
   
   Removing the write-back in the try branch does fail this test, so it's a 
good guard for the partially flushed case.
   
   Could you keep this test and add a fully unflushed case next to it? With the 
same setup:
   1. Add entries 0–2 without flushing.
   2. Evict with the same `invalidate` calls.
   3. Assert LAC 1.
   4. Assert `waitForLastAddConfirmedUpdate(ledgerId, 0, watcher)` returns 
`false` (the write-back reached the cache).
   5. Call `flush()`, assert the memtable is empty, and assert LAC 1 again.
   
   In my local checks, assertions like these fail under both changes above.



##########
bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/SortedLedgerStorage.java:
##########
@@ -240,7 +240,46 @@ public ByteBuf getEntry(long ledgerId, long entryId) 
throws IOException, BookieE
 
     @Override
     public long getLastAddConfirmed(long ledgerId) throws IOException {
-        return interleavedLedgerStorage.getLastAddConfirmed(ledgerId);
+        Long memTableLac = lastAddConfirmedFromMemTable(ledgerId);
+        try {
+            long persistedLac = 
interleavedLedgerStorage.getLastAddConfirmed(ledgerId);
+            if (memTableLac == null || memTableLac <= persistedLac) {
+                return persistedLac;
+            }
+            try {
+                return 
interleavedLedgerStorage.ledgerCache.updateLastAddConfirmed(ledgerId, 
memTableLac);
+            } catch (Bookie.NoLedgerException e) {
+                return memTableLac;
+            }

Review Comment:
   Nit: a one-line comment on why the value is written back would help, for 
example: it keeps the cached LAC from falling back to the older index value 
once the memtable is flushed, and it notifies LAC watchers. The method returns 
the right value either way, so a later reader could take the write-back for 
dead code.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to