Esempio n. 1
0
        private unsafe static void RenderPage(LowLevelTransaction tx, TreePage page, TextWriter sw, string text, bool open)
        {
            sw.WriteLine(
                "<ul><li><input type='checkbox' id='page-{0}' {3} /><label for='page-{0}'>{4}: Page {0:#,#;;0} - {1} - {2:#,#;;0} entries</label><ul>",
                page.PageNumber, page.IsLeaf ? "Leaf" : "Branch", page.NumberOfEntries, open ? "checked" : "", text);

            for (int i = 0; i < page.NumberOfEntries; i++)
            {
                var nodeHeader = page.GetNode(i);
                var key        = TreeNodeHeader.ToSlicePtr(tx.Allocator, nodeHeader).ToString();

                if (page.IsLeaf)
                {
                    sw.Write("<li>{0} {1} - size: {2:#,#}</li>", key, nodeHeader->Flags, TreeNodeHeader.GetDataSize(tx, nodeHeader));
                }
                else
                {
                    var pageNum = nodeHeader->PageNumber;

                    if (i == 0)
                    {
                        key = "[smallest]";
                    }

                    RenderPage(tx, tx.GetReadOnlyTreePage(pageNum), sw, key, false);
                }
            }
            sw.WriteLine("</ul></li></ul>");
        }
        private TreePage GetNestedMultiValuePage(byte *nestedPagePtr, TreeNodeHeader *currentNode)
        {
            var nestedPage = new TreePage(nestedPagePtr, "multi tree", (ushort)TreeNodeHeader.GetDataSize(_tx, currentNode));

            Debug.Assert(nestedPage.PageNumber == -1); // nested page marker
            return(nestedPage);
        }
Esempio n. 3
0
        protected unsafe Tuple <Slice, Slice> ReadKey(Transaction txh, Tree tree, Slice key)
        {
            TreeNodeHeader *node;

            tree.FindPageFor(key, out node);

            if (node == null)
            {
                return(null);
            }

            Slice item1;

            TreeNodeHeader.ToSlicePtr(txh.Allocator, node, out item1);

            if (SliceComparer.CompareInline(item1, key) != 0)
            {
                return(null);
            }

            Slice item2;

            Slice.External(txh.Allocator, (byte *)node + node->KeySize + Constants.Tree.NodeHeaderSize, (ushort)node->DataSize, ByteStringType.Immutable, out item2);
            return(Tuple.Create(item1, item2));
        }
Esempio n. 4
0
        public void CopyToOriginal(LowLevelTransaction tx, bool defragRequired, bool wasModified)
        {
            if (CalcSizeUsed() < Original.PageMaxSpace)
            {
                // no need to compress
                Original.Lower  = (ushort)Constants.Tree.PageHeaderSize;
                Original.Upper  = (ushort)Original.PageSize;
                Original.Flags &= ~PageFlags.Compressed;

                for (var i = 0; i < NumberOfEntries; i++)
                {
                    var node = GetNode(i);
                    using (TreeNodeHeader.ToSlicePtr(tx.Allocator, node, out var slice))
                        Original.CopyNodeDataToEndOfPage(node, slice);
                }
            }
            else
            {
                using (LeafPageCompressor.TryGetCompressedTempPage(tx, this, out var compressed, defrag: defragRequired))
                {
                    if (compressed == null)
                    {
                        if (wasModified == false)
                        {
                            return;
                        }

                        ThrowCouldNotCompressDecompressedPage(PageNumber);
                    }

                    LeafPageCompressor.CopyToPage(compressed, Original);
                }
            }
        }
Esempio n. 5
0
        public void CopyToOriginal(LowLevelTransaction tx, bool defragRequired)
        {
            if (CalcSizeUsed() < Original.PageMaxSpace)
            {
                // no need to compress
                Original.Lower  = (ushort)Constants.Tree.PageHeaderSize;
                Original.Upper  = (ushort)Original.PageSize;
                Original.Flags &= ~PageFlags.Compressed;

                for (var i = 0; i < NumberOfEntries; i++)
                {
                    var   node = GetNode(i);
                    Slice slice;
                    using (TreeNodeHeader.ToSlicePtr(tx.Allocator, node, out slice))
                        Original.CopyNodeDataToEndOfPage(node, slice);
                }
            }
            else
            {
                CompressionResult compressed;
                using (LeafPageCompressor.TryGetCompressedTempPage(tx, this, out compressed, defrag: defragRequired))
                {
                    if (compressed == null)
                    {
                        throw new InvalidOperationException("Could not compress a page which was already compressed. Should never happen");
                    }

                    LeafPageCompressor.CopyToPage(compressed, Original);
                }
            }
        }
Esempio n. 6
0
                public TreeNodeHeaderSafe(Tree tree, TreeNodeHeader *nodeHeader)
                {
                    _tree       = tree ?? throw new ArgumentNullException(nameof(tree));
                    _nodeHeader = nodeHeader;

                    using (TreeNodeHeader.ToSlicePtr(tree.Llt.Allocator, nodeHeader, out Slice keySlice))
                        Key = keySlice.ToString();
                }
        private MultiValuesReport CreateMultiValuesReport(Tree tree)
        {
            var multiValues = new MultiValuesReport();

            using (var multiTreeIterator = tree.Iterate(false))
            {
                if (multiTreeIterator.Seek(Slices.BeforeAllKeys))
                {
                    do
                    {
                        var currentNode = multiTreeIterator.Current;

                        switch (currentNode->Flags)
                        {
                        case TreeNodeFlags.MultiValuePageRef:
                        {
                            var multiValueTreeHeader = (TreeRootHeader *)((byte *)currentNode + currentNode->KeySize + Constants.NodeHeaderSize);

                            Debug.Assert(multiValueTreeHeader->Flags == TreeFlags.MultiValue);

                            multiValues.NumberOfEntries += multiValueTreeHeader->NumberOfEntries;
                            multiValues.BranchPages     += multiValueTreeHeader->BranchPages;
                            multiValues.LeafPages       += multiValueTreeHeader->LeafPages;
                            multiValues.PageCount       += multiValueTreeHeader->PageCount;
                            break;
                        }

                        case TreeNodeFlags.Data:
                        {
                            var nestedPage = GetNestedMultiValuePage(TreeNodeHeader.DirectAccess(_tx, currentNode), currentNode);

                            multiValues.NumberOfEntries += nestedPage.NumberOfEntries;
                            break;
                        }

                        case TreeNodeFlags.PageRef:
                        {
                            var overFlowPage = _tx.GetReadOnlyTreePage(currentNode->PageNumber);
                            var nestedPage   = GetNestedMultiValuePage(overFlowPage.Base + Constants.TreePageHeaderSize, currentNode);

                            multiValues.NumberOfEntries += nestedPage.NumberOfEntries;
                            break;
                        }

                        default:
                            throw new VoronUnrecoverableErrorException("currentNode->FixedTreeFlags has value of " + currentNode->Flags);
                        }
                    } while (multiTreeIterator.MoveNext());
                }
            }
            return(multiValues);
        }
Esempio n. 8
0
        public void CopyToOriginal(LowLevelTransaction tx, bool defragRequired, bool wasModified, Tree tree)
        {
            if (CalcSizeUsed() < Original.PageMaxSpace)
            {
                // no need to compress
                Original.Lower  = (ushort)Constants.Tree.PageHeaderSize;
                Original.Upper  = (ushort)Original.PageSize;
                Original.Flags &= ~PageFlags.Compressed;

                for (var i = 0; i < NumberOfEntries; i++)
                {
                    var node = GetNode(i);
                    using (TreeNodeHeader.ToSlicePtr(tx.Allocator, node, out var slice))
                        Original.CopyNodeDataToEndOfPage(node, slice);
                }

                tree.DecompressionsCache.Invalidate(PageNumber, DecompressionUsage.Write);
            }
            else
            {
                using (LeafPageCompressor.TryGetCompressedTempPage(tx, this, out var compressed, defrag: defragRequired))
                {
                    if (compressed == null)
                    {
                        if (wasModified == false)
                        {
                            return;
                        }

                        if (NumberOfEntries > 0)
                        {
                            // we aren't able to compress the page back to 8KB page
                            // let's split it and try to copy it then

                            SplitPage(tx, tree);
                        }
                        else
                        {
                            ThrowCouldNotCompressEmptyDecompressedPage(PageNumber);
                        }

                        CopyToOriginal(tx, defragRequired: true, wasModified: true, tree);

                        return;
                    }

                    LeafPageCompressor.CopyToPage(compressed, Original);
                }
            }
        }
Esempio n. 9
0
        private AggregationResult AggregateLeafPage(TreePage page, LowLevelTransaction lowLevelTransaction, TransactionOperationContext indexContext, CancellationToken token)
        {
            using (_treeReductionStats.LeafAggregation.Start())
            {
                for (int i = 0; i < page.NumberOfEntries; i++)
                {
                    var valueReader = TreeNodeHeader.Reader(lowLevelTransaction, page.GetNode(i));
                    var reduceEntry = new BlittableJsonReaderObject(valueReader.Base, valueReader.Length, indexContext);

                    _aggregationBatch.Add(reduceEntry);
                }

                return(AggregateBatchResults(_aggregationBatch, indexContext, token));
            }
        }
Esempio n. 10
0
                public TreeNodeHeaderSafe(Tree tree, TreeNodeHeader *nodeHeader)
                {
                    _tree       = tree ?? throw new ArgumentNullException(nameof(tree));
                    _nodeHeader = nodeHeader;

                    using (TreeNodeHeader.ToSlicePtr(tree.Llt.Allocator, nodeHeader, out Slice keySlice))
                    {
                        // uncomment to convert the slice to long
                        //if (keySlice.Size == sizeof(long))
                        //{
                        //    var idPtr = (long*)keySlice.Content.Ptr;
                        //    var id = Bits.SwapBytes(*idPtr);
                        //    Key = id.ToString();
                        //}
                        //else
                        Key = keySlice.ToString();
                    }
                }
Esempio n. 11
0
        private static unsafe void RenderPage(Tree tree, TreePage page, TextWriter sw, string text, bool open)
        {
            sw.WriteLine(
                "<ul><li><input type='checkbox' id='page-{0}' {3} /><label for='page-{0}'>{4}: Page {0:#,#;;0} - {1} - {2:#,#;;0} entries {5}</label><ul>",
                page.PageNumber, page.IsLeaf ? "Leaf" : "Branch", page.NumberOfEntries, open ? "checked" : "", text,
                page.IsCompressed? $"(Compressed ({page.CompressionHeader->NumberOfCompressedEntries} entries [uncompressed/compressed: {page.CompressionHeader->UncompressedSize}/{page.CompressionHeader->CompressedSize}])" : string.Empty);

            for (int i = 0; i < page.NumberOfEntries; i++)
            {
                var nodeHeader = page.GetNode(i);

                string key;
                Slice  keySlice;
                using (TreeNodeHeader.ToSlicePtr(tree.Llt.Allocator, nodeHeader, out keySlice))
                {
                    key = keySlice.ToString();
                }

                if (page.IsLeaf)
                {
                    sw.Write("<li>{0} {1} - size: {2:#,#}</li>", key, nodeHeader->Flags, tree.GetDataSize(nodeHeader));
                }
                else
                {
                    var pageNum = nodeHeader->PageNumber;

                    if (i == 0)
                    {
                        key = "[smallest]";
                    }

                    RenderPage(tree, tree.GetReadOnlyTreePage(pageNum), sw, key, false);
                }
            }
            sw.WriteLine("</ul></li></ul>");
        }
Esempio n. 12
0
        private static unsafe ReduceTree RenderTree(Tree tree, ulong reduceKeyHash, Dictionary <long, string> idToDocIdHash, Index index, TransactionOperationContext context)
        {
            var stack    = new Stack <ReduceTreePage>();
            var rootPage = tree.GetReadOnlyTreePage(tree.State.RootPageNumber);

            var root = new ReduceTreePage(rootPage);

            root.AggregationResult = GetReduceResult(reduceKeyHash, index, context);

            stack.Push(root);

            var table =
                context.Transaction.InnerTransaction.OpenTable(
                    ReduceMapResultsBase <MapReduceIndexDefinition> .ReduceResultsSchema,
                    ReduceMapResultsBase <MapReduceIndexDefinition> .PageNumberToReduceResultTableName);

            var tx = tree.Llt;

            while (stack.Count > 0)
            {
                var node = stack.Pop();
                var page = node.Page;

                if (page.IsCompressed)
                {
                    var decompressed = tree.DecompressPage(page, DecompressionUsage.Read, true);

                    node.DecompressedLeaf = decompressed;
                    page = decompressed;
                }

                if (page.NumberOfEntries == 0 && page != rootPage)
                {
                    throw new InvalidOperationException($"The page {page.PageNumber} is empty");
                }

                for (var i = 0; i < page.NumberOfEntries; i++)
                {
                    if (page.IsBranch)
                    {
                        var p = page.GetNode(i)->PageNumber;

                        var childNode = new ReduceTreePage(tree.GetReadOnlyTreePage(p));

                        node.Children.Add(childNode);

                        stack.Push(childNode);
                    }
                    else
                    {
                        var entry = new MapResultInLeaf();

                        var valueReader = TreeNodeHeader.Reader(tx, page.GetNode(i));
                        entry.Data = new BlittableJsonReaderObject(valueReader.Base, valueReader.Length, context);

                        using (page.GetNodeKey(tx, i, out Slice s))
                        {
                            var mapEntryId = Bits.SwapBytes(*(long *)s.Content.Ptr);

                            if (idToDocIdHash.TryGetValue(mapEntryId, out string docId))
                            {
                                entry.Source = docId;
                            }
                        }

                        node.Entries.Add(entry);
                    }
                }

                if (node != root)
                {
                    node.AggregationResult = GetAggregationResult(node.PageNumber, table, context);
                }
            }

            return(new ReduceTree
            {
                DisplayName = GetTreeName(root.AggregationResult, index.Definition, context),
                Name = tree.Name.ToString(),
                Root = root,
                Depth = tree.State.Depth,
                PageCount = tree.State.PageCount,
                NumberOfEntries = tree.State.NumberOfEntries
            });
        }
Esempio n. 13
0
        public TreeNodeHeader *Original_WithPrefetch_Search(TreePage page, ByteStringContext allocator, Slice key)
        {
            int numberOfEntries = page.NumberOfEntries;

            if (numberOfEntries == 0)
            {
                goto NoEntries;
            }

            int lastMatch          = -1;
            int lastSearchPosition = 0;

            SliceOptions options = key.Options;

            if (options == SliceOptions.Key)
            {
                if (numberOfEntries == 1)
                {
                    goto SingleEntryKey;
                }

                int low      = page.IsLeaf ? 0 : 1;
                int high     = numberOfEntries - 1;
                int position = 0;

                ushort *offsets = page.KeysOffsets;
                byte *  @base   = page.Base;
                while (low <= high)
                {
                    position = (low + high) >> 1;

                    var node = (TreeNodeHeader *)(@base + offsets[position]);

                    Slice pageKey;
                    using (TreeNodeHeader.ToSlicePtr(allocator, node, out pageKey))
                    {
                        Sse.Prefetch0(pageKey.Content.Ptr);
                        lastMatch = SliceComparer.CompareInline(key, pageKey);
                    }

                    if (lastMatch == 0)
                    {
                        break;
                    }

                    if (lastMatch > 0)
                    {
                        low = position + 1;
                    }
                    else
                    {
                        high = position - 1;
                    }
                }

                if (lastMatch > 0) // found entry less than key
                {
                    position++;    // move to the smallest entry larger than the key
                }

                lastSearchPosition = position;
                goto MultipleEntryKey;
            }
            if (options == SliceOptions.BeforeAllKeys)
            {
                lastMatch = 1;
                goto MultipleEntryKey;
            }
            if (options == SliceOptions.AfterAllKeys)
            {
                lastSearchPosition = numberOfEntries - 1;
                goto MultipleEntryKey;
            }

            return(null);

NoEntries:
            {
                page.LastSearchPosition = 0;
                page.LastMatch          = 1;
                return(null);
            }

SingleEntryKey:
            {
                var node = page.GetNode(0);

                Slice pageKey;
                using (TreeNodeHeader.ToSlicePtr(allocator, node, out pageKey))
                {
                    page.LastMatch = SliceComparer.CompareInline(key, pageKey);
                }

                page.LastSearchPosition = page.LastMatch > 0 ? 1 : 0;
                return(page.LastSearchPosition == 0 ? node : null);
            }

MultipleEntryKey:
            {
                page.LastMatch          = lastMatch;
                page.LastSearchPosition = lastSearchPosition;

                if (lastSearchPosition >= numberOfEntries)
                {
                    return(null);
                }

                return(page.GetNode(lastSearchPosition));
            }
        }