@@ -474,13 +474,76 @@ private static Block readIndirectBlock(SeekableByteChannel channel, FractalHeapH
474474 return ib ;
475475 }
476476
477+ // private static long getBlockSize(FractalHeapHeader header, long blockOffset) throws IOException, InvocationTargetException, InstantiationException, IllegalAccessException {
478+ // long startingBlockSize = header.startingBlockSize.getInstance(Long.class);
479+ // if (blockOffset == 0 && header.currentNumRowsRootIndirectBlock == 0) {
480+ // return startingBlockSize;
481+ // }
482+ // double arg = ((double) blockOffset / (header.tableWidth * header.startingBlockSize.getInstance(Long.class))) + 1;
483+ // int row = (int) Math.floor(Math.log(arg) / Math.log(2));
484+ // long exponent = Math.max(0L, row - 1L);
485+ // return startingBlockSize * (1L << exponent);
486+ // }
487+ /**
488+ * Calculates the block size for a given offset based on the HDF5 Fractal Heap spec.
489+ *
490+ * The block size is startingBlockSize for the first two rows (row 0 and row 1)
491+ * of the indirect block. It then doubles for each subsequent row.
492+ *
493+ * @param header The FractalHeapHeader, containing startingBlockSize and tableWidth
494+ * @param blockOffset The absolute offset of the block in the heap
495+ * @return The calculated block size for that offset
496+ */
477497 private static long getBlockSize (FractalHeapHeader header , long blockOffset ) throws IOException , InvocationTargetException , InstantiationException , IllegalAccessException {
498+
478499 long startingBlockSize = header .startingBlockSize .getInstance (Long .class );
500+
501+ // Original special case for an empty heap's root block
479502 if (blockOffset == 0 && header .currentNumRowsRootIndirectBlock == 0 ) {
480503 return startingBlockSize ;
481504 }
482- double arg = ((double ) blockOffset / (header .tableWidth * header .startingBlockSize .getInstance (Long .class ))) + 1 ;
483- int row = (int ) Math .floor (Math .log (arg ) / Math .log (2 ));
505+
506+ // N = baseRowSize
507+ long baseRowSize = header .tableWidth * startingBlockSize ; // e.g., 4 * 512 = 2048
508+
509+ int row ;
510+
511+ // Check if we are in Row 0 (offsets 0 to 2047)
512+ if (blockOffset < baseRowSize ) {
513+ row = 0 ;
514+ }
515+ // Check if we are in Row 1 (offsets 2048 to 4095)
516+ else if (blockOffset < 2 * baseRowSize ) {
517+ row = 1 ;
518+ }
519+ // We are in Row 2 or higher (offset >= 4096)
520+ else {
521+ // We need to find the row 'i' (where i >= 2)
522+ // The starting offset for row 'i' is (2^(i-1)) * baseRowSize
523+ // We are looking for 'i' where:
524+ // 2^(i-1) * baseRowSize <= blockOffset < 2^i * baseRowSize
525+ //
526+ // Divide by baseRowSize:
527+ // 2^(i-1) <= (blockOffset / baseRowSize) < 2^i
528+ //
529+ // Let arg = (double) blockOffset / baseRowSize
530+ // Take log2 of the left side:
531+ // i - 1 <= log2(arg) => i <= log2(arg) + 1
532+ //
533+ // Take log2 of the right side:
534+ // log2(arg) < i
535+ //
536+ // This means 'i' is exactly floor(log2(arg)) + 1
537+
538+ double arg = (double ) blockOffset / baseRowSize ;
539+ row = (int ) Math .floor (Math .log (arg ) / Math .log (2 )) + 1 ;
540+ }
541+
542+ // The first two rows (0 and 1) have exponent 0.
543+ // Row 2 has exponent 1 (size = 512 * 2^1 = 1024)
544+ // Row 3 has exponent 2 (size = 512 * 2^2 = 2048)
545+ // Pattern: exponent = max(0, row - 1)
546+
484547 long exponent = Math .max (0L , row - 1L );
485548 return startingBlockSize * (1L << exponent );
486549 }
0 commit comments