public void Dispose() { if (_disposed) { return; } _disposed = true; if (RequiredPrefix.HasValue) { RequiredPrefix.Release(_tx.Allocator); } if (MaxKey.HasValue) { MaxKey.Release(_tx.Allocator); } _prevKeyScope.Dispose(); _cursor?.Dispose(); _decompressedPage?.Dispose(); OnDisposal?.Invoke(this); }
private static async Task RenderPageInternalAsync(Tree tree, TreePageSafe page, TextWriter sw, string text, bool open, bool decompress) { await sw.WriteLineAsync( string.Format("<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.NumberOfCompressedEntries} entries [uncompressed/compressed: {page.UncompressedSize}/{page.CompressedSize}])" : string.Empty)); DecompressedLeafPage decompressedPage = null; if (page.IsCompressed && decompress) { decompressedPage = tree.DecompressPage(page.TreePage, DecompressionUsage.Read, skipCache: true); page = new TreePageSafe(page.Tree, decompressedPage); } try { for (int i = 0; i < page.NumberOfEntries; i++) { var nodeHeader = page.GetNode(i); string key = nodeHeader.Key; if (page.IsLeaf) { await sw.WriteAsync(string.Format("<li>{0} {1} - size: {2:#,#}</li>", key, nodeHeader.Flags, nodeHeader.GetDataSize())); } else { var pageNum = nodeHeader.PageNumber; if (i == 0) { key = "[smallest]"; } await RenderPageAsync(tree, tree.GetReadOnlyTreePage(pageNum), sw, key, false, decompress); } } } finally { decompressedPage?.Dispose(); } await sw.WriteLineAsync("</ul></li></ul>"); }
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 }); }
public void Dispose() { if (_disposed) { return; } _disposed = true; if (_isLeaf) { DecompressedLeaf?.Dispose(); } else { foreach (var reduceTreePage in Children) { reduceTreePage.Dispose(); } } GC.SuppressFinalize(this); }
public void Dispose() { ExternalScope.Dispose(); DecompressedLeafPage?.Dispose(); }
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 }); }