@@ -1568,14 +1568,11 @@ public HFileBlock readBlockData(long offset, long onDiskSizeWithHeaderL, boolean
1568
1568
}
1569
1569
1570
1570
/**
1571
- * Check that {@code value} value seems reasonable, within a large margin of error.
1571
+ * Check that {@code value} read from a block header seems reasonable, within a large margin of
1572
+ * error.
1572
1573
* @return {@code true} if the value is safe to proceed, {@code false} otherwise.
1573
1574
*/
1574
1575
private boolean checkOnDiskSizeWithHeader (int value ) {
1575
- if (value == -1 ) {
1576
- // a magic value we expect to see.
1577
- return true ;
1578
- }
1579
1576
if (value < 0 ) {
1580
1577
if (LOG .isTraceEnabled ()) {
1581
1578
LOG .trace (
@@ -1596,18 +1593,23 @@ private boolean checkOnDiskSizeWithHeader(int value) {
1596
1593
}
1597
1594
1598
1595
/**
1599
- * Check that {@code value} value seems reasonable, within a large margin of error.
1596
+ * Check that {@code value} provided by the calling context seems reasonable, within a large
1597
+ * margin of error.
1600
1598
* @return {@code true} if the value is safe to proceed, {@code false} otherwise.
1601
1599
*/
1602
- private boolean checkOnDiskSizeWithHeader (long value ) {
1600
+ private boolean checkCallerProvidedOnDiskSizeWithHeader (long value ) {
1603
1601
// same validation logic as is used by Math.toIntExact(long)
1604
1602
int intValue = (int ) value ;
1605
1603
if (intValue != value ) {
1606
1604
if (LOG .isTraceEnabled ()) {
1607
- LOG .trace ("onDiskSizeWithHeader ={}; value exceeds int size limits." , value );
1605
+ LOG .trace ("onDiskSizeWithHeaderL ={}; value exceeds int size limits." , value );
1608
1606
}
1609
1607
return false ;
1610
1608
}
1609
+ if (intValue == -1 ) {
1610
+ // a magic value we expect to see.
1611
+ return true ;
1612
+ }
1611
1613
return checkOnDiskSizeWithHeader (intValue );
1612
1614
}
1613
1615
@@ -1646,14 +1648,9 @@ private void invalidateNextBlockHeader() {
1646
1648
prefetchedHeader .set (new PrefetchedHeader ());
1647
1649
}
1648
1650
1649
- private int getNextBlockOnDiskSize (boolean readNextHeader , ByteBuff onDiskBlock ,
1650
- int onDiskSizeWithHeader ) {
1651
- int nextBlockOnDiskSize = -1 ;
1652
- if (readNextHeader ) {
1653
- nextBlockOnDiskSize =
1654
- onDiskBlock .getIntAfterPosition (onDiskSizeWithHeader + BlockType .MAGIC_LENGTH ) + hdrSize ;
1655
- }
1656
- return nextBlockOnDiskSize ;
1651
+ private int getNextBlockOnDiskSize (ByteBuff onDiskBlock , int onDiskSizeWithHeader ) {
1652
+ return onDiskBlock .getIntAfterPosition (onDiskSizeWithHeader + BlockType .MAGIC_LENGTH )
1653
+ + hdrSize ;
1657
1654
}
1658
1655
1659
1656
private ByteBuff allocate (int size , boolean intoHeap ) {
@@ -1679,16 +1676,15 @@ private ByteBuff allocate(int size, boolean intoHeap) {
1679
1676
protected HFileBlock readBlockDataInternal (FSDataInputStream is , long offset ,
1680
1677
long onDiskSizeWithHeaderL , boolean pread , boolean verifyChecksum , boolean updateMetrics ,
1681
1678
boolean intoHeap ) throws IOException {
1682
- if (offset < 0 ) {
1683
- throw new IOException ("Invalid offset=" + offset + " trying to read " + "block (onDiskSize="
1684
- + onDiskSizeWithHeaderL + ")" );
1685
- }
1686
-
1687
1679
final Span span = Span .current ();
1688
1680
final AttributesBuilder attributesBuilder = Attributes .builder ();
1689
1681
Optional .of (Context .current ()).map (val -> val .get (CONTEXT_KEY ))
1690
1682
.ifPresent (c -> c .accept (attributesBuilder ));
1691
- if (!checkOnDiskSizeWithHeader (onDiskSizeWithHeaderL )) {
1683
+ if (offset < 0 ) {
1684
+ throw new IOException ("Invalid offset=" + offset + " trying to read " + "block (onDiskSize="
1685
+ + onDiskSizeWithHeaderL + ")" );
1686
+ }
1687
+ if (!checkCallerProvidedOnDiskSizeWithHeader (onDiskSizeWithHeaderL )) {
1692
1688
throw new IOException (
1693
1689
"Caller provided invalid onDiskSizeWithHeaderL=" + onDiskSizeWithHeaderL );
1694
1690
}
@@ -1722,28 +1718,24 @@ protected HFileBlock readBlockDataInternal(FSDataInputStream is, long offset,
1722
1718
headerBuf = HEAP .allocate (hdrSize );
1723
1719
readAtOffset (is , headerBuf , hdrSize , false , offset , pread );
1724
1720
headerBuf .rewind ();
1721
+ }
1722
+ onDiskSizeWithHeader = getOnDiskSizeWithHeader (headerBuf , checksumSupport );
1723
+ }
1725
1724
1726
- // The caller didn't provide an anticipated block size and headerBuf was null, this is
1727
- // probably the first time this HDFS block has been read. The value we just read has not
1728
- // had HBase checksum validation ; assume it was not protected by HDFS checksum either.
1729
- // Sanity check the value. If it doesn't seem right, either trigger fall-back to hdfs
1730
- // checksum or abort the read.
1731
- //
1732
- // TODO: Should we also check the value vs. some multiple of fileContext.getBlocksize() ?
1733
- onDiskSizeWithHeader = getOnDiskSizeWithHeader (headerBuf , checksumSupport );
1734
- if (!checkOnDiskSizeWithHeader (onDiskSizeWithHeader )) {
1735
- if (verifyChecksum ) {
1736
- invalidateNextBlockHeader ();
1737
- span .addEvent ("Falling back to HDFS checksumming." , attributesBuilder .build ());
1738
- return null ;
1739
- } else {
1740
- throw new IOException ("Read invalid onDiskSizeWithHeader=" + onDiskSizeWithHeader );
1741
- }
1742
- }
1725
+ // The common case is that onDiskSizeWithHeader was produced by a read without checksum
1726
+ // validation, so give it a sanity check before trying to use it.
1727
+ //
1728
+ // TODO: Should we also check the value vs. some multiple of fileContext.getBlocksize() ?
1729
+ if (!checkOnDiskSizeWithHeader (onDiskSizeWithHeader )) {
1730
+ if (verifyChecksum ) {
1731
+ invalidateNextBlockHeader ();
1732
+ span .addEvent ("Falling back to HDFS checksumming." , attributesBuilder .build ());
1733
+ return null ;
1743
1734
} else {
1744
- onDiskSizeWithHeader = getOnDiskSizeWithHeader ( headerBuf , checksumSupport );
1735
+ throw new IOException ( "Invalid onDiskSizeWithHeader=" + onDiskSizeWithHeader );
1745
1736
}
1746
1737
}
1738
+
1747
1739
int preReadHeaderSize = headerBuf == null ? 0 : hdrSize ;
1748
1740
// Allocate enough space to fit the next block's header too; saves a seek next time through.
1749
1741
// onDiskBlock is whole block + header + checksums then extra hdrSize to read next header;
@@ -1760,8 +1752,16 @@ protected HFileBlock readBlockDataInternal(FSDataInputStream is, long offset,
1760
1752
boolean readNextHeader = readAtOffset (is , onDiskBlock ,
1761
1753
onDiskSizeWithHeader - preReadHeaderSize , true , offset + preReadHeaderSize , pread );
1762
1754
onDiskBlock .rewind (); // in case of moving position when copying a cached header
1763
- int nextBlockOnDiskSize =
1764
- getNextBlockOnDiskSize (readNextHeader , onDiskBlock , onDiskSizeWithHeader );
1755
+
1756
+ // the call to validateChecksum for this block excludes the next block header over-read, so
1757
+ // no reason to delay extracting this value.
1758
+ int nextBlockOnDiskSize = -1 ;
1759
+ if (readNextHeader ) {
1760
+ int parsedVal = getNextBlockOnDiskSize (onDiskBlock , onDiskSizeWithHeader );
1761
+ if (checkOnDiskSizeWithHeader (parsedVal )) {
1762
+ nextBlockOnDiskSize = parsedVal ;
1763
+ }
1764
+ }
1765
1765
if (headerBuf == null ) {
1766
1766
headerBuf = onDiskBlock .duplicate ().position (0 ).limit (hdrSize );
1767
1767
}
0 commit comments