public void TestInsertAndDeleteInReverseOrder() { const string pageStoreName = "TestInsertAndDeleteInReverseOrder.data"; var value = new byte[64]; ulong rootPageId; const int keyCount = 20000; using (var pageStore = TestUtils.CreateEmptyPageStore(pageStoreName)) { var tree = new BPlusTree(0, pageStore); for (int i = 0; i < keyCount; i++) { tree.Insert(0, (ulong) i, value); } rootPageId = tree.Save(0, null); pageStore.Commit(0, null); } using (var pageStore = TestUtils.OpenPageStore(pageStoreName, false)) { var tree = new BPlusTree(pageStore, rootPageId); for (int i = keyCount - 1; i >= 0; i--) { try { tree.Delete(1, (ulong) i, null); } catch (Exception) { Console.WriteLine("Delete threw exception on key {0}", i); throw; } } rootPageId = tree.Save(1, null); pageStore.Commit(0, null); } using (var pageStore = TestUtils.OpenPageStore(pageStoreName, false)) { var tree = new BPlusTree(pageStore, rootPageId); Assert.AreEqual(0, tree.Scan(null).Count(), "Expected and empty tree after all deletes"); } }
public void TestDeleteInRandomOrder() { const string pageStoreName = "DeleteInRandomOrder.data"; var value = new byte[64]; ulong rootPageId; const int keyCount = 20000; using (var pageStore = TestUtils.CreateEmptyPageStore(pageStoreName)) { var tree = new BPlusTree(0, pageStore); for (int i = 0; i < keyCount; i++) { tree.Insert(0, (ulong)i, value); } rootPageId = tree.Save(0, null); pageStore.Commit(0, null); } var deleteList = TestUtils.MakeRandomInsertList(20000).ToList(); using (var pageStore = TestUtils.OpenPageStore(pageStoreName, false)) { var tree = new BPlusTree(pageStore, rootPageId); for (int i = 0; i < deleteList.Count; i++) { Assert.IsTrue(tree.Search((ulong)deleteList[i], value, null), "Could not find key {0} before deletion", deleteList[i]); tree.Delete(1, (ulong)deleteList[i], null); Assert.IsFalse(tree.Search((ulong)deleteList[i],value, null), "Search returned key {0} after it was supposed to be deleted", deleteList[i]); } rootPageId = tree.Save(1, null); pageStore.Commit(1, null); } using (var pageStore = TestUtils.OpenPageStore(pageStoreName, false)) { var tree = new BPlusTree(pageStore, rootPageId); Assert.AreEqual(0, tree.Scan(null).Count(), "Expected and empty tree after all deletes"); } }
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 TestInsertAndDeleteAllEntries() { var value = new byte[64]; ulong rootPageId; const int keyCount = 20000; using(var pageStore = TestUtils.CreateEmptyPageStore("TestInsertAndDeleteAllEntries.data")) { var tree = new BPlusTree(0, pageStore); for(int i = 0; i < keyCount; i++) { tree.Insert(0, (ulong)i, value); } rootPageId = tree.Save(0, null); pageStore.Commit(0, null); } using(var pageStore = TestUtils.OpenPageStore("TestInsertAndDeleteAllEntries.data", true)) { var tree = new BPlusTree(pageStore, rootPageId); for(int i = 0; i < keyCount; i++) { Assert.IsTrue(tree.Search((ulong)i, value, null), "Could not find key {0} after insert and save."); } } using (var pageStore = TestUtils.OpenPageStore("TestInsertAndDeleteAllEntries.data", false)) { var tree = new BPlusTree(pageStore, rootPageId); Assert.IsTrue(tree.Search(3457ul, value, null), "Could not find entry 3457 before deletes"); for (int i = 0; i < keyCount; i += 2) { tree.Delete(1ul, (ulong)i, null); Assert.IsFalse(tree.Search((ulong)i, value, null), "Still found entry for key {0} after delete", i); Assert.IsTrue(tree.Search(3457ul, value, null), "Could not find entry 3457 after delete of {0}",i); } rootPageId = tree.Save(1, null); pageStore.Commit(1, null); } using (var pageStore = TestUtils.OpenPageStore("TestInsertAndDeleteAllEntries.data", true)) { var tree = new BPlusTree(pageStore, rootPageId); for (int i = 1; i < keyCount; i += 2) { Assert.IsTrue(tree.Search((ulong)i, value, null), "Could not find key {0} after deletion of even numbered keys.", i); Assert.IsFalse(tree.Search((ulong)i-1, value, null), "Found key {0} after deletion of even numbered keys", i-1); } } using (var pageStore = TestUtils.OpenPageStore("TestInsertAndDeleteAllEntries.data", false)) { var tree = new BPlusTree(pageStore, rootPageId); for (int i = 1; i < keyCount; i += 2) { tree.Delete(2ul, (ulong)i, null); Assert.IsFalse(tree.Search((ulong)i, value, null), "Key {0} was still found by a search after it was deleted", i); } rootPageId = tree.Save(2, null); pageStore.Commit(2, null); } using (var pageStore = TestUtils.OpenPageStore("TestInsertAndDeleteAllEntries.data", true)) { var tree = new BPlusTree(pageStore, rootPageId); Console.WriteLine("After load\r\n"); tree.DumpStructure(); Assert.AreEqual(0, tree.Scan(null).Count(), "Expected an empty tree after deleting all odd-numbered entries"); } }
public void TestMergeLeft() { using (var pageStore = TestUtils.CreateEmptyPageStore("TestMergeLeft.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++) { tree.Insert(txnId, (ulong) i, testBytes); } ulong delFrom = (ulong) (config.LeafLoadFactor*config.InternalBranchFactor) - 1; ulong delRange = ((ulong) config.LeafLoadFactor/2) + 2; for (ulong i = 0; i < delRange; i++) { tree.Delete(txnId, delFrom - i, null); // Should be enough to force a left merge } for (ulong i = 0; i < delFrom; i++) { Assert.IsTrue((delFrom - i < delRange) ^ tree.Search(i, buff, null), "Failed to find key {0} after deletes", i); } } }
public void TestBorrowRight() { using (var pageStore = TestUtils.CreateEmptyPageStore("TestBorrowRight.data")) { var txnId = 0ul; var tree = new BPlusTree(txnId, pageStore); var config = tree.Configuration; var buff = new byte[config.ValueSize]; for (int i = 0; i <= config.LeafLoadFactor; i++) { tree.Insert(txnId, (ulong) i, BitConverter.GetBytes((ulong) i)); } //Console.WriteLine("Before deletes:"); //tree.DumpStructure(); tree.Delete(txnId, 13ul, null); tree.Delete(txnId, 12ul, null); // Should force a borrow frrom the right node //Console.WriteLine("After Deletes"); //tree.DumpStructure(); for (int i = 0; i <= config.LeafLoadFactor; i++) { Assert.IsTrue(i == 12 ^ i == 13 ^ tree.Search((ulong) i, buff, null), "Could not find entry for key {0}", i); } } }
public void TestBorrowLeft() { using (var pageStore = TestUtils.CreateEmptyPageStore("TestBorrowLeft.data")) { var txnId = 0ul; var tree = new BPlusTree(txnId, pageStore); var config = tree.Configuration; var buff = new byte[config.ValueSize]; for (int j = config.LeafLoadFactor; j >= 0; j--) { tree.Insert(txnId, (ulong) j, BitConverter.GetBytes((ulong) j)); } tree.Delete(txnId, (ulong) (config.LeafLoadFactor - 1), null); tree.Delete(txnId, (ulong) (config.LeafLoadFactor - 2), null); // This should force a borrow from the left node for (int i = 0; i <= config.LeafLoadFactor; i++) { Assert.IsTrue( i == (config.LeafLoadFactor - 1) ^ i == (config.LeafLoadFactor - 2) ^ tree.Search((ulong) i, buff, null), "Could not find entry for key {0}", i); } } }
public void TestDeleteFromLeafRoot() { using (var pageStore = TestUtils.CreateEmptyPageStore("TestDeleteFromLeafRoot.data")) { var txnId = 0ul; var tree = new BPlusTree(txnId, pageStore); var config = tree.Configuration; var buff = new byte[config.ValueSize]; tree.Insert(txnId, 1ul, TestUtils.StringToByteArray("one")); tree.Insert(txnId, 2ul, TestUtils.StringToByteArray("two")); tree.Insert(txnId, 3ul, TestUtils.StringToByteArray("three")); tree.Delete(txnId, 2ul, null); Assert.IsTrue(tree.Search(1ul, buff, null)); TestUtils.AssertBuffersEqual(TestUtils.StringToByteArray("one"), buff); Assert.IsTrue(tree.Search(3ul, buff, null)); TestUtils.AssertBuffersEqual(TestUtils.StringToByteArray("three"), buff); Assert.IsFalse(tree.Search(2ul, buff, null)); } }
public void TestBorrowRight() { using (var pageStore = TestUtils.CreateEmptyPageStore("TestBorrowRight.data")) { var tree = new BPlusTree(pageStore); var buff = new byte[_config.ValueSize]; var txnId = 0ul; for (int i = 0; i <= _config.LeafLoadFactor; i++) { tree.Insert(txnId, (ulong) i, BitConverter.GetBytes((ulong) i)); } tree.Delete(txnId, 13ul, null); tree.Delete(txnId, 12ul, null); // Should force a borrow frrom the right node for (int i = 0; i <= _config.LeafLoadFactor; i++) { Assert.IsTrue(i == 12 ^ i == 13 ^ tree.Search((ulong) i, buff, null)); } } }