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); } }
// 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; } } }
public ExtensibleArrayIndexBlock( H5BinaryReader reader, Superblock superblock, ExtensibleArrayHeader header, Func <H5BinaryReader, T> decode) { // H5EAiblock.c (H5EA__iblock_alloc) this.SecondaryBlockDataBlockAddressCount = 2 * (ulong)Math.Log(header.SecondaryBlockMinimumDataBlockPointerCount, 2); ulong dataBlockPointerCount = (ulong)(2 * (header.SecondaryBlockMinimumDataBlockPointerCount - 1)); ulong secondaryBlockPointerCount = header.SecondaryBlockCount - this.SecondaryBlockDataBlockAddressCount; // signature var signature = reader.ReadBytes(4); H5Utils.ValidateSignature(signature, ExtensibleArrayIndexBlock <T> .Signature); // version this.Version = reader.ReadByte(); // client ID this.ClientID = (ClientID)reader.ReadByte(); // header address this.HeaderAddress = superblock.ReadOffset(reader); // elements this.Elements = Enumerable .Range(0, header.IndexBlockElementsCount) .Select(i => decode(reader)) .ToArray(); // data block addresses this.DataBlockAddresses = new ulong[dataBlockPointerCount]; for (ulong i = 0; i < dataBlockPointerCount; i++) { this.DataBlockAddresses[i] = superblock.ReadOffset(reader); } // secondary block addresses this.SecondaryBlockAddresses = new ulong[secondaryBlockPointerCount]; for (ulong i = 0; i < secondaryBlockPointerCount; i++) { this.SecondaryBlockAddresses[i] = superblock.ReadOffset(reader); } // checksum this.Checksum = reader.ReadUInt32(); }
public ExtensibleArraySecondaryBlock(H5BinaryReader reader, Superblock superblock, ExtensibleArrayHeader header, uint index) { // H5EAsblock.c (H5EA__sblock_alloc) /* Compute/cache information */ var dataBlocksCount = header.SecondaryBlockInfos[index].DataBlockCount; var elementsCount = header.SecondaryBlockInfos[index].ElementsCount; var dataBlockPageCount = 0UL; var dataBlockPageInitBitMaskSize = 0UL; /* Check if # of elements in data blocks requires paging */ if (elementsCount > header.DataBlockPageElementsCount) { /* Compute # of pages in each data block from this super block */ dataBlockPageCount = elementsCount / header.DataBlockPageElementsCount; /* Sanity check that we have at least 2 pages in data block */ if (dataBlockPageCount < 2) { throw new Exception("There must be at least two pages in the data block."); } /* Compute size of buffer for each data block's 'page init' bitmask */ dataBlockPageInitBitMaskSize = dataBlockPageCount + 7 / 8; } // signature var signature = reader.ReadBytes(4); H5Utils.ValidateSignature(signature, ExtensibleArraySecondaryBlock.Signature); // version this.Version = reader.ReadByte(); // client ID this.ClientID = (ClientID)reader.ReadByte(); // header address this.HeaderAddress = superblock.ReadOffset(reader); // block offset this.BlockOffset = H5Utils.ReadUlong(reader, header.ArrayOffsetsSize); // page bitmap // H5EAcache.c (H5EA__cache_sblock_deserialize) /* Check for 'page init' bitmasks for this super block */ if (dataBlockPageCount > 0) { /* Compute total size of 'page init' buffer */ var totalPageInitSize = dataBlocksCount * dataBlockPageInitBitMaskSize; /* Retrieve the 'page init' bitmasks */ this.PageBitmap = reader.ReadBytes((int)totalPageInitSize); } // data block addresses this.DataBlockAddresses = new ulong[dataBlocksCount]; for (ulong i = 0; i < dataBlocksCount; i++) { this.DataBlockAddresses[i] = superblock.ReadOffset(reader); } // checksum this.Checksum = reader.ReadUInt32(); }
public ExtensibleArrayIndexBlock(H5BinaryReader reader, Superblock superblock, ExtensibleArrayHeader header, uint chunkSizeLength) { // H5EAiblock.c (H5EA__iblock_alloc) ulong secondaryBlockDataBlockAddressCount = 2 * (ulong)Math.Log(header.SecondaryBlockMinimumDataBlockPointerCount, 2); ulong dataBlockPointerCount = (ulong)(2 * (header.SecondaryBlockMinimumDataBlockPointerCount - 1)); ulong secondaryBlockPointerCount = header.SecondaryBlockCount - secondaryBlockDataBlockAddressCount; // signature var signature = reader.ReadBytes(4); H5Utils.ValidateSignature(signature, ExtensibleArrayIndexBlock.Signature); // version this.Version = reader.ReadByte(); // client ID this.ClientID = (ClientID)reader.ReadByte(); // header address this.HeaderAddress = superblock.ReadOffset(reader); // elements this.Elements = ArrayIndexUtils.ReadElements(reader, superblock, header.IndexBlockElementsCount, this.ClientID, chunkSizeLength); // data block addresses this.DataBlockAddresses = new ulong[dataBlockPointerCount]; for (ulong i = 0; i < dataBlockPointerCount; i++) { this.DataBlockAddresses[i] = superblock.ReadOffset(reader); } // secondary block addresses this.SecondaryBlockAddresses = new ulong[secondaryBlockPointerCount]; for (ulong i = 0; i < secondaryBlockPointerCount; i++) { this.SecondaryBlockAddresses[i] = superblock.ReadOffset(reader); } // checksum this.Checksum = reader.ReadUInt32(); }
public ExtensibleArrayDataBlock(H5BinaryReader reader, Superblock superblock, ExtensibleArrayHeader header, ulong elementCount, Func <H5BinaryReader, T> decode) { // H5EAdblock.c (H5EA__dblock_alloc) this.PageCount = 0UL; if (elementCount > header.DataBlockPageElementsCount) { /* Set the # of pages in the data block */ this.PageCount = elementCount / header.DataBlockPageElementsCount; } // H5EAcache.c (H5EA__cache_dblock_deserialize) // signature var signature = reader.ReadBytes(4); H5Utils.ValidateSignature(signature, ExtensibleArrayDataBlock <T> .Signature); // version this.Version = reader.ReadByte(); // client ID this.ClientID = (ClientID)reader.ReadByte(); // header address this.HeaderAddress = superblock.ReadOffset(reader); // block offset this.BlockOffset = H5Utils.ReadUlong(reader, header.ArrayOffsetsSize); // elements if (this.PageCount == 0) { this.Elements = Enumerable .Range(0, (int)elementCount) .Select(i => decode(reader)) .ToArray(); } else { this.Elements = new T[0]; } // checksum this.Checksum = reader.ReadUInt32(); }
public ExtensibleArrayDataBlock(H5BinaryReader reader, Superblock superblock, ExtensibleArrayHeader header, uint chunkSizeLength, ulong elementsCount) { // H5EAdblock.c (H5EA__dblock_alloc) this.PageCount = 0UL; if (elementsCount > header.DataBlockPageElementsCount) { /* Set the # of pages in the data block */ this.PageCount = elementsCount / header.DataBlockPageElementsCount; } // H5EAcache.c (H5EA__cache_dblock_deserialize) // signature var signature = reader.ReadBytes(4); H5Utils.ValidateSignature(signature, ExtensibleArrayDataBlock.Signature); // version this.Version = reader.ReadByte(); // client ID this.ClientID = (ClientID)reader.ReadByte(); // header address this.HeaderAddress = superblock.ReadOffset(reader); // block offset this.BlockOffset = H5Utils.ReadUlong(reader, header.ArrayOffsetsSize); // elements if (this.PageCount == 0) { this.Elements = ArrayIndexUtils.ReadElements(reader, superblock, elementsCount, this.ClientID, chunkSizeLength); } // checksum this.Checksum = reader.ReadUInt32(); }