/// <summary> /// Dump a trace of the structure of this node to the console /// </summary> /// <param name="tree">The tree that contains this node</param> /// <param name="indentLevel">The indent level to use when writing the structure</param> public void DumpStructure(BPlusTree tree, int indentLevel) { var keyPrefix = new string(' ', indentLevel *4); var pointerPrefix = keyPrefix + " "; INode childNode; for (int i = 0; i < _keyCount; i++) { Console.WriteLine("{0}PTR[{1}]: {2}", pointerPrefix, i, _childPointers[i]); childNode = tree.GetNode(_childPointers[i], null); childNode.DumpStructure(tree, indentLevel + 1); Console.WriteLine("{0}KEY[{1}]: {2}", keyPrefix, i, _keys[i].Dump()); } Console.WriteLine("{0}PTR[{1}]: {2}", pointerPrefix, _keyCount, _childPointers[_keyCount]); childNode = tree.GetNode(_childPointers[_keyCount], null); childNode.DumpStructure(tree, indentLevel + 1); }
public void DumpStructure(BPlusTree tree, int indentLevel) { var keyPrefix = new string(' ', indentLevel * 4); var pointerPrefix = keyPrefix + " "; INode childNode; for (int i = 0; i < _keyCount; i++) { var childPointer = GetPointer(i); Console.WriteLine("{0}PTR[{1}]: {2}", pointerPrefix, i, childPointer); childNode = tree.GetNode(childPointer, null); childNode.DumpStructure(tree, indentLevel + 1); Console.WriteLine("{0}KEY[{1}]: {2}", keyPrefix, i, GetKey(i).Dump()); } var lastPointer = GetPointer(KeyCount); Console.WriteLine("{0}PTR[{1}]: {2}", pointerPrefix, _keyCount, lastPointer); childNode = tree.GetNode(lastPointer, null); childNode.DumpStructure(tree, indentLevel + 1); }
public void TestMergeRight() { using (var pageStore = TestUtils.CreateEmptyPageStore("TestMergeRight.data")) { var txnId = 0ul; var tree = new BPlusTree(txnId, pageStore); var testBytes = new byte[] {1, 2, 3, 4}; var config = tree.Configuration; var buff = new byte[config.ValueSize]; for (int i = 0; i < config.LeafLoadFactor*config.InternalBranchFactor; i++) { try { tree.Insert(txnId, (ulong) i, testBytes); } catch (Exception ex) { Assert.Fail("Insert failed for key {0} with exception {1}", i, ex); } } var rootNode = tree.GetNode(tree.RootId, null); var childId = (rootNode as IInternalNode).GetChildNodeId(rootNode.RightmostKey); var child = tree.GetNode(childId, null) as IInternalNode; var childLeftmostKey = BitConverter.ToUInt64(child.LeftmostKey, 0); var grandchild = tree.GetNode(child.GetChildNodeId(BitConverter.GetBytes(childLeftmostKey - 1)), null) as ILeafNode; var deleteFrom = BitConverter.ToUInt64(grandchild.LeftmostKey, 0); var findChildId = (rootNode as IInternalNode).GetChildNodeId(BitConverter.GetBytes(deleteFrom)); Assert.AreEqual(child.PageId, findChildId, "Incorrect node id returned for key {0}", deleteFrom); tree.DumpStructure(); for (ulong i = 0; i < 4; i++) { var deleteKey = deleteFrom + i; tree.Delete(txnId, deleteKey, null); // Should be enough to force a right merge //Console.WriteLine("\n\nDeleted {0}\n", deleteKey); //tree.DumpStructure(); Assert.IsTrue(tree.Search(10395ul, buff, null)); } for (ulong i = 0; i < (ulong) (config.LeafLoadFactor*config.InternalBranchFactor); i++) { try { Assert.IsTrue(tree.Search(i, buff, null) ^ (i - deleteFrom >= 0 && i - deleteFrom < 4), "Could not find key {0}. deleteFrom={1}", i, deleteFrom); } catch (AssertionException) { Console.WriteLine("\nFailed tree structure:\n"); tree.DumpStructure(); throw; } } deleteFrom = (ulong) (config.LeafLoadFactor*config.InternalBranchFactor) - 5; for (ulong i = 0; i < 4; i++) { var deleteKey = deleteFrom + i; tree.Delete(txnId, deleteKey, null); } } }
public void TestCoalesceLeafLoadPlusOne() { const string storeName = "Coalesce.LeafLoadPlusOne.data"; ulong srcRootId, targetRootId; var config = new BPlusTreeConfiguration(8, 64, 4096); var txnId = 0ul; using (var store = TestUtils.CreateEmptyPageStore(storeName)) { var sourceTree = new BPlusTree(store); for (int i = 0; i < config.LeafLoadFactor + 1; i++) { sourceTree.Insert(txnId, (ulong)i, BitConverter.GetBytes((ulong)i)); } sourceTree.DumpStructure(); srcRootId = sourceTree.Save(txnId, null); store.Commit(txnId, null); } txnId = 1; using (var store = TestUtils.OpenPageStore(storeName, false)) { var sourceTree = new BPlusTree(store, srcRootId); var builder = new BPlusTreeBuilder(store, config); targetRootId = builder.Build(1, sourceTree.Scan(null)); var targetTree = new BPlusTree(store, targetRootId); targetTree.DumpStructure(); byte[] valueBuff = new byte[64]; for (int i = 0; i < config.LeafLoadFactor + 1; i++) { Assert.IsTrue(targetTree.Search((ulong)i, valueBuff, null)); Assert.AreEqual((ulong)i, BitConverter.ToUInt64(valueBuff, 0)); } store.Commit(1, null); } using (var store = TestUtils.OpenPageStore(storeName, true)) { var targetTree = new BPlusTree(store, targetRootId); targetTree.DumpStructure(); byte[] valueBuff = new byte[64]; for (int i = 0; i < config.LeafLoadFactor + 1; i++) { Assert.IsTrue(targetTree.Search((ulong)i, valueBuff, null)); Assert.AreEqual((ulong)i, BitConverter.ToUInt64(valueBuff, 0)); } var root = targetTree.GetNode(targetTree.RootId, null) as InternalNode; Assert.IsNotNull(root); Assert.AreEqual(1, root.KeyCount); var leftChild = targetTree.GetNode(root.ChildPointers[0], null) as LeafNode; var rightChild = targetTree.GetNode(root.ChildPointers[1], null) as LeafNode; Assert.IsNotNull(leftChild); Assert.IsNotNull(rightChild); Assert.AreEqual(config.LeafLoadFactor+1, leftChild.KeyCount + rightChild.KeyCount); // Key count in each node should be >= split index Assert.IsTrue(leftChild.KeyCount > config.LeafSplitIndex, "Left child has too few keys"); Assert.IsTrue(rightChild.KeyCount > config.LeafSplitIndex, "Right child has too few keys"); // And neither } }
/// <summary> /// Dump a trace of the structure of this node to the console /// </summary> /// <param name="tree">The tree that contains this node</param> /// <param name="indentLevel">The indent level to use when writing the structure</param> public void DumpStructure(BPlusTree tree, int indentLevel) { var keyPrefix = new string(' ', indentLevel*4); var pointerPrefix = keyPrefix + " "; INode childNode; for (int i = 0; i < _keyCount; i++) { Console.WriteLine("{0}PTR[{1}]: {2}", pointerPrefix, i, _childPointers[i]); childNode = tree.GetNode(_childPointers[i], null); childNode.DumpStructure(tree, indentLevel + 1); Console.WriteLine("{0}KEY[{1}]: {2}", keyPrefix, i, _keys[i].Dump()); } Console.WriteLine("{0}PTR[{1}]: {2}", pointerPrefix, _keyCount, _childPointers[_keyCount]); childNode = tree.GetNode(_childPointers[_keyCount], null); childNode.DumpStructure(tree, indentLevel + 1); }