示例#1
0
        protected override ChunkInfo GetChunkInfo(ulong[] chunkIndices)
        {
            if (this.Dataset.InternalFilterPipeline is null)
            {
                if (_btree2_no_filter is null)
                {
                    this.Dataset.Context.Reader.Seek((long)this.Dataset.InternalDataLayout.Address, SeekOrigin.Begin);

                    Func <BTree2Record10> decodeKey
                        = () => this.DecodeRecord10(this.ChunkRank);

                    _btree2_no_filter = new BTree2Header <BTree2Record10>(this.Dataset.Context.Reader, this.Dataset.Context.Superblock, decodeKey);
                }

                // get record
                var success = _btree2_no_filter.TryFindRecord(out var record, record =>
                {
                    // H5Dbtree2.c (H5D__bt2_compare)
                    return(H5Utils.VectorCompare(this.ChunkRank, chunkIndices, record.ScaledOffsets));
                });

                return(success
                    ? new ChunkInfo(record.Address, this.ChunkByteSize, 0)
                    : ChunkInfo.None);
            }
            else
            {
                if (_btree2_filter is null)
                {
                    this.Dataset.Context.Reader.Seek((long)this.Dataset.InternalDataLayout.Address, SeekOrigin.Begin);
                    var chunkSizeLength = H5Utils.ComputeChunkSizeLength(this.ChunkByteSize);

                    Func <BTree2Record11> decodeKey =
                        () => this.DecodeRecord11(this.ChunkRank, chunkSizeLength);

                    _btree2_filter = new BTree2Header <BTree2Record11>(this.Dataset.Context.Reader, this.Dataset.Context.Superblock, decodeKey);
                }

                // get record
                var success = _btree2_filter.TryFindRecord(out var record, record =>
                {
                    // H5Dbtree2.c (H5D__bt2_compare)
                    return(H5Utils.VectorCompare(this.ChunkRank, chunkIndices, record.ScaledOffsets));
                });

                return(success
                    ? new ChunkInfo(record.Address, record.ChunkSize, record.FilterMask)
                    : ChunkInfo.None);
            }
        }
        protected override ChunkInfo GetChunkInfo(ulong[] chunkIndices)
        {
            // H5Dfarray.c (H5D__farray_idx_get_addr)

            /* Calculate the index of this chunk */
            var chunkIndex = chunkIndices.ToLinearIndexPrecomputed(this.DownMaxChunkCounts);

            /* Check for filters on chunks */
            if (this.Dataset.InternalFilterPipeline is not null)
            {
                var chunkSizeLength = H5Utils.ComputeChunkSizeLength(this.ChunkByteSize);

                var element = this.GetElement(chunkIndex, reader =>
                {
                    return(new FilteredDataBlockElement()
                    {
                        Address = this.Dataset.Context.Superblock.ReadOffset(reader),
                        ChunkSize = (uint)H5Utils.ReadUlong(reader, chunkSizeLength),
                        FilterMask = reader.ReadUInt32()
                    });
                });

                return(element is not null
                    ? new ChunkInfo(element.Address, element.ChunkSize, element.FilterMask)
                    : ChunkInfo.None);
            }
            else
            {
                var element = this.GetElement(chunkIndex, reader =>
                {
                    return(new DataBlockElement()
                    {
                        Address = this.Dataset.Context.Superblock.ReadOffset(reader)
                    });
                });

                return(element is not null
                    ? new ChunkInfo(element.Address, this.ChunkByteSize, 0)
                    : ChunkInfo.None);
            }
        }
        protected override ChunkInfo GetChunkInfo(ulong[] chunkIndices)
        {
            // H5Dearray.c (H5D__earray_idx_get_addr)

            /* Check for unlimited dim. not being the slowest-changing dim. */
            ulong chunkIndex;

            if (_unlimitedDim > 0)
            {
                var swizzledCoords = new ulong[this.ChunkRank];

                /* Compute coordinate offset from scaled offset */
                for (int i = 0; i < this.ChunkRank; i++)
                {
                    swizzledCoords[i] = chunkIndices[i] * this.ChunkDims[i];
                }

                H5Utils.SwizzleCoords(swizzledCoords, _unlimitedDim);

                /* Calculate the index of this chunk */
                var swizzledScaledDims = swizzledCoords
                                         .Select((swizzledCoord, i) => H5Utils.CeilDiv(swizzledCoord, _swizzledChunkDims[i]))
                                         .ToArray();

                chunkIndex = swizzledScaledDims.ToLinearIndexPrecomputed(_swizzledDownMaxChunkCounts);
            }
            else
            {
                /* Calculate the index of this chunk */
                chunkIndex = chunkIndices.ToLinearIndexPrecomputed(this.DownMaxChunkCounts);
            }

            /* Check for filters on chunks */
            if (this.Dataset.InternalFilterPipeline is not null)
            {
                var chunkSizeLength = H5Utils.ComputeChunkSizeLength(this.ChunkByteSize);

                var element = this.GetElement(chunkIndex, reader =>
                {
                    return(new FilteredDataBlockElement()
                    {
                        Address = this.Dataset.Context.Superblock.ReadOffset(reader),
                        ChunkSize = (uint)H5Utils.ReadUlong(reader, chunkSizeLength),
                        FilterMask = reader.ReadUInt32()
                    });
                });

                return(element is not null
                    ? new ChunkInfo(element.Address, element.ChunkSize, element.FilterMask)
                    : ChunkInfo.None);
            }
            else
            {
                var element = this.GetElement(chunkIndex, reader =>
                {
                    return(new DataBlockElement()
                    {
                        Address = this.Dataset.Context.Superblock.ReadOffset(reader)
                    });
                });

                return(element is not null
                    ? new ChunkInfo(element.Address, this.ChunkByteSize, 0)
                    : ChunkInfo.None);
            }
        }
        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]);
                    }
                }
            }
        }