Example #1
0
        private ActualKeyScope GetActualKey(TreePage page, int pos, out TreeNodeHeader *node, out Slice key)
        {
            DecompressedLeafPage decompressedLeafPage = null;

            node = page.GetNode(pos);
            var scope = TreeNodeHeader.ToSlicePtr(_tx.Allocator, node, out key);

            while (key.Size == 0)
            {
                Debug.Assert(page.IsBranch);
                page = _tree.GetReadOnlyTreePage(node->PageNumber);
                if (page.IsCompressed == false)
                {
                    node = page.GetNode(0);
                }
                else
                {
                    decompressedLeafPage?.Dispose();
                    decompressedLeafPage = _tree.DecompressPage(page, skipCache: true);

                    if (decompressedLeafPage.NumberOfEntries > 0)
                    {
                        node = decompressedLeafPage.GetNode(0);
                    }
                    else
                    {
                        // we have empty page after decompression (each compressed entry has a corresponding CompressionTombstone)
                        // we can safely use the node key of first tombstone (they have proper order)

                        node = page.GetNode(0);
                    }
                }

                scope.Dispose();
                scope = TreeNodeHeader.ToSlicePtr(_tx.Allocator, node, out key);
            }

            return(new ActualKeyScope
            {
                DecompressedLeafPage = decompressedLeafPage,
                ExternalScope = scope
            });
        }
Example #2
0
        private void HandleTombstone(DecompressedLeafPage decompressedPage, Slice nodeKey, DecompressionUsage usage)
        {
            decompressedPage.Search(_llt, nodeKey);

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

            var node = decompressedPage.GetNode(decompressedPage.LastSearchPosition);

            if (usage == DecompressionUsage.Write)
            {
                State.NumberOfEntries--;

                if (node->Flags == TreeNodeFlags.PageRef)
                {
                    var overflowPage = GetReadOnlyTreePage(node->PageNumber);
                    FreePage(overflowPage);
                }
            }

            decompressedPage.RemoveNode(decompressedPage.LastSearchPosition);
        }
Example #3
0
        private ActualKeyScope GetActualKey(TreePage page, int pos, out TreeNodeHeader *node, out Slice key)
        {
            DecompressedLeafPage decompressedLeafPage = null;

            node = page.GetNode(pos);
            var scope = TreeNodeHeader.ToSlicePtr(_tx.Allocator, node, out key);

            while (key.Size == 0)
            {
                Debug.Assert(page.IsBranch);
                page = _tree.GetReadOnlyTreePage(node->PageNumber);
                if (page.IsCompressed == false)
                {
                    node = page.GetNode(0);
                }
                else
                {
                    decompressedLeafPage?.Dispose();
                    decompressedLeafPage = _tree.DecompressPage(page, DecompressionUsage.Read, skipCache: true);

                    if (decompressedLeafPage.NumberOfEntries > 0)
                    {
                        if (page.NumberOfEntries == 0)
                        {
                            node = decompressedLeafPage.GetNode(0);
                        }
                        else
                        {
                            // we want to find the smallest key in compressed page
                            // it can be inside compressed part or not compressed one
                            // in particular, it can be the key of compression tombstone node that we don't see after decompression
                            // so we need to take first keys from decompressed and compressed page and compare them

                            var decompressedNode = decompressedLeafPage.GetNode(0);
                            var compressedNode   = page.GetNode(0);

                            using (TreeNodeHeader.ToSlicePtr(_tx.Allocator, decompressedNode, out var firstDecompressedKey))
                                using (TreeNodeHeader.ToSlicePtr(_tx.Allocator, compressedNode, out var firstCompressedKey))
                                {
                                    node = SliceComparer.CompareInline(firstDecompressedKey, firstCompressedKey) > 0 ? compressedNode : decompressedNode;
                                }
                        }
                    }
                    else
                    {
                        // we have empty page after decompression (each compressed entry has a corresponding CompressionTombstone)
                        // we can safely use the node key of first tombstone (they have proper order)

                        node = page.GetNode(0);
                    }
                }

                scope.Dispose();
                scope = TreeNodeHeader.ToSlicePtr(_tx.Allocator, node, out key);
            }

            return(new ActualKeyScope
            {
                DecompressedLeafPage = decompressedLeafPage,
                ExternalScope = scope
            });
        }