Пример #1
0
        private IEnumerable <BTree1Node <T> > EnumerateNodes(BTree1Node <T> node)
        {
            // internal node
            if (node.NodeLevel > 0)
            {
                foreach (var address in node.ChildAddresses)
                {
                    _reader.Seek((long)address, SeekOrigin.Begin);

                    var childNode = new BTree1Node <T>(_reader, _superblock, _decodeKey);

                    // internal node
                    if ((node.NodeLevel - 1) > 0)
                    {
                        var internalNodes = this.EnumerateNodes(childNode);

                        foreach (var internalNode in internalNodes)
                        {
                            yield return(internalNode);
                        }
                    }
                    // leaf node
                    else
                    {
                        yield return(childNode);
                    }
                }
            }
            // leaf node
            else
            {
                yield return(node);
            }
        }
Пример #2
0
        public bool TryFindUserData <TUserData>([NotNullWhen(returnValue: true)] out TUserData userData,
                                                Func <T, T, int> compare3,
                                                FoundDelegate <T, TUserData> found)
            where TUserData : struct
        {
            userData = default;

            // H5B.c (H5B_find)

            /*
             * Perform a binary search to locate the child which contains
             * the thing for which we're searching.
             */
            (var index, var cmp) = this.LocateRecord(compare3);

            /* Check if not found */
            if (cmp != 0)
            {
                return(false);
            }

            /*
             * Follow the link to the subtree or to the data node.
             */
            var childAddress = this.ChildAddresses[(int)index];
            var key          = this.Keys[index];

            if (this.NodeLevel > 0)
            {
                _reader.Seek((long)childAddress, SeekOrigin.Begin);
                var subtree = new BTree1Node <T>(_reader, _superblock, _decodeKey);

                if (subtree.TryFindUserData(out userData, compare3, found))
                {
                    return(true);
                }
            }
            else
            {
                if (found(childAddress, key, out userData))
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #3
0
        private void ReadChunkedBTree1(Span <byte> buffer, byte rank, ulong chunkSize)
        {
            // btree1
            Func <BTree1RawDataChunksKey> decodeKey = () => this.DecodeRawDataChunksKey(rank);
            var btree1         = new BTree1Node <BTree1RawDataChunksKey>(this.Context.Reader, this.Context.Superblock, decodeKey);
            var nodes          = btree1.EnumerateNodes().ToList();
            var childAddresses = nodes.SelectMany(key => key.ChildAddresses).ToArray();
            var keys           = nodes.SelectMany(key => key.Keys).ToArray();

            // read data
            var offset     = 0UL;
            var chunkCount = (ulong)childAddresses.Length;

            for (ulong i = 0; i < chunkCount; i++)
            {
                var rawChunkSize = keys[i].ChunkSize;
                this.SeekSliceAndReadChunk(offset, chunkSize, rawChunkSize, childAddresses[i], buffer);
                offset += rawChunkSize;
            }
        }
Пример #4
0
        private bool TryGetReference(string name, H5LinkAccess linkAccess, out H5NamedReference namedReference)
        {
            namedReference = default;

            /* cached data */
            if (_scratchPad != null)
            {
                var localHeap = _scratchPad.LocalHeap;

                this.Context.Reader.Seek((long)_scratchPad.BTree1Address, SeekOrigin.Begin);
                var tree = new BTree1Node <BTree1GroupKey>(this.Context.Reader, this.Context.Superblock, this.DecodeGroupKey);
                var b    = tree.EnumerateNodes().ToList();

                this.Context.Reader.Seek((long)_scratchPad.NameHeapAddress, SeekOrigin.Begin);
                var heap = new LocalHeap(this.Context.Reader, this.Context.Superblock);
                var c    = heap.GetObjectName(0);


                var success = _scratchPad
                              .GetBTree1(this.DecodeGroupKey)
                              .TryFindUserData(out var userData,
                                               (leftKey, rightKey) => this.NodeCompare3(localHeap, name, leftKey, rightKey),
                                               (ulong address, out BTree1SymbolTableUserData userData) => this.NodeFound(localHeap, name, address, out userData));

                if (success)
                {
                    namedReference = this.GetObjectReferencesForSymbolTableEntry(localHeap, userData.SymbolTableEntry, linkAccess);
                    return(true);
                }
            }
            else
            {
                var symbolTableHeaderMessages = this.Header.GetMessages <SymbolTableMessage>();

                if (symbolTableHeaderMessages.Any())
                {
                    /* Original approach.
                     * IV.A.2.r.: The Symbol Table Message
                     * Required for "old style" groups; may not be repeated. */

                    if (symbolTableHeaderMessages.Count() != 1)
                    {
                        throw new Exception("There may be only a single symbol table header message.");
                    }

                    var smessage  = symbolTableHeaderMessages.First();
                    var localHeap = smessage.LocalHeap;

                    var success = smessage
                                  .GetBTree1(this.DecodeGroupKey)
                                  .TryFindUserData(out var userData,
                                                   (leftKey, rightKey) => this.NodeCompare3(localHeap, name, leftKey, rightKey),
                                                   (ulong address, out BTree1SymbolTableUserData userData) => this.NodeFound(localHeap, name, address, out userData));

                    if (success)
                    {
                        namedReference = this.GetObjectReferencesForSymbolTableEntry(localHeap, userData.SymbolTableEntry, linkAccess);
                        return(true);
                    }
                }
                else
                {
                    var linkInfoMessages = this.Header.GetMessages <LinkInfoMessage>();

                    if (linkInfoMessages.Any())
                    {
                        if (linkInfoMessages.Count() != 1)
                        {
                            throw new Exception("There may be only a single link info message.");
                        }

                        var lmessage = linkInfoMessages.First();

                        /* New (1.8) indexed format (in combination with Group Info Message)
                         * IV.A.2.c. The Link Info Message
                         * Optional; may not be repeated. */
                        if (!this.Context.Superblock.IsUndefinedAddress(lmessage.BTree2NameIndexAddress))
                        {
                            if (this.TryGetLinkMessageFromLinkInfoMessage(lmessage, name, out var linkMessage))
                            {
                                namedReference = this.GetObjectReference(linkMessage, linkAccess);
                                return(true);
                            }
                        }

                        /* New (1.8) compact format
                         * IV.A.2.g. The Link Message
                         * A group is storing its links compactly when the fractal heap address
                         * in the Link Info Message is set to the "undefined address" value. */
                        else
                        {
                            var linkMessage = this.Header
                                              .GetMessages <LinkMessage>()
                                              .FirstOrDefault(message => message.LinkName == name);

                            if (linkMessage != null)
                            {
                                namedReference = this.GetObjectReference(linkMessage, linkAccess);
                                return(true);
                            }
                        }
                    }
                    else
                    {
                        throw new Exception("No link information found in object header.");
                    }
                }
            }

            return(false);
        }