Esempio n. 1
0
        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);
            }
        }
Esempio n. 2
0
        private void ReadFixedArray(Span <byte> buffer, ulong chunkSize)
        {
            var chunkSizeLength = this.ComputeChunkSizeLength(chunkSize);
            var header          = new FixedArrayHeader(this.Context.Reader, this.Context.Superblock, chunkSizeLength);
            var dataBlock       = header.DataBlock;

            IEnumerable <DataBlockElement> elements;

            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, dataBlock.ElementsPerPage, dataBlock.ClientID, chunkSizeLength);
                    pages.Add(page);
                }

                elements = pages.SelectMany(page => page.Elements);
            }
            else
            {
                elements = dataBlock.Elements.AsEnumerable();
            }

            var offset     = 0UL;
            var index      = 0UL;
            var enumerator = elements.GetEnumerator();

            for (ulong i = 0; i < header.EntriesCount; i++)
            {
                enumerator.MoveNext();
                var element = enumerator.Current;

                // if page/element is initialized (see also datablock.PageBitmap)
                if (element.Address > 0)
                {
                    this.SeekSliceAndReadChunk(offset, chunkSize, element.ChunkSize, element.Address, buffer);
                }

                offset += chunkSize;
                index++;
            }
        }
        private T?LookupElement <T>(ulong index, Func <H5BinaryReader, T> decode) where T : DataBlockElement
        {
            // H5FA.c (H5FA_get)

            /* Get the data block */
            this.Dataset.Context.Reader.Seek((long)_header.DataBlockAddress, SeekOrigin.Begin);

            var dataBlock = new FixedArrayDataBlock <T>(
                this.Dataset.Context.Reader,
                this.Dataset.Context.Superblock,
                _header,
                decode);

            /* Check for paged data block */
            if (dataBlock.PageCount > 0)
            {
                /* Compute the page index */
                var pageIndex       = index / dataBlock.ElementsPerPage;
                var pageBitmapEntry = dataBlock.PageBitmap[pageIndex / 8];
                var bitMaskIndex    = (int)pageIndex % 8;

                /* Check if the page is defined yet */
                if ((pageBitmapEntry & H5Utils.SequentialBitMask[bitMaskIndex]) > 0)
                {
                    /* Compute the element index */
                    var elementIndex = index % dataBlock.ElementsPerPage;

                    /* Compute the address of the data block */
                    var pageSize    = dataBlock.ElementsPerPage * _header.EntrySize + 4;
                    var pageAddress = this.Dataset.Context.Reader.BaseStream.Position + (long)(pageIndex * pageSize);

                    /* Check for using last page, to set the number of elements on the page */
                    ulong elementCount;

                    if (pageIndex + 1 == dataBlock.PageCount)
                    {
                        elementCount = dataBlock.LastPageElementCount;
                    }

                    else
                    {
                        elementCount = dataBlock.ElementsPerPage;
                    }

                    /* Protect the data block page */
                    this.Dataset.Context.Reader.Seek(pageAddress, SeekOrigin.Begin);

                    var page = new DataBlockPage <T>(
                        this.Dataset.Context.Reader,
                        elementCount,
                        decode);

                    /* Retrieve element from data block */
                    return(page.Elements[elementIndex]);
                }
                else
                {
                    /* Call the class's 'fill' callback */
                    return(null);
                }
            }
            else
            {
                /* Retrieve element from data block */
                return(dataBlock.Elements[index]);
            }
        }
        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]);
                    }
                }
            }
        }