// for later: H5EA__lookup_elmt private void ReadExtensibleArray(Span <byte> buffer, ulong chunkSize) { var chunkSizeLength = this.ComputeChunkSizeLength(chunkSize); var header = new ExtensibleArrayHeader(this.Context.Reader, this.Context.Superblock, chunkSizeLength); var indexBlock = header.IndexBlock; var elementIndex = 0U; var elements = new List <DataBlockElement>() .AsEnumerable(); // elements elements = elements.Concat(indexBlock.Elements); // data blocks ReadDataBlocks(indexBlock.DataBlockAddresses); // secondary blocks #warning Is there any precalculated way to avoid checking all addresses? var addresses = indexBlock .SecondaryBlockAddresses .Where(address => !this.Context.Superblock.IsUndefinedAddress(address)); foreach (var secondaryBlockAddress in addresses) { this.Context.Reader.Seek((long)secondaryBlockAddress, SeekOrigin.Begin); var secondaryBlockIndex = header.ComputeSecondaryBlockIndex(elementIndex + header.IndexBlockElementsCount); var secondaryBlock = new ExtensibleArraySecondaryBlock(this.Context.Reader, this.Context.Superblock, header, secondaryBlockIndex); ReadDataBlocks(secondaryBlock.DataBlockAddresses); } var offset = 0UL; foreach (var element in elements) { // if page/element is initialized (see also datablock.PageBitmap) #warning Is there any precalculated way to avoid checking all addresses? if (element.Address > 0 && !this.Context.Superblock.IsUndefinedAddress(element.Address)) { this.SeekSliceAndReadChunk(offset, chunkSize, element.ChunkSize, element.Address, buffer); } offset += chunkSize; } void ReadDataBlocks(ulong[] dataBlockAddresses) { #warning Is there any precalculated way to avoid checking all addresses? dataBlockAddresses = dataBlockAddresses .Where(address => !this.Context.Superblock.IsUndefinedAddress(address)) .ToArray(); foreach (var dataBlockAddress in dataBlockAddresses) { this.Context.Reader.Seek((long)dataBlockAddress, SeekOrigin.Begin); var newElements = this.ReadExtensibleArrayDataBlock(header, chunkSizeLength, elementIndex); elements = elements.Concat(newElements); elementIndex += (uint)newElements.Length; } } }
private T?LookupElement <T>(ulong index, Func <H5BinaryReader, T> decode) where T : DataBlockElement { // H5EA.c (H5EA__lookup_elmt) var chunkSizeLength = H5Utils.ComputeChunkSizeLength(this.ChunkByteSize); /* Check if we should create the index block */ if (this.Dataset.Context.Superblock.IsUndefinedAddress(_header.IndexBlockAddress)) { return(null); } /* Protect index block */ if (_indexBlock is null) { this.Dataset.Context.Reader.Seek((long)_header.IndexBlockAddress, SeekOrigin.Begin); _indexBlock = new ExtensibleArrayIndexBlock <T>( this.Dataset.Context.Reader, this.Dataset.Context.Superblock, _header, decode); } var indexBlock = (ExtensibleArrayIndexBlock <T>)_indexBlock; /* Check if element is in index block */ if (index < _header.IndexBlockElementsCount) { return(indexBlock.Elements[index]); } else { /* Get super block index where element is located */ var secondaryBlockIndex = _header.ComputeSecondaryBlockIndex(index); /* Adjust index to offset in super block */ var elementIndex = index - (_header.IndexBlockElementsCount + _header.SecondaryBlockInfos[secondaryBlockIndex].ElementStartIndex); /* Check for data block containing element address in the index block */ if (secondaryBlockIndex < indexBlock.SecondaryBlockDataBlockAddressCount) { /* Compute the data block index in index block */ var dataBlockIndex = _header.SecondaryBlockInfos[secondaryBlockIndex].DataBlockStartIndex + elementIndex / _header.SecondaryBlockInfos[secondaryBlockIndex].ElementsCount; /* Check if the data block has been allocated on disk yet */ if (this.Dataset.Context.Superblock.IsUndefinedAddress(indexBlock.DataBlockAddresses[dataBlockIndex])) { return(null); } /* Protect data block */ this.Dataset.Context.Reader.Seek((long)indexBlock.DataBlockAddresses[dataBlockIndex], SeekOrigin.Begin); var elementsCount = _header.SecondaryBlockInfos[secondaryBlockIndex].ElementsCount; var dataBlock = new ExtensibleArrayDataBlock <T>( this.Dataset.Context.Reader, this.Dataset.Context.Superblock, _header, elementsCount, decode); /* Adjust index to offset in data block */ elementIndex %= _header.SecondaryBlockInfos[secondaryBlockIndex].ElementsCount; /* Set 'thing' info to refer to the data block */ return(dataBlock.Elements[elementIndex]); } else { /* Calculate offset of super block in index block's array */ var secondaryBlockOffset = secondaryBlockIndex - indexBlock.SecondaryBlockDataBlockAddressCount; /* Check if the super block has been allocated on disk yet */ if (this.Dataset.Context.Superblock.IsUndefinedAddress(indexBlock.SecondaryBlockAddresses[secondaryBlockOffset])) { return(null); } /* Protect super block */ this.Dataset.Context.Reader.Seek((long)indexBlock.SecondaryBlockAddresses[secondaryBlockOffset], SeekOrigin.Begin); var secondaryBlock = new ExtensibleArraySecondaryBlock( this.Dataset.Context.Reader, this.Dataset.Context.Superblock, _header, secondaryBlockIndex); /* Compute the data block index in super block */ var dataBlockIndex = elementIndex / secondaryBlock.ElementCount; /* Check if the data block has been allocated on disk yet */ if (this.Dataset.Context.Superblock.IsUndefinedAddress(secondaryBlock.DataBlockAddresses[dataBlockIndex])) { return(null); } /* Adjust index to offset in data block */ elementIndex %= secondaryBlock.ElementCount; /* Check if the data block is paged */ if (secondaryBlock.DataBlockPageCount > 0) { /* Compute page index */ var pageIndex = elementIndex / _header.DataBlockPageElementsCount; /* Compute 'page init' index */ var pageInitIndex = dataBlockIndex * secondaryBlock.DataBlockPageCount + pageIndex; /* Adjust index to offset in data block page */ elementIndex %= _header.DataBlockPageElementsCount; /* Compute data block page address */ var dataBlockPrefixSize = // H5EA_METADATA_PREFIX_SIZE 4UL + 1UL + 1UL + 4UL + // H5EA_DBLOCK_PREFIX_SIZE this.Dataset.Context.Superblock.OffsetsSize + _header.ArrayOffsetsSize + // H5EA_DBLOCK_SIZE secondaryBlock.ElementCount * _header.ElementSize + /* Elements in data block */ secondaryBlock.DataBlockPageCount * 4; /* Checksum for each page */ var dataBlockPageAddress = secondaryBlock.DataBlockAddresses[dataBlockIndex] + dataBlockPrefixSize + (pageIndex * secondaryBlock.DataBlockPageSize); /* Check if page has been initialized yet */ var pageBitmapEntry = secondaryBlock.PageBitmap[pageIndex / 8]; var bitMaskIndex = (int)pageIndex % 8; if ((pageBitmapEntry & H5Utils.SequentialBitMask[bitMaskIndex]) == 0) { return(null); } /* Protect data block page */ this.Dataset.Context.Reader.Seek((long)dataBlockPageAddress, SeekOrigin.Begin); var dataBlockPage = new DataBlockPage <T>( this.Dataset.Context.Reader, _header.DataBlockPageElementsCount, decode); /* Set 'thing' info to refer to the data block page */ return(dataBlockPage.Elements[elementIndex]); } else { /* Protect data block */ this.Dataset.Context.Reader.Seek((long)secondaryBlock.DataBlockAddresses[dataBlockIndex], SeekOrigin.Begin); var dataBlock = new ExtensibleArrayDataBlock <T>( this.Dataset.Context.Reader, this.Dataset.Context.Superblock, _header, secondaryBlock.ElementCount, decode); /* Set 'thing' info to refer to the data block */ return(dataBlock.Elements[elementIndex]); } } } }