You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bookkeeper.apache.org by ch...@apache.org on 2022/08/01 07:11:40 UTC

[bookkeeper] branch master updated: Issue #2908: Replace unsafe NoEntryException with IOException (#2909)

This is an automated email from the ASF dual-hosted git repository.

chenhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git


The following commit(s) were added to refs/heads/master by this push:
     new 966b865973 Issue #2908: Replace unsafe NoEntryException with IOException (#2909)
966b865973 is described below

commit 966b865973714c1bde596004bc4e5c1daa5a6d00
Author: Jack Vanlightly <va...@gmail.com>
AuthorDate: Mon Aug 1 09:11:35 2022 +0200

    Issue #2908: Replace unsafe NoEntryException with IOException (#2909)
    
    * Replace unsafe NoEntryException with IOException
    
    Throwing a NoEntryException from the entry logger
    for an entry that the index says should exist is
    unsafe. It can cause ledger truncation during ledger
    recovery. It only takes a single false NoSuchEntry
    response to trigger truncation.
    
    NoEntryException should only be thrown from inside
    ledger storage if the entry is not found in the index.
    
    * fix CI
    
    Co-authored-by: chenhang <ch...@apache.org>
---
 .../apache/bookkeeper/bookie/DefaultEntryLogger.java    | 17 ++++-------------
 .../org/apache/bookkeeper/bookie/LedgerCacheTest.java   |  9 +++++++--
 2 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/DefaultEntryLogger.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/DefaultEntryLogger.java
index f7d2715b7d..34a51aefbb 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/DefaultEntryLogger.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/DefaultEntryLogger.java
@@ -835,27 +835,18 @@ public class DefaultEntryLogger implements EntryLogger {
             if (validateEntry) {
                 validateEntry(ledgerId, entryId, entryLogId, pos, sizeBuff);
             }
-        } catch (EntryLookupException.MissingEntryException entryLookupError) {
-            throw new Bookie.NoEntryException("Short read from entrylog " + entryLogId,
-                    ledgerId, entryId);
         } catch (EntryLookupException e) {
-            throw new IOException(e.toString());
+            throw new IOException("Bad entry read from log file id: " + entryLogId, e);
         }
 
         ByteBuf data = allocator.buffer(entrySize, entrySize);
         int rc = readFromLogChannel(entryLogId, fc, data, pos);
         if (rc != entrySize) {
-            // Note that throwing NoEntryException here instead of IOException is not
-            // without risk. If all bookies in a quorum throw this same exception
-            // the client will assume that it has reached the end of the ledger.
-            // However, this may not be the case, as a very specific error condition
-            // could have occurred, where the length of the entry was corrupted on all
-            // replicas. However, the chance of this happening is very very low, so
-            // returning NoEntryException is mostly safe.
             data.release();
-            throw new Bookie.NoEntryException("Short read for " + ledgerId + "@"
+            throw new IOException("Bad entry read from log file id: " + entryLogId,
+                    new EntryLookupException("Short read for " + ledgerId + "@"
                                               + entryId + " in " + entryLogId + "@"
-                                              + pos + "(" + rc + "!=" + entrySize + ")", ledgerId, entryId);
+                                              + pos + "(" + rc + "!=" + entrySize + ")"));
         }
         data.writerIndex(entrySize);
 
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/LedgerCacheTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/LedgerCacheTest.java
index 968b5fce58..85c3bca8d7 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/LedgerCacheTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/LedgerCacheTest.java
@@ -350,8 +350,13 @@ public class LedgerCacheTest {
                 // this is fine, means the ledger was written to the index cache, but not
                 // the entry log
             } catch (IOException ioe) {
-                LOG.info("Shouldn't have received IOException", ioe);
-                fail("Shouldn't throw IOException, should say that entry is not found");
+                if (ioe.getCause() instanceof DefaultEntryLogger.EntryLookupException) {
+                    // this is fine, means the ledger was not fully written to
+                    // the entry log
+                } else {
+                    LOG.info("Shouldn't have received IOException for entry {}", i, ioe);
+                    fail("Shouldn't throw IOException, should say that entry is not found");
+                }
             }
         }
     }