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>"); }
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.Equals(item1, key)) { return(null); } Slice item2; Slice.External(txh.Allocator, (byte *)node + node->KeySize + Constants.Tree.NodeHeaderSize, (ushort)node->DataSize, out item2); return(Tuple.Create(item1, item2)); }
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)); } }