@@ -285,7 +285,7 @@ public HFileBlock deserialize(ByteBuff buf, ByteBuffAllocator alloc)
285285 boolean usesChecksum = buf .get () == (byte ) 1 ;
286286 long offset = buf .getLong ();
287287 int nextBlockOnDiskSize = buf .getInt ();
288- return new HFileBlock (newByteBuff , usesChecksum , offset , nextBlockOnDiskSize , null , alloc );
288+ return createFromBuff (newByteBuff , usesChecksum , offset , nextBlockOnDiskSize , null , alloc );
289289 }
290290
291291 @ Override
@@ -300,28 +300,6 @@ public int getDeserializerIdentifier() {
300300 CacheableDeserializerIdManager .registerDeserializer (BLOCK_DESERIALIZER );
301301 }
302302
303- /**
304- * Copy constructor. Creates a shallow copy of {@code that}'s buffer.
305- */
306- private HFileBlock (HFileBlock that ) {
307- this (that , false );
308- }
309-
310- /**
311- * Copy constructor. Creates a shallow/deep copy of {@code that}'s buffer as per the boolean
312- * param.
313- */
314- private HFileBlock (HFileBlock that , boolean bufCopy ) {
315- init (that .blockType , that .onDiskSizeWithoutHeader , that .uncompressedSizeWithoutHeader ,
316- that .prevBlockOffset , that .offset , that .onDiskDataSizeWithHeader , that .nextBlockOnDiskSize ,
317- that .fileContext , that .allocator );
318- if (bufCopy ) {
319- this .buf = ByteBuff .wrap (ByteBuffer .wrap (that .buf .toBytes (0 , that .buf .limit ())));
320- } else {
321- this .buf = that .buf .duplicate ();
322- }
323- }
324-
325303 /**
326304 * Creates a new {@link HFile} block from the given fields. This constructor
327305 * is used only while writing blocks and caching,
@@ -336,20 +314,27 @@ private HFileBlock(HFileBlock that, boolean bufCopy) {
336314 * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}
337315 * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}
338316 * @param prevBlockOffset see {@link #prevBlockOffset}
339- * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)
317+ * @param buf block buffer with header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)
340318 * @param fillHeader when true, write the first 4 header fields into passed buffer.
341319 * @param offset the file offset the block was read from
342320 * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}
343321 * @param fileContext HFile meta data
344322 */
345323 @ VisibleForTesting
346324 public HFileBlock (BlockType blockType , int onDiskSizeWithoutHeader ,
347- int uncompressedSizeWithoutHeader , long prevBlockOffset , ByteBuffer b , boolean fillHeader ,
348- long offset , final int nextBlockOnDiskSize , int onDiskDataSizeWithHeader ,
349- HFileContext fileContext , ByteBuffAllocator allocator ) {
350- init (blockType , onDiskSizeWithoutHeader , uncompressedSizeWithoutHeader , prevBlockOffset , offset ,
351- onDiskDataSizeWithHeader , nextBlockOnDiskSize , fileContext , allocator );
352- this .buf = new SingleByteBuff (b );
325+ int uncompressedSizeWithoutHeader , long prevBlockOffset , ByteBuff buf , boolean fillHeader ,
326+ long offset , int nextBlockOnDiskSize , int onDiskDataSizeWithHeader , HFileContext fileContext ,
327+ ByteBuffAllocator allocator ) {
328+ this .blockType = blockType ;
329+ this .onDiskSizeWithoutHeader = onDiskSizeWithoutHeader ;
330+ this .uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader ;
331+ this .prevBlockOffset = prevBlockOffset ;
332+ this .offset = offset ;
333+ this .onDiskDataSizeWithHeader = onDiskDataSizeWithHeader ;
334+ this .nextBlockOnDiskSize = nextBlockOnDiskSize ;
335+ this .fileContext = fileContext ;
336+ this .allocator = allocator ;
337+ this .buf = buf ;
353338 if (fillHeader ) {
354339 overwriteHeader ();
355340 }
@@ -363,7 +348,7 @@ public HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader,
363348 * to that point.
364349 * @param buf Has header, content, and trailing checksums if present.
365350 */
366- HFileBlock (ByteBuff buf , boolean usesHBaseChecksum , final long offset ,
351+ static HFileBlock createFromBuff (ByteBuff buf , boolean usesHBaseChecksum , final long offset ,
367352 final int nextBlockOnDiskSize , HFileContext fileContext , ByteBuffAllocator allocator )
368353 throws IOException {
369354 buf .rewind ();
@@ -374,15 +359,15 @@ public HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader,
374359 final long prevBlockOffset = buf .getLong (Header .PREV_BLOCK_OFFSET_INDEX );
375360 // This constructor is called when we deserialize a block from cache and when we read a block in
376361 // from the fs. fileCache is null when deserialized from cache so need to make up one.
377- HFileContextBuilder fileContextBuilder = fileContext != null ?
378- new HFileContextBuilder (fileContext ): new HFileContextBuilder ();
362+ HFileContextBuilder fileContextBuilder =
363+ fileContext != null ? new HFileContextBuilder (fileContext ) : new HFileContextBuilder ();
379364 fileContextBuilder .withHBaseCheckSum (usesHBaseChecksum );
380365 int onDiskDataSizeWithHeader ;
381366 if (usesHBaseChecksum ) {
382367 byte checksumType = buf .get (Header .CHECKSUM_TYPE_INDEX );
383368 int bytesPerChecksum = buf .getInt (Header .BYTES_PER_CHECKSUM_INDEX );
384369 onDiskDataSizeWithHeader = buf .getInt (Header .ON_DISK_DATA_SIZE_WITH_HEADER_INDEX );
385- // Use the checksum type and bytes per checksum from header, not from filecontext .
370+ // Use the checksum type and bytes per checksum from header, not from fileContext .
386371 fileContextBuilder .withChecksumType (ChecksumType .codeToType (checksumType ));
387372 fileContextBuilder .withBytesPerCheckSum (bytesPerChecksum );
388373 } else {
@@ -393,29 +378,19 @@ public HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader,
393378 }
394379 fileContext = fileContextBuilder .build ();
395380 assert usesHBaseChecksum == fileContext .isUseHBaseChecksum ();
396- init (blockType , onDiskSizeWithoutHeader , uncompressedSizeWithoutHeader , prevBlockOffset , offset ,
397- onDiskDataSizeWithHeader , nextBlockOnDiskSize , fileContext , allocator );
398- this .offset = offset ;
399- this .buf = buf ;
400- this .buf .rewind ();
401- }
402-
403- /**
404- * Called from constructors.
405- */
406- private void init (BlockType blockType , int onDiskSizeWithoutHeader ,
407- int uncompressedSizeWithoutHeader , long prevBlockOffset , long offset ,
408- int onDiskDataSizeWithHeader , final int nextBlockOnDiskSize , HFileContext fileContext ,
409- ByteBuffAllocator allocator ) {
410- this .blockType = blockType ;
411- this .onDiskSizeWithoutHeader = onDiskSizeWithoutHeader ;
412- this .uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader ;
413- this .prevBlockOffset = prevBlockOffset ;
414- this .offset = offset ;
415- this .onDiskDataSizeWithHeader = onDiskDataSizeWithHeader ;
416- this .nextBlockOnDiskSize = nextBlockOnDiskSize ;
417- this .fileContext = fileContext ;
418- this .allocator = allocator ;
381+ return new HFileBlockBuilder ()
382+ .withBlockType (blockType )
383+ .withOnDiskSizeWithoutHeader (onDiskSizeWithoutHeader )
384+ .withUncompressedSizeWithoutHeader (uncompressedSizeWithoutHeader )
385+ .withPrevBlockOffset (prevBlockOffset )
386+ .withOffset (offset )
387+ .withOnDiskDataSizeWithHeader (onDiskDataSizeWithHeader )
388+ .withNextBlockOnDiskSize (nextBlockOnDiskSize )
389+ .withHFileContext (fileContext )
390+ .withByteBuffAllocator (allocator )
391+ .withOffset (offset )
392+ .withByteBuff (buf .rewind ())
393+ .build ();
419394 }
420395
421396 /**
@@ -639,7 +614,7 @@ public String toString() {
639614 .append ("(" ).append (onDiskSizeWithoutHeader )
640615 .append ("+" ).append (HConstants .HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM ).append (")" );
641616 }
642- String dataBegin = null ;
617+ String dataBegin ;
643618 if (buf .hasArray ()) {
644619 dataBegin = Bytes .toStringBinary (buf .array (), buf .arrayOffset () + headerSize (),
645620 Math .min (32 , buf .limit () - buf .arrayOffset () - headerSize ()));
@@ -673,7 +648,7 @@ HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException
673648 return this ;
674649 }
675650
676- HFileBlock unpacked = new HFileBlock (this );
651+ HFileBlock unpacked = shallowClone (this );
677652 unpacked .allocateBuffer (); // allocates space for the decompressed block
678653 boolean succ = false ;
679654 try {
@@ -763,7 +738,7 @@ public long heapSize() {
763738 /**
764739 * @return true to indicate the block is allocated from JVM heap, otherwise from off-heap.
765740 */
766- boolean isOnHeap () {
741+ public boolean isOnHeap () {
767742 return buf .hasArray ();
768743 }
769744
@@ -1039,8 +1014,7 @@ void writeHeaderAndData(FSDataOutputStream out) throws IOException {
10391014 + offset );
10401015 }
10411016 startOffset = offset ;
1042-
1043- finishBlockAndWriteHeaderAndData ((DataOutputStream ) out );
1017+ finishBlockAndWriteHeaderAndData (out );
10441018 }
10451019
10461020 /**
@@ -1251,13 +1225,26 @@ HFileBlock getBlockForCaching(CacheConfig cacheConf) {
12511225 .withIncludesMvcc (fileContext .isIncludesMvcc ())
12521226 .withIncludesTags (fileContext .isIncludesTags ())
12531227 .build ();
1254- return new HFileBlock (blockType , getOnDiskSizeWithoutHeader (),
1255- getUncompressedSizeWithoutHeader (), prevOffset ,
1256- cacheConf .shouldCacheCompressed (blockType .getCategory ()) ? cloneOnDiskBufferWithHeader ()
1257- : cloneUncompressedBufferWithHeader (),
1258- FILL_HEADER , startOffset , UNSET ,
1259- onDiskBlockBytesWithHeader .size () + onDiskChecksum .length , newContext ,
1260- cacheConf .getByteBuffAllocator ());
1228+ // Build the HFileBlock.
1229+ HFileBlockBuilder builder = new HFileBlockBuilder ();
1230+ ByteBuffer buffer ;
1231+ if (cacheConf .shouldCacheCompressed (blockType .getCategory ())) {
1232+ buffer = cloneOnDiskBufferWithHeader ();
1233+ } else {
1234+ buffer = cloneUncompressedBufferWithHeader ();
1235+ }
1236+ return builder .withBlockType (blockType )
1237+ .withOnDiskSizeWithoutHeader (getOnDiskSizeWithoutHeader ())
1238+ .withUncompressedSizeWithoutHeader (getUncompressedSizeWithoutHeader ())
1239+ .withPrevBlockOffset (prevOffset )
1240+ .withByteBuff (ByteBuff .wrap (buffer ))
1241+ .withFillHeader (FILL_HEADER )
1242+ .withOffset (startOffset )
1243+ .withNextBlockOnDiskSize (UNSET )
1244+ .withOnDiskDataSizeWithHeader (onDiskBlockBytesWithHeader .size () + onDiskChecksum .length )
1245+ .withHFileContext (newContext )
1246+ .withByteBuffAllocator (cacheConf .getByteBuffAllocator ())
1247+ .build ();
12611248 }
12621249 }
12631250
@@ -1781,8 +1768,8 @@ protected HFileBlock readBlockDataInternal(FSDataInputStream is, long offset,
17811768 // The onDiskBlock will become the headerAndDataBuffer for this block.
17821769 // If nextBlockOnDiskSizeWithHeader is not zero, the onDiskBlock already
17831770 // contains the header of next block, so no need to set next block's header in it.
1784- HFileBlock hFileBlock = new HFileBlock (curBlock , checksumSupport , offset ,
1785- nextBlockOnDiskSize , fileContext , intoHeap ? HEAP : allocator );
1771+ HFileBlock hFileBlock = createFromBuff (curBlock , checksumSupport , offset ,
1772+ nextBlockOnDiskSize , fileContext , intoHeap ? HEAP : allocator );
17861773 // Run check on uncompressed sizings.
17871774 if (!fileContext .isCompressedOrEncrypted ()) {
17881775 hFileBlock .sanityCheckUncompressed ();
@@ -2084,7 +2071,26 @@ static String toStringHeader(ByteBuff buf) throws IOException {
20842071 " onDiskDataSizeWithHeader " + onDiskDataSizeWithHeader ;
20852072 }
20862073
2087- public HFileBlock deepCloneOnHeap () {
2088- return new HFileBlock (this , true );
2074+ private static HFileBlockBuilder createBuilder (HFileBlock blk ){
2075+ return new HFileBlockBuilder ()
2076+ .withBlockType (blk .blockType )
2077+ .withOnDiskSizeWithoutHeader (blk .onDiskSizeWithoutHeader )
2078+ .withUncompressedSizeWithoutHeader (blk .uncompressedSizeWithoutHeader )
2079+ .withPrevBlockOffset (blk .prevBlockOffset )
2080+ .withByteBuff (blk .buf .duplicate ()) // Duplicate the buffer.
2081+ .withOffset (blk .offset )
2082+ .withOnDiskDataSizeWithHeader (blk .onDiskDataSizeWithHeader )
2083+ .withNextBlockOnDiskSize (blk .nextBlockOnDiskSize )
2084+ .withHFileContext (blk .fileContext )
2085+ .withByteBuffAllocator (blk .allocator );
2086+ }
2087+
2088+ static HFileBlock shallowClone (HFileBlock blk ) {
2089+ return createBuilder (blk ).build ();
2090+ }
2091+
2092+ static HFileBlock deepCloneOnHeap (HFileBlock blk ) {
2093+ ByteBuff deepCloned = ByteBuff .wrap (ByteBuffer .wrap (blk .buf .toBytes (0 , blk .buf .limit ())));
2094+ return createBuilder (blk ).withByteBuff (deepCloned ).build ();
20892095 }
20902096}
0 commit comments