Exemple #1
0
        public List <long> AllPages()
        {
            var results = new List <long>();
            var stack   = new Stack <TreePage>();
            var root    = _llt.GetReadOnlyTreePage(State.RootPageNumber);

            stack.Push(root);

            Slice key = default(Slice);

            while (stack.Count > 0)
            {
                var p = stack.Pop();
                results.Add(p.PageNumber);

                for (int i = 0; i < p.NumberOfEntries; i++)
                {
                    var node       = p.GetNode(i);
                    var pageNumber = node->PageNumber;
                    if (p.IsBranch)
                    {
                        stack.Push(_llt.GetReadOnlyTreePage(pageNumber));
                    }
                    else if (node->Flags == TreeNodeFlags.PageRef)
                    {
                        // This is an overflow page
                        var overflowPage  = _llt.GetReadOnlyTreePage(pageNumber);
                        var numberOfPages = _llt.DataPager.GetNumberOfOverflowPages(overflowPage.OverflowSize);
                        for (long j = 0; j < numberOfPages; ++j)
                        {
                            results.Add(overflowPage.PageNumber + j);
                        }
                    }
                    else if (node->Flags == TreeNodeFlags.MultiValuePageRef)
                    {
                        key = TreeNodeHeader.ToSlicePtr(_tx.Allocator, node, ByteStringType.Mutable);
                        var tree = OpenMultiValueTree(key, node);
                        results.AddRange(tree.AllPages());
                    }
                    else
                    {
                        if ((State.Flags & TreeFlags.FixedSizeTrees) == TreeFlags.FixedSizeTrees)
                        {
                            var valueReader = TreeNodeHeader.Reader(_llt, node);
                            var valueSize   = ((FixedSizeTreeHeader.Embedded *)valueReader.Base)->ValueSize;

                            var fixedSizeTreeName = p.GetNodeKey(_llt, i);

                            var fixedSizeTree = new FixedSizeTree(_llt, this, fixedSizeTreeName, valueSize);

                            var pages = fixedSizeTree.AllPages();
                            results.AddRange(pages);
                        }
                    }
                }
            }
            return(results);
        }
Exemple #2
0
        public ReadResult Read(Slice key)
        {
            TreeNodeHeader *node;
            var             p = FindPageFor(key, out node);

            if (p.LastMatch != 0)
            {
                return(null);
            }

            return(new ReadResult(TreeNodeHeader.Reader(_llt, node), node->Version));
        }
Exemple #3
0
        private void HandleUncompressedNodes(DecompressedLeafPage decompressedPage, TreePage p, DecompressionUsage usage)
        {
            int numberOfEntries = p.NumberOfEntries;

            for (var i = 0; i < numberOfEntries; i++)
            {
                var uncompressedNode = p.GetNode(i);

                Slice nodeKey;
                using (TreeNodeHeader.ToSlicePtr(_tx.Allocator, uncompressedNode, out nodeKey))
                {
                    if (uncompressedNode->Flags == TreeNodeFlags.CompressionTombstone)
                    {
                        HandleTombstone(decompressedPage, nodeKey, usage);
                        continue;
                    }

                    if (decompressedPage.HasSpaceFor(_llt, TreeSizeOf.NodeEntry(uncompressedNode)) == false)
                    {
                        throw new InvalidOperationException("Could not add uncompressed node to decompressed page");
                    }

                    int index;

                    if (decompressedPage.NumberOfEntries > 0)
                    {
                        Slice lastKey;
                        using (decompressedPage.GetNodeKey(_llt, decompressedPage.NumberOfEntries - 1, out lastKey))
                        {
                            // optimization: it's very likely that uncompressed nodes have greater keys than compressed ones
                            // when we insert sequential keys

                            var cmp = SliceComparer.CompareInline(nodeKey, lastKey);

                            if (cmp > 0)
                            {
                                index = decompressedPage.NumberOfEntries;
                            }
                            else
                            {
                                if (cmp == 0)
                                {
                                    // update of the last entry, just decrement NumberOfEntries in the page and
                                    // put it at the last position

                                    index = decompressedPage.NumberOfEntries - 1;
                                    decompressedPage.Lower -= Constants.Tree.NodeOffsetSize;
                                }
                                else
                                {
                                    index = decompressedPage.NodePositionFor(_llt, nodeKey);

                                    if (decompressedPage.LastMatch == 0) // update
                                    {
                                        decompressedPage.RemoveNode(index);

                                        if (usage == DecompressionUsage.Write)
                                        {
                                            State.NumberOfEntries--;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // all uncompressed nodes were compresion tombstones which deleted all entries from the decompressed page
                        index = 0;
                    }

                    switch (uncompressedNode->Flags)
                    {
                    case TreeNodeFlags.PageRef:
                        decompressedPage.AddPageRefNode(index, nodeKey, uncompressedNode->PageNumber);
                        break;

                    case TreeNodeFlags.Data:
                        var pos       = decompressedPage.AddDataNode(index, nodeKey, uncompressedNode->DataSize);
                        var nodeValue = TreeNodeHeader.Reader(_llt, uncompressedNode);
                        Memory.Copy(pos, nodeValue.Base, nodeValue.Length);
                        break;

                    case TreeNodeFlags.MultiValuePageRef:
                        throw new NotSupportedException("Multi trees do not support compression");

                    default:
                        throw new NotSupportedException("Invalid node type to copye: " + uncompressedNode->Flags);
                    }
                }
            }
        }
 public ValueReader CreateReaderForCurrent()
 {
     return(TreeNodeHeader.Reader(_tx, Current));
 }