Skip to content

Commit a74e929

Browse files
committed
refactor v2 code
1 parent 29f916c commit a74e929

4 files changed

Lines changed: 142 additions & 86 deletions

File tree

src/main/java/org/hdf5javalib/hdffile/infrastructure/fractalheap/FractalHeap.java

Lines changed: 132 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,25 @@ public Block getRootBlock() {
2828
return rootBlock;
2929
}
3030

31-
public static FractalHeap read(SeekableByteChannel channel, long position, HdfDataFile hdfDataFile) throws IOException {
32-
FixedPointDatatype sizeOfOffsets = hdfDataFile.getSuperblock().getFixedPointDatatypeForOffset();
31+
public static FractalHeap read(SeekableByteChannel channel, long position, HdfDataFile hdfDataFile) throws IOException, InvocationTargetException, InstantiationException, IllegalAccessException {
32+
FixedPointDatatype sizeOfOffset = hdfDataFile.getSuperblock().getFixedPointDatatypeForOffset();
33+
FixedPointDatatype sizeOfLength = hdfDataFile.getSuperblock().getFixedPointDatatypeForLength();
3334
channel.position(position);
3435
FractalHeapHeader header = readHeader(channel, hdfDataFile);
35-
long rootAddress = header.addressRootBlock;
36-
short nrows = header.currentNumRowsRootIndirectBlock;
37-
long filteredSize = -1;
38-
int filterMask = 0;
36+
HdfFixedPoint rootAddress = header.addressRootBlock;
37+
int nrows = header.currentNumRowsRootIndirectBlock;
38+
HdfFixedPoint filteredSize = sizeOfLength.undefined();
39+
long filterMask = 0;
3940
if (header.hasFilters && nrows == 0) {
4041
filteredSize = header.filteredRootDirectSize;
4142
filterMask = header.filterMaskRoot;
4243
}
4344
long expectedBlockOffset = 0;
4445
Block root;
4546
if (nrows == 0) {
46-
root = readDirectBlock(reader, header, rootAddress, expectedBlockOffset, filteredSize, filterMask);
47+
root = readDirectBlock(channel, header, rootAddress, sizeOfOffset, expectedBlockOffset, filteredSize, filterMask);
4748
} else {
48-
root = readIndirectBlock(reader, header, rootAddress, expectedBlockOffset, -1, nrows);
49+
root = readIndirectBlock(channel, header, sizeOfOffset, sizeOfLength, rootAddress, expectedBlockOffset, -1, nrows);
4950
}
5051
FractalHeap heap = new FractalHeap();
5152
heap.header = header;
@@ -55,11 +56,12 @@ public static FractalHeap read(SeekableByteChannel channel, long position, HdfDa
5556

5657
private static FractalHeapHeader readHeader(SeekableByteChannel channel, HdfDataFile hdfDataFile) throws IOException, InvocationTargetException, InstantiationException, IllegalAccessException {
5758
FixedPointDatatype sizeOfOffset = hdfDataFile.getSuperblock().getFixedPointDatatypeForOffset();
58-
FixedPointDatatype sizeOfLength = hdfDataFile.getSuperblock().getFixedPointDatatypeForLength().getSize();
59+
FixedPointDatatype sizeOfLength = hdfDataFile.getSuperblock().getFixedPointDatatypeForLength();
5960

6061
FractalHeapHeader h = new FractalHeapHeader();
6162
ByteBuffer signatureBuffer = ByteBuffer.allocate(4);
6263
channel.read(signatureBuffer);
64+
signatureBuffer.flip();
6365
h.signature = new String(signatureBuffer.array(), StandardCharsets.US_ASCII);
6466
if (!Objects.equals(h.signature, "FRHP")) {
6567
throw new IOException("Invalid signature");
@@ -70,6 +72,7 @@ private static FractalHeapHeader readHeader(SeekableByteChannel channel, HdfData
7072
if ( bytesRead != headerSize) {
7173
throw new IllegalStateException("Incorrect amount of bytes read: " + headerSize + " wanted but got " + bytesRead);
7274
}
75+
headerBuffer.flip();
7376

7477
h.version = headerBuffer.get();
7578
h.heapIdLength = Short.toUnsignedInt(headerBuffer.getShort());
@@ -105,6 +108,7 @@ private static FractalHeapHeader readHeader(SeekableByteChannel channel, HdfData
105108
if ( bytesRead != headerSize) {
106109
throw new IllegalStateException("Incorrect amount of bytes read: " + headerSize + " wanted but got " + bytesRead);
107110
}
111+
headerBuffer.flip();
108112
h.filteredRootDirectSize = HdfReadUtils.readHdfFixedPointFromBuffer(sizeOfLength, headerBuffer);
109113
h.filterMaskRoot = Integer.toUnsignedLong(headerBuffer.getInt());
110114
}
@@ -114,6 +118,7 @@ private static FractalHeapHeader readHeader(SeekableByteChannel channel, HdfData
114118
if ( bytesRead != headerSize) {
115119
throw new IllegalStateException("Incorrect amount of bytes read: " + headerSize + " wanted but got " + bytesRead);
116120
}
121+
headerBuffer.flip();
117122
channel.read(headerBuffer);
118123
byte[] filterData = headerBuffer.array();
119124
h.filterPipeline = parseFilterPipeline(filterData);
@@ -124,7 +129,7 @@ private static FractalHeapHeader readHeader(SeekableByteChannel channel, HdfData
124129
if ( bytesRead != headerSize) {
125130
throw new IllegalStateException("Incorrect amount of bytes read: " + headerSize + " wanted but got " + bytesRead);
126131
}
127-
channel.read(headerBuffer);
132+
headerBuffer.flip();
128133
h.checksum = Integer.toUnsignedLong(headerBuffer.getInt());
129134
h.offsetBytes = (h.maximumHeapSize + 7) / 8;
130135
double logVal = Math.log((double) h.maximumDirectBlockSize.getInstance(Long.class) / h.startingBlockSize.getInstance(Long.class)) / Math.log(2);
@@ -234,51 +239,59 @@ private static FilterPipeline parseFilterPipeline(byte[] data) throws IOExceptio
234239
return fp;
235240
}
236241

237-
private static Block readDirectBlock(HdfReader reader, FractalHeapHeader header, long address, long expectedBlockOffset, long filteredSize, int filterMask) throws IOException {
238-
long undefined = -1L;
239-
if (address == undefined) {
242+
private static Block readDirectBlock(SeekableByteChannel channel, FractalHeapHeader header, HdfFixedPoint address, FixedPointDatatype sizeOfOffset, long expectedBlockOffset, HdfFixedPoint filteredSize, long filterMask) throws IOException, InvocationTargetException, InstantiationException, IllegalAccessException {
243+
if (address.isUndefined()) {
240244
throw new IOException("Invalid direct block address");
241245
}
242-
reader.seek(address);
243-
String sig = new String(reader.readBytes(4));
246+
channel.position(address.getInstance(Long.class));
247+
//
248+
int headerSize = 4 + 1 + sizeOfOffset.getSize() + header.offsetBytes + (header.checksumDirect ? 4 : 0);
249+
ByteBuffer headerBuffer = ByteBuffer.allocate(headerSize).order(ByteOrder.LITTLE_ENDIAN);
250+
int bytesRead = channel.read(headerBuffer);
251+
if ( headerSize != bytesRead)
252+
throw new IllegalStateException("Incorrect bytesRead: " + bytesRead + ": expected " + headerSize);
253+
headerBuffer.flip();
254+
String sig = new String(Arrays.copyOfRange(headerBuffer.array(), 0, 4), StandardCharsets.US_ASCII);
244255
if (!Objects.equals(sig, "FHDB")) {
245256
throw new IOException("Invalid direct block signature");
246257
}
247-
byte version = reader.readByte();
258+
headerBuffer.position(4);
259+
byte version = headerBuffer.get();
248260
if (version != 0) {
249261
throw new IOException("Unsupported version");
250262
}
251-
long heapHeader = reader.readVariableLong(header.sizeOfOffsets);
252-
if (heapHeader == undefined) {
263+
HdfFixedPoint heapHeader = HdfReadUtils.readHdfFixedPointFromBuffer(sizeOfOffset, headerBuffer);
264+
if (heapHeader.isUndefined()) {
253265
throw new IOException("Invalid heap header address in direct block");
254266
}
255-
long blockOffset = reader.readVariableLong(header.offsetBytes);
256-
if (blockOffset != expectedBlockOffset) {
267+
HdfFixedPoint blockOffset = HdfReadUtils.readHdfFixedPointFromBuffer(sizeOfOffset, headerBuffer);
268+
if (blockOffset.getInstance(Long.class) != expectedBlockOffset) {
257269
throw new IOException("Block offset mismatch");
258270
}
259-
int checksum = 0;
271+
headerBuffer.position(4 + 1 + sizeOfOffset.getSize()+header.offsetBytes);
272+
long checksum = 0;
260273
if (header.checksumDirect) {
261-
checksum = reader.readInt(); // checksum, not verifying
274+
checksum = Integer.toUnsignedLong(headerBuffer.getInt()); // checksum, not verifying
262275
}
263-
int headerSize = 4 + 1 + header.sizeOfOffsets + header.offsetBytes + (header.checksumDirect ? 4 : 0);
264276
long blockSize = getBlockSize(header, expectedBlockOffset);
265277
long dataSize;
266-
// if (filteredSize != -1) {
267-
// dataSize = filteredSize - headerSize;
268-
// } else {
269-
// dataSize = blockSize - headerSize;
270-
// }
271-
if (filteredSize != -1) {
272-
dataSize = filteredSize;
278+
if (!filteredSize.isUndefined()) {
279+
dataSize = filteredSize.getInstance(Long.class);
273280
} else {
274281
dataSize = blockSize;
275282
}
276283
if (dataSize < 0) {
277284
throw new IOException("Invalid data size in direct block");
278285
}
279-
byte[] data = reader.readBytes((int) dataSize);
286+
headerBuffer = ByteBuffer.allocate((int) dataSize);
287+
bytesRead = channel.read(headerBuffer);
288+
if ( bytesRead != dataSize)
289+
throw new IllegalStateException();
290+
headerBuffer.flip();
291+
292+
byte[] data = headerBuffer.array();
280293
DirectBlock db = new DirectBlock();
281-
db.blockOffset = blockOffset;
294+
db.blockOffset = blockOffset.getInstance(Long.class);
282295
db.blockSize = blockSize;
283296
db.data = data;
284297
db.filterMask = filterMask;
@@ -287,35 +300,17 @@ private static Block readDirectBlock(HdfReader reader, FractalHeapHeader header,
287300
return db;
288301
}
289302

290-
private static Block readIndirectBlock(HdfReader reader, FractalHeapHeader header, long address, long expectedBlockOffset, long iblockSize, short passedNrows) throws IOException {
291-
long undefined = -1L;
292-
if (address == undefined) {
303+
private static Block readIndirectBlock(SeekableByteChannel channel, FractalHeapHeader header, FixedPointDatatype sizeOfOffset, FixedPointDatatype sizeOfLength, HdfFixedPoint address, long expectedBlockOffset, long iblockSize, int passedNrows) throws IOException, InvocationTargetException, InstantiationException, IllegalAccessException {
304+
if (address.isUndefined()) {
293305
throw new IOException("Invalid indirect block address");
294306
}
295-
reader.seek(address);
296-
String sig = new String(reader.readBytes(4));
297-
if (!Objects.equals(sig, "FHIB")) {
298-
throw new IOException("Invalid indirect block signature");
299-
}
300-
byte version = reader.readByte();
301-
if (version != 0) {
302-
throw new IOException("Unsupported version");
303-
}
304-
long heapHeader = reader.readVariableLong(header.sizeOfOffsets);
305-
if (heapHeader == undefined) {
306-
throw new IOException("Invalid heap header address in indirect block");
307-
}
308-
long blockOffset = reader.readVariableLong(header.offsetBytes);
309-
if (blockOffset != expectedBlockOffset) {
310-
throw new IOException("Block offset mismatch");
311-
}
307+
channel.position(address.getInstance(Long.class));
312308
IndirectBlock ib = new IndirectBlock();
313-
ib.blockOffset = blockOffset;
314-
ib.children = new ArrayList<>();
315-
short nrows;
309+
int nrows;
310+
long startingBlockSize = header.startingBlockSize.getInstance(Long.class);
316311
if (iblockSize > 0) {
317312
long covered = 0;
318-
long current = header.startingBlockSize;
313+
long current = startingBlockSize;
319314
int nr = 0;
320315
while (covered < iblockSize) {
321316
covered += (long) header.tableWidth * current;
@@ -326,50 +321,90 @@ private static Block readIndirectBlock(HdfReader reader, FractalHeapHeader heade
326321
} else {
327322
nrows = passedNrows;
328323
}
324+
int plusSize = 0;
329325
ib.nrows = nrows;
326+
for (short r = 0; r < nrows; r++) {
327+
for (int c = 0; c < header.tableWidth; c++) {
328+
plusSize += sizeOfOffset.getSize();
329+
boolean isDirect = r < header.maxDblockRows;
330+
if (header.hasFilters && isDirect) {
331+
plusSize += sizeOfLength.getSize();
332+
plusSize += 4;
333+
}
334+
}
335+
}
336+
plusSize += 4; // checksum
337+
338+
int headerSize = 4 + 1 + sizeOfOffset.getSize() + header.offsetBytes + plusSize;
339+
ByteBuffer headerBuffer = ByteBuffer.allocate(headerSize);
340+
int bytesRead = channel.read(headerBuffer);
341+
if ( headerSize != bytesRead)
342+
throw new IllegalStateException("Incorrect bytesRead: " + bytesRead + ": expected " + headerSize);
343+
headerBuffer.flip();
344+
345+
String sig = new String(Arrays.copyOfRange(headerBuffer.array(), 0, 4), StandardCharsets.US_ASCII);
346+
if (!Objects.equals(sig, "FHIB")) {
347+
throw new IOException("Invalid indirect block signature");
348+
}
349+
headerBuffer.position(4);
350+
byte version = headerBuffer.get();
351+
if (version != 0) {
352+
throw new IOException("Unsupported version");
353+
}
354+
HdfFixedPoint heapHeader = HdfReadUtils.readHdfFixedPointFromBuffer(sizeOfOffset, headerBuffer);
355+
if (heapHeader.isUndefined()) {
356+
throw new IOException("Invalid heap header address in indirect block");
357+
}
358+
HdfFixedPoint blockOffset = HdfReadUtils.readHdfFixedPointFromBuffer(sizeOfOffset, headerBuffer);
359+
if (blockOffset.getInstance(Long.class) != expectedBlockOffset) {
360+
throw new IOException("Block offset mismatch");
361+
}
362+
headerBuffer.position(4 + 1 + sizeOfOffset.getSize() + header.offsetBytes);
363+
ib.blockOffset = blockOffset.getInstance(Long.class);
364+
ib.children = new ArrayList<>();
330365
List<ChildInfo> childInfos = new ArrayList<>();
331-
long currentOffset = expectedBlockOffset;
366+
long currentOffset = expectedBlockOffset; // expectedBlockOffset;
332367
for (short r = 0; r < nrows; r++) {
333-
long rowBlockSize = header.startingBlockSize * (1L << r);
368+
long rowBlockSize = startingBlockSize * (1L << r);
334369
for (int c = 0; c < header.tableWidth; c++) {
335-
long childAddress = reader.readVariableLong(header.sizeOfOffsets);
336-
long childFilteredSize = -1;
337-
int childFilterMask = 0;
370+
HdfFixedPoint childAddress = HdfReadUtils.readHdfFixedPointFromBuffer(sizeOfOffset, headerBuffer);
371+
HdfFixedPoint childFilteredSize = sizeOfOffset.undefined();
372+
long childFilterMask = 0;
338373
boolean isDirect = r < header.maxDblockRows;
339374
if (header.hasFilters && isDirect) {
340-
childFilteredSize = reader.readVariableLong(header.sizeOfLengths);
341-
childFilterMask = reader.readInt();
375+
childFilteredSize = HdfReadUtils.readHdfFixedPointFromBuffer(sizeOfLength, headerBuffer);
376+
childFilterMask = headerBuffer.getInt();
342377
}
343-
if (childAddress != undefined) {
344-
long childBlockOffset = currentOffset;
345-
ChildInfo info = new ChildInfo(childAddress, childBlockOffset, isDirect, childFilteredSize, childFilterMask, rowBlockSize);
378+
if (!childAddress.isUndefined()) {
379+
ChildInfo info = new ChildInfo(childAddress, currentOffset, isDirect, childFilteredSize, childFilterMask, rowBlockSize);
346380
childInfos.add(info);
347381
}
348382
currentOffset += rowBlockSize;
349383
}
350384
}
351-
ib.checksum = reader.readInt();
385+
ib.checksum = Integer.toUnsignedLong(headerBuffer.getInt());
352386
for (ChildInfo info : childInfos) {
353-
if (info.address != undefined) {
387+
if (!info.address.isUndefined()) {
354388
Block child;
355389
if (info.isDirect) {
356-
child = readDirectBlock(reader, header, info.address, info.blockOffset, info.filteredSize, info.filterMask);
390+
child = readDirectBlock(channel, header, info.address, sizeOfOffset, info.blockOffset, info.filteredSize, info.filterMask);
357391
} else {
358-
child = readIndirectBlock(reader, header, info.address, info.blockOffset, info.blockSize, (short) 0);
392+
child = readIndirectBlock(channel, header, sizeOfOffset, sizeOfLength, info.address, info.blockOffset, info.blockSize, (short) 0);
359393
}
360394
ib.children.add(child);
361395
}
362396
}
363397
return ib;
364398
}
365399

366-
private static long getBlockSize(FractalHeapHeader header, long blockOffset) {
400+
private static long getBlockSize(FractalHeapHeader header, long blockOffset) throws IOException, InvocationTargetException, InstantiationException, IllegalAccessException {
401+
long startingBlockSize = header.startingBlockSize.getInstance(Long.class);
367402
if (blockOffset == 0 && header.currentNumRowsRootIndirectBlock == 0) {
368-
return header.startingBlockSize;
403+
return startingBlockSize;
369404
}
370-
double arg = ((double) blockOffset / (header.tableWidth * header.startingBlockSize)) + 1;
405+
double arg = ((double) blockOffset / (header.tableWidth * header.startingBlockSize.getInstance(Long.class))) + 1;
371406
int row = (int) Math.floor(Math.log(arg) / Math.log(2));
372-
return header.startingBlockSize * (1L << row);
407+
return startingBlockSize * (1L << row);
373408
}
374409

375410
public byte[] getObject(ParsedHeapId heapId) {
@@ -452,25 +487,25 @@ public static class DirectBlock extends Block {
452487
public int headerSize;
453488
long blockSize;
454489
byte[] data;
455-
int filterMask;
456-
int checksum;
490+
long filterMask;
491+
long checksum;
457492
}
458493

459494
public static class IndirectBlock extends Block {
460-
short nrows;
495+
int nrows;
461496
List<Block> children;
462-
int checksum;
497+
long checksum;
463498
}
464499

465500
private static class ChildInfo {
466-
long address;
501+
HdfFixedPoint address;
467502
long blockOffset;
468503
boolean isDirect;
469-
long filteredSize;
470-
int filterMask;
504+
HdfFixedPoint filteredSize;
505+
long filterMask;
471506
long blockSize;
472507

473-
public ChildInfo(long address, long blockOffset, boolean isDirect, long filteredSize, int filterMask, long blockSize) {
508+
public ChildInfo(HdfFixedPoint address, long blockOffset, boolean isDirect, HdfFixedPoint filteredSize, long filterMask, long blockSize) {
474509
this.address = address;
475510
this.blockOffset = blockOffset;
476511
this.isDirect = isDirect;
@@ -480,6 +515,21 @@ public ChildInfo(long address, long blockOffset, boolean isDirect, long filtered
480515
}
481516
}
482517

518+
// public static long readVariableLong(byte[] bytes, int size) {
519+
// long val = 0;
520+
// for (int i = 0; i < size; i++) {
521+
// val |= (bytes[i] & 0xFFL) << (8 * i);
522+
// }
523+
// // If the most significant bit is set, check if all bits are 1 (undefined address)
524+
// if (size < 8 && (val & (1L << (size * 8 - 1))) != 0) {
525+
// long mask = (1L << (size * 8)) - 1;
526+
// if (val == mask) {
527+
// return -1L; // Undefined address
528+
// }
529+
// }
530+
// return val;
531+
// }
532+
//
483533
// private static class HdfReader {
484534
// private final SeekableByteChannel channel;
485535
//

0 commit comments

Comments
 (0)