public void TestCoalesceEmptyTree() { const string storeName = "Coalesce.EmptyTree.data"; ulong srcRootId, coalescedRootId; using(var store = TestUtils.CreateEmptyPageStore(storeName)) { var tree = new BPlusTree(store); srcRootId = tree.Save(0, null); store.Commit(0, null); } using(var store = TestUtils.OpenPageStore(storeName, false)) { var sourceTree = new BPlusTree(store, srcRootId); Assert.AreEqual(0, sourceTree.Scan(null).Count()); var builder = new BPlusTreeBuilder(store, sourceTree.Configuration); coalescedRootId = builder.Build(1, sourceTree.Scan(null)); var coalescedTree = new BPlusTree(store, coalescedRootId); Assert.AreEqual(0, coalescedTree.Scan(null).Count()); store.Commit(1ul, null); } using (var store = TestUtils.OpenPageStore(storeName, true)) { var coalescedTree = new BPlusTree(store, coalescedRootId); Assert.AreEqual(0, coalescedTree.Scan(null).Count()); } }
public void TestCoalesceRootLeafNode() { const string storeName = "Coalesce.RootLeafNode.data"; ulong srcRootId, targetRootId; var txnId = 0ul; using(var store = TestUtils.CreateEmptyPageStore(storeName)) { var sourceTree = new BPlusTree(0, store); var config = sourceTree.Configuration; for (int i = 0; i < config.LeafLoadFactor; i++) { sourceTree.Insert(txnId, (ulong)i, BitConverter.GetBytes((ulong)i)); } sourceTree.DumpStructure(); srcRootId = sourceTree.Save(txnId, null); store.Commit(txnId, null); } using(var store = TestUtils.OpenPageStore(storeName, false)) { var sourceTree = new BPlusTree(store, srcRootId); var config = sourceTree.Configuration; 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; 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); var config = targetTree.Configuration; targetTree.DumpStructure(); byte[] valueBuff = new byte[64]; for (int i = 0; i < config.LeafLoadFactor; i++) { Assert.IsTrue(targetTree.Search((ulong)i, valueBuff, null)); Assert.AreEqual((ulong)i, BitConverter.ToUInt64(valueBuff, 0)); } } }
private void BuildAndScan(IPageStore pageStore, string pageStoreName, PersistenceType persistenceType, int keyCount) { var config = new BPlusTreeConfiguration(8, 64, pageStore.PageSize); var builder = new BPlusTreeBuilder(pageStore, config); var treeRoot = builder.Build(1, _testOrderedValues.Take(keyCount)); var treeBeforeSave = new BPlusTree(pageStore, treeRoot); treeBeforeSave.Save(1, null); //ValidateScan(treeBeforeSave.Scan(null), keyCount, pageStoreName + " before save"); pageStore.Commit(1, null); pageStore.Close(); using(var ps = TestUtils.OpenPageStore(pageStoreName, true, persistenceType, 1)) { var tree = new BPlusTree(ps, treeRoot); tree.DumpStructure(); ValidateScan(tree.Scan(null), keyCount, pageStoreName + " after save"); ValidateSearch(tree, keyCount, pageStoreName + "after save"); } }
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 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 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 TestBatchedInserts() { var rng = new Random(); var keyBuff = new byte[8]; var value = new byte[64]; ulong key = 0; var txnId = 0ul; var inserted = new HashSet<ulong>(); inserted.Add(0); // Not using enumerable initializer because its not supported in the mobile build using (var pageStore = TestUtils.CreateEmptyPageStore("TestBatchedInserts.data")) { var tree = new BPlusTree(txnId, pageStore); for (int i = 1; i <= 10000; i++) { while (inserted.Contains(key)) { rng.NextBytes(keyBuff); key = BitConverter.ToUInt64(keyBuff, 0); } inserted.Add(key); tree.Insert(txnId, key, value); if (i%250 == 0) { tree.Save((ulong)i / 250, null); pageStore.Commit((ulong)i / 250, null); //Console.WriteLine("Dump tree @ commit after {0}", i); //tree.DumpStructure(); Assert.AreEqual(i, tree.Scan(0, ulong.MaxValue, null).Count()); } } } }
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 } }