private DataBlockElement[] ReadExtensibleArrayDataBlock(ExtensibleArrayHeader header, uint chunkSizeLength, uint elementIndex) { var secondaryBlockIndex = header.ComputeSecondaryBlockIndex(elementIndex + header.IndexBlockElementsCount); var elementsCount = header.SecondaryBlockInfos[secondaryBlockIndex].ElementsCount; var dataBlock = new ExtensibleArrayDataBlock(this.Context.Reader, this.Context.Superblock, header, chunkSizeLength, elementsCount); if (dataBlock.PageCount > 0) { var pages = new List <DataBlockPage>((int)dataBlock.PageCount); for (int i = 0; i < (int)dataBlock.PageCount; i++) { var page = new DataBlockPage(this.Context.Reader, this.Context.Superblock, header.DataBlockPageElementsCount, dataBlock.ClientID, chunkSizeLength); pages.Add(page); } return(pages .SelectMany(page => page.Elements) .ToArray()); } else { return(dataBlock.Elements); } }
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]); } } } }