Ejemplo n.º 1
0
        private bool TryUseRecentTransactionPage(Slice key, out TreeCursorConstructor cursor, out TreePage page, out TreeNodeHeader *node)
        {
            var foundPage = _recentlyFoundPages?.Find(key);

            if (foundPage == null)
            {
                page   = null;
                node   = null;
                cursor = default(TreeCursorConstructor);
                return(false);
            }

            var lastFoundPageNumber = foundPage.Number;

            if (foundPage.Page != null)
            {
                // we can't share the same instance, Page instance may be modified by
                // concurrently run iterators
                page = new TreePage(foundPage.Page.Base, foundPage.Page.PageSize);
            }
            else
            {
                page = GetReadOnlyTreePage(lastFoundPageNumber);
            }

            if (page.IsLeaf == false)
            {
                VoronUnrecoverableErrorException.Raise(_llt.Environment, "Index points to a non leaf page");
            }

            node = page.Search(_llt, key); // will set the LastSearchPosition

            cursor = new TreeCursorConstructor(_llt, this, page, foundPage.CursorPath, lastFoundPageNumber);
            return(true);
        }
Ejemplo n.º 2
0
        private void DeleteOnCompressedPage(TreePage page, Slice keyToDelete, ref TreeCursorConstructor cursorConstructor)
        {
            var tombstoneNodeSize = page.GetRequiredSpace(keyToDelete, 0);

            page = ModifyPage(page);

            if (page.HasSpaceFor(_llt, tombstoneNodeSize))
            {
                if (page.LastMatch == 0)
                {
                    RemoveLeafNode(page);
                }

                page.AddCompressionTombstoneNode(page.LastSearchPosition, keyToDelete);
                return;
            }

            var decompressed = DecompressPage(page, usage: DecompressionUsage.Write);

            try
            {
                decompressed.Search(_llt, keyToDelete);

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

                State.NumberOfEntries--;

                RemoveLeafNode(decompressed);

                using (var cursor = cursorConstructor.Build(keyToDelete))
                {
                    var treeRebalancer = new TreeRebalancer(_llt, this, cursor);
                    var changedPage    = (TreePage)decompressed;
                    while (changedPage != null)
                    {
                        changedPage = treeRebalancer.Execute(changedPage);
                    }
                }

                page.DebugValidate(this, State.RootPageNumber);
            }
            finally
            {
                decompressed.CopyToOriginal(_llt, defragRequired: true, wasModified: true, this);
            }
        }
Ejemplo n.º 3
0
        internal TreePage FindPageFor(Slice key, out TreeNodeHeader *node, out TreeCursorConstructor cursor, bool allowCompressed = false)
        {
            TreePage p;

            if (TryUseRecentTransactionPage(key, out cursor, out p, out node))
            {
                if (allowCompressed == false && p.IsCompressed)
                {
                    ThrowOnCompressedPage(p);
                }

                return(p);
            }

            return(SearchForPage(key, allowCompressed, out cursor, out node));
        }
Ejemplo n.º 4
0
        private TreePage SearchForPage(Slice key, bool allowCompressed, out TreeCursorConstructor cursorConstructor, out TreeNodeHeader *node, bool addToRecentlyFoundPages = true)
        {
            var p = GetReadOnlyTreePage(State.RootPageNumber);

            var cursor = new TreeCursor();

            cursor.Push(p);

            bool rightmostPage = true;
            bool leftmostPage  = true;

            while ((p.TreeFlags & TreePageFlags.Branch) == TreePageFlags.Branch)
            {
                int nodePos;
                if (key.Options == SliceOptions.BeforeAllKeys)
                {
                    p.LastSearchPosition = nodePos = 0;
                    rightmostPage        = false;
                }
                else if (key.Options == SliceOptions.AfterAllKeys)
                {
                    p.LastSearchPosition = nodePos = (ushort)(p.NumberOfEntries - 1);
                    leftmostPage         = false;
                }
                else
                {
                    if (p.Search(_llt, key) != null)
                    {
                        nodePos = p.LastSearchPosition;
                        if (p.LastMatch != 0)
                        {
                            nodePos--;
                            p.LastSearchPosition--;
                        }

                        if (nodePos != 0)
                        {
                            leftmostPage = false;
                        }

                        rightmostPage = false;
                    }
                    else
                    {
                        nodePos = (ushort)(p.LastSearchPosition - 1);

                        leftmostPage = false;
                    }
                }

                var pageNode = p.GetNode(nodePos);
                p = GetReadOnlyTreePage(pageNode->PageNumber);
                Debug.Assert(pageNode->PageNumber == p.PageNumber,
                             string.Format("Requested Page: #{0}. Got Page: #{1}", pageNode->PageNumber, p.PageNumber));

                cursor.Push(p);
            }

            cursorConstructor = new TreeCursorConstructor(cursor);

            if (p.IsLeaf == false)
            {
                VoronUnrecoverableErrorException.Raise(_llt.Environment, "Index points to a non leaf page");
            }

            if (allowCompressed == false && p.IsCompressed)
            {
                ThrowOnCompressedPage(p);
            }

            node = p.Search(_llt, key);                           // will set the LastSearchPosition

            if (p.NumberOfEntries > 0 && addToRecentlyFoundPages) // compressed page can have no ordinary entries
            {
                AddToRecentlyFoundPages(cursor, p, leftmostPage, rightmostPage);
            }

            return(p);
        }