Пример #1
0
        public void TestBorrowLeft()
        {
            var config = new BPlusTreeConfiguration(8, 8, 4096);

            var leftNode  = new LeafNode(1ul, 0ul, 0ul, config);
            var rightNode = new LeafNode(2ul, 0ul, 0ul, config);

            byte[] testBytes = new byte[] { 1, 2, 3, 4 };
            leftNode.Insert(BitConverter.GetBytes(1ul), testBytes);
            leftNode.Insert(BitConverter.GetBytes(2ul), testBytes);
            leftNode.Insert(BitConverter.GetBytes(3ul), testBytes);
            leftNode.Insert(BitConverter.GetBytes(4ul), testBytes);
            leftNode.Insert(BitConverter.GetBytes(5ul), testBytes);

            rightNode.Insert(BitConverter.GetBytes(10ul), testBytes);
            rightNode.Insert(BitConverter.GetBytes(11ul), testBytes);

            Assert.IsTrue(rightNode.RedistributeFromLeft(leftNode));
            Assert.IsTrue(rightNode.KeyCount == 3);

            TestUtils.AssertBuffersEqual(rightNode.LeftmostKey, BitConverter.GetBytes(5ul));
            Assert.IsTrue(leftNode.KeyCount == 4);
            TestUtils.AssertBuffersEqual(leftNode.RightmostKey, BitConverter.GetBytes(4ul));

            leftNode.Delete(BitConverter.GetBytes(1ul));
            leftNode.Delete(BitConverter.GetBytes(2ul));
            Assert.IsFalse(rightNode.RedistributeFromLeft(leftNode));
        }
Пример #2
0
 /// <summary>
 /// Creates a new tree in the page store
 /// </summary>
 /// <param name="txnId">The transaction id for the update</param>
 /// <param name="pageStore"></param>
 /// <param name="keySize">The size of the B+ tree's key (in bytes)</param>
 /// <param name="dataSize">The size of the values stored in leaf nodes (in bytes)</param>
 public BPlusTree(ulong txnId, IPageStore pageStore, int keySize = 8, int dataSize = 64) 
 {
     _config = new BPlusTreeConfiguration(pageStore, keySize, dataSize, pageStore.PageSize);
     _pageStore = pageStore;
     var root = MakeLeafNode(txnId);
     _rootId = root.PageId;
 }
Пример #3
0
 /// <summary>
 /// Opens an existing tree in the page store
 /// </summary>
 /// <param name="pageStore"></param>
 /// <param name="rootPageId">The page ID of the BTree root node</param>
 /// <param name="keySize"></param>
 /// <param name="dataSize"></param>
 /// <param name="profiler"></param>
 public BPlusTree(IPageStore pageStore, ulong rootPageId, int keySize = 8, int dataSize = 64, BrightstarProfiler profiler = null)
 {
     _config = new BPlusTreeConfiguration(pageStore, keySize, dataSize, pageStore.PageSize);
     _pageStore = pageStore;
     var root = GetNode(rootPageId, profiler);
     _rootId = root.PageId;
 }
Пример #4
0
        public void TestBorrowLeft()
        {
            var config = new BPlusTreeConfiguration(8, 8, 4096);

            var leftNode = new LeafNode(1ul, 0ul, 0ul, config);
            var rightNode = new LeafNode(2ul, 0ul, 0ul, config);
            byte[] testBytes = new byte[]{1,2,3,4};
            leftNode.Insert(BitConverter.GetBytes(1ul), testBytes);
            leftNode.Insert(BitConverter.GetBytes(2ul), testBytes); 
            leftNode.Insert(BitConverter.GetBytes(3ul), testBytes); 
            leftNode.Insert(BitConverter.GetBytes(4ul), testBytes); 
            leftNode.Insert(BitConverter.GetBytes(5ul), testBytes);

            rightNode.Insert(BitConverter.GetBytes(10ul), testBytes);
            rightNode.Insert(BitConverter.GetBytes(11ul), testBytes);

            Assert.IsTrue(rightNode.RedistributeFromLeft(leftNode));
            Assert.IsTrue(rightNode.KeyCount == 3);
            
            TestUtils.AssertBuffersEqual(rightNode.LeftmostKey, BitConverter.GetBytes(5ul));
            Assert.IsTrue(leftNode.KeyCount == 4);
            TestUtils.AssertBuffersEqual(leftNode.RightmostKey, BitConverter.GetBytes(4ul));

            leftNode.Delete(BitConverter.GetBytes(1ul));
            leftNode.Delete(BitConverter.GetBytes(2ul));
            Assert.IsFalse(rightNode.RedistributeFromLeft(leftNode));
        }
Пример #5
0
        public void TestLeafNodeSplit()
        {
            var pageStore = new MemoryPageStore(4096);
            var config    = new BPlusTreeConfiguration(pageStore, 8, 8, 4096);
            var firstNode = new LeafNode(pageStore.Create(0), 0, 0, config);
            var testBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

            for (int i = 0; i < config.LeafLoadFactor; i++)
            {
                firstNode.Insert(0, BitConverter.GetBytes((ulong)i), testBytes);
            }

            var secondNodePage = pageStore.Create(0);
            var splitKey       = new byte[8];
            var secondNode     = firstNode.Split(0, secondNodePage, out splitKey);

            Assert.AreEqual(config.LeafSplitIndex, firstNode.KeyCount);
            Assert.AreEqual(config.LeafLoadFactor - config.LeafSplitIndex, secondNode.KeyCount);

            var firstNodePage     = pageStore.Retrieve(0, null);
            var firstNodeKeyCount = BitConverter.ToInt32(firstNodePage.Data, 0);

            secondNodePage = pageStore.Retrieve(1, null);
            var secondNodeKeyCount = BitConverter.ToInt32(secondNodePage.Data, 0);

            Assert.AreEqual(config.LeafSplitIndex, firstNodeKeyCount);
            Assert.AreEqual(config.LeafLoadFactor - config.LeafSplitIndex, secondNodeKeyCount);
        }
Пример #6
0
        public void TestBorrowRight()
        {
            var pageStore = new MemoryPageStore(4096);
            var config    = new BPlusTreeConfiguration(pageStore, 8, 8, 4096);
            var leftNode  = new LeafNode(pageStore.Create(0), 0, 0, config);
            var rightNode = new LeafNode(pageStore.Create(0), 0, 0, config);

            byte[] testBytes = new byte[] { 1, 2, 3, 4 };

            leftNode.Insert(1, BitConverter.GetBytes(1ul), testBytes);
            leftNode.Insert(1, BitConverter.GetBytes(2ul), testBytes);

            rightNode.Insert(1, BitConverter.GetBytes(10ul), testBytes);
            rightNode.Insert(1, BitConverter.GetBytes(11ul), testBytes);
            rightNode.Insert(1, BitConverter.GetBytes(12ul), testBytes);
            rightNode.Insert(1, BitConverter.GetBytes(13ul), testBytes);
            rightNode.Insert(1, BitConverter.GetBytes(14ul), testBytes);

            Assert.IsTrue(leftNode.RedistributeFromRight(1, rightNode));
            Assert.IsTrue(leftNode.KeyCount == 3);
            TestUtils.AssertBuffersEqual(BitConverter.GetBytes(10ul), leftNode.RightmostKey);
            TestUtils.AssertBuffersEqual(BitConverter.GetBytes(11ul), rightNode.LeftmostKey);
            Assert.IsTrue(rightNode.KeyCount == 4);
            Assert.IsFalse(leftNode.RedistributeFromRight(1, rightNode));
        }
Пример #7
0
        public LeafNode(ulong nodeId, byte[] nodePage, int keyCount, BPlusTreeConfiguration treeConfiguration)
        {
            _config = treeConfiguration;
            _keyCount = keyCount;
            _prevPointer = BitConverter.ToUInt64(nodePage, 4);
            _nextPointer = BitConverter.ToUInt64(nodePage, 12);
            _keys = new byte[_config.LeafLoadFactor][];
            _dataSegments = new byte[_config.LeafLoadFactor][];

            for (int i = 0, j = BPlusTreeConfiguration.LeafNodeHeaderSize; i < _keyCount; i++,j += _config.KeySize)
            {
                _keys[i] = new byte[_config.KeySize];
                Array.Copy(nodePage, j, _keys[i], 0, _config.KeySize);
            }
            if (_config.ValueSize > 0)
            {
                for (int i = 0, j = _config.LeafDataStartOffset; i < _keyCount; i++, j += (_config.ValueSize + 1))
                {
                    byte dataLength = nodePage[j];
                    _dataSegments[i] = new byte[dataLength];
                    Array.Copy(nodePage, j + 1, _dataSegments[i], 0, dataLength);
                }
            }
            PageId = nodeId;
            IsDirty = false;
        }
Пример #8
0
        public void TestLeafNodeSplit()
        {
            var pageStore = new MemoryPageStore(4096);
            var config = new BPlusTreeConfiguration(pageStore, 8, 8, 4096);
            var firstNode = new LeafNode(pageStore.Create(0), 0, 0, config);
            var testBytes = new byte[]{1,2,3,4,5,6,7,8};
            for (int i = 0; i < config.LeafLoadFactor; i++)
            {
                firstNode.Insert(0, BitConverter.GetBytes((ulong)i), testBytes);
            }

            var secondNodePage = pageStore.Create(0);
            var splitKey = new byte[8];
            var secondNode = firstNode.Split(0, secondNodePage, out splitKey);

            Assert.AreEqual(config.LeafSplitIndex, firstNode.KeyCount);
            Assert.AreEqual(config.LeafLoadFactor - config.LeafSplitIndex, secondNode.KeyCount);

            var firstNodePage = pageStore.Retrieve(0, null);
            var firstNodeKeyCount = BitConverter.ToInt32(firstNodePage.Data, 0);
            secondNodePage = pageStore.Retrieve(1, null);
            var secondNodeKeyCount = BitConverter.ToInt32(secondNodePage.Data, 0);
            Assert.AreEqual(config.LeafSplitIndex, firstNodeKeyCount);
            Assert.AreEqual(config.LeafLoadFactor - config.LeafSplitIndex, secondNodeKeyCount);
            
        }
Пример #9
0
        public void TestBorrowRight()
        {
            var pageStore = new MemoryPageStore(4096);
            var config = new BPlusTreeConfiguration(pageStore, 8, 8, 4096);
            var leftNode = new LeafNode(pageStore.Create(0), 0, 0, config);
            var rightNode = new LeafNode(pageStore.Create(0), 0, 0, config);

            byte[] testBytes = new byte[] { 1, 2, 3, 4 };

            leftNode.Insert(1, BitConverter.GetBytes(1ul), testBytes);
            leftNode.Insert(1, BitConverter.GetBytes(2ul), testBytes);

            rightNode.Insert(1, BitConverter.GetBytes(10ul), testBytes);
            rightNode.Insert(1, BitConverter.GetBytes(11ul), testBytes);
            rightNode.Insert(1, BitConverter.GetBytes(12ul), testBytes);
            rightNode.Insert(1, BitConverter.GetBytes(13ul), testBytes);
            rightNode.Insert(1, BitConverter.GetBytes(14ul), testBytes);

            Assert.IsTrue(leftNode.RedistributeFromRight(1, rightNode));
            Assert.IsTrue(leftNode.KeyCount == 3);
            TestUtils.AssertBuffersEqual(BitConverter.GetBytes(10ul), leftNode.RightmostKey);
            TestUtils.AssertBuffersEqual(BitConverter.GetBytes(11ul), rightNode.LeftmostKey);
            Assert.IsTrue(rightNode.KeyCount == 4);
            Assert.IsFalse(leftNode.RedistributeFromRight(1, rightNode));
        }
Пример #10
0
        public ulong Write(IPageStore pageStore, ulong transactionId, BrightstarProfiler profiler)
        {
            var targetConfiguration = new BPlusTreeConfiguration(pageStore, Configuration.KeySize,
                                                                 Configuration.ValueSize, Configuration.PageSize);
            var builder = new BPlusTreeBuilder(pageStore, targetConfiguration);

            return(builder.Build(transactionId, Scan(profiler), profiler));
        }
Пример #11
0
 public BPlusTreeBuilder(IPageStore targetPageStore, BPlusTreeConfiguration targetTreeConfiguration)
 {
     _pageStore = targetPageStore;
     _config = targetTreeConfiguration;
     // These values are copied locally to allow us to later change the default loading from 100% to something lower if we want
     _leafLoadFactor = _config.LeafLoadFactor;
     _internalBranchFactor = _config.InternalBranchFactor;
 }
Пример #12
0
 /// <summary>
 /// Creates a new tree in the page store
 /// </summary>
 /// <param name="txnId">The transaction id for the update</param>
 /// <param name="pageStore"></param>
 /// <param name="keySize">The size of the B+ tree's key (in bytes)</param>
 /// <param name="dataSize">The size of the values stored in leaf nodes (in bytes)</param>
 public BPlusTree(ulong txnId, IPageStore pageStore, int keySize = 8, int dataSize = 64) 
 {
     _config = new BPlusTreeConfiguration(pageStore, keySize, dataSize, pageStore.PageSize);
     _pageStore = pageStore;
     var root = MakeLeafNode(txnId);
     _rootId = root.PageId;
     _nodeCache = new WeakReferenceNodeCache();
     _nodeCache.Add(root);
 }
Пример #13
0
 /// <summary>
 /// Opens an existing tree in the page store
 /// </summary>
 /// <param name="pageStore"></param>
 /// <param name="rootPageId">The page ID of the BTree root node</param>
 /// <param name="keySize"></param>
 /// <param name="dataSize"></param>
 /// <param name="profiler"></param>
 public BPlusTree(IPageStore pageStore, ulong rootPageId, int keySize = 8, int dataSize = 64, BrightstarProfiler profiler = null)
 {
     _config = new BPlusTreeConfiguration(keySize, dataSize, pageStore.PageSize);
     _pageStore = pageStore;
     _modifiedNodes = new Dictionary<ulong, INode>();
     _nodeCache = new WeakReferenceNodeCache();
     _root = GetNode(rootPageId, profiler);
     _nodeCache.Add(_root);
 }
 public void TestRightShiftFrom()
 {
     var pageStore = new MemoryPageStore(1024);
     var config = new BPlusTreeConfiguration( pageStore, 8, 8, 1024);
     var n = new InternalNode(pageStore.Create(0), BitConverter.GetBytes(50ul), 2,3, config);
     n.Insert(1, BitConverter.GetBytes(100ul), 4);
     Assert.AreEqual(50ul, BitConverter.ToUInt64(n.LeftmostKey, 0));
     Assert.AreEqual(100ul, BitConverter.ToUInt64(n.RightmostKey, 0));
 }
Пример #15
0
        /// <summary>
        /// Initializes a new node using the data contained in the specified persisten storage page
        /// </summary>
        /// <param name="page">The page used to back the node</param>
        /// <param name="keyCount">The number of keys in the node (as read from page data)</param>
        /// <param name="treeConfig">The tree configuration parameters</param>
        /// <remarks>Strictly speaking we don't have to pass the key count because it can be read from
        /// the page data. However, the code that invokes this constructor needs to check the key
        /// count value to see if a node contains a leaf or an internal node and having this constructor
        /// separate from one that specifies that the page is empty initially is also convenient</remarks>
        public InternalNode(IPage page, int keyCount, BPlusTreeConfiguration treeConfig)
        {
            _config = treeConfig;
            _page = page;
            _keyCount = keyCount;
#if DEBUG_BTREE
            treeConfig.BTreeDebug("+Internal {0}", page.Id);
#endif
        }
Пример #16
0
        public void TestRightShiftFrom()
        {
            var pageStore = new MemoryPageStore(1024);
            var config    = new BPlusTreeConfiguration(pageStore, 8, 8, 1024);
            var n         = new InternalNode(pageStore.Create(0), BitConverter.GetBytes(50ul), 2, 3, config);

            n.Insert(1, BitConverter.GetBytes(100ul), 4);
            Assert.AreEqual(50ul, BitConverter.ToUInt64(n.LeftmostKey, 0));
            Assert.AreEqual(100ul, BitConverter.ToUInt64(n.RightmostKey, 0));
        }
Пример #17
0
 /// <summary>
 /// Creates a new tree in the page store
 /// </summary>
 /// <param name="pageStore"></param>
 /// <param name="keySize">The size of the B+ tree's key (in bytes)</param>
 /// <param name="dataSize">The size of the values stored in leaf nodes (in bytes)</param>
 public BPlusTree(IPageStore pageStore, int keySize = 8, int dataSize = 64) 
 {
     _config = new BPlusTreeConfiguration(keySize, dataSize, pageStore.PageSize);
     _pageStore = pageStore;
     _modifiedNodes = new Dictionary<ulong, INode>();
     _root = new LeafNode(pageStore.Create(), 0, 0, _config);
     _nodeCache = new WeakReferenceNodeCache();
     _modifiedNodes[_root.PageId] = _root;
     _nodeCache.Add(_root);
 }
 public ulong Write(IPageStore pageStore, ulong transactionId, BrightstarProfiler profiler)
 {
     using (profiler.Step("RelatedResourceIndex.Write"))
     {
         var targetConfiguration = new BPlusTreeConfiguration(pageStore, Configuration.KeySize,
                                                              Configuration.ValueSize, Configuration.PageSize);
         var indexBuilder = new BPlusTreeBuilder(pageStore, targetConfiguration);
         return(indexBuilder.Build(transactionId, WritePredicateIndexes(pageStore, transactionId, profiler),
                                   profiler));
     }
 }
Пример #19
0
 public LeafNode(ulong reservedPageId, ulong prevPointer, ulong nextPointer, BPlusTreeConfiguration treeConfig)
 {
     _config = treeConfig;
     _keyCount = 0;
     _prevPointer = prevPointer;
     _nextPointer = nextPointer;
     _keys = new byte[_config.LeafLoadFactor][];
     _dataSegments = new byte[_config.LeafLoadFactor][];
     PageId = reservedPageId;
     IsDirty = true;
 }
Пример #20
0
        public LeafNode(IPage page, int keyCount, BPlusTreeConfiguration treeConfiguration)
        {
            _page = page;
            _keyCount = keyCount;
            _prevPointer = BitConverter.ToUInt64(_page.Data, 4);
            _nextPointer = BitConverter.ToUInt64(_page.Data, 12);
            _config = treeConfiguration;
#if DEBUG_BTREE
            _config.BTreeDebug("+Leaf2 {0}", _page.Id);
#endif
        }
Пример #21
0
        /// <summary>
        /// Creates a new node backed by the specified persistent storage page that has only
        /// a single child node pointer
        /// </summary>
        /// <param name="page">The page used to back the node. Must be writeable.</param>
        /// <param name="onlyChild">The child node pointer</param>
        /// <param name="treeConfiguration">The tree configuration</param>
        /// <exception cref="InvalidOperationException">Raised if <paramref name="page"/> is not a writeable page</exception>
        public InternalNode(IPage page, ulong onlyChild, BPlusTreeConfiguration treeConfiguration)
        {
            _config = treeConfiguration;
            AssertWriteable(page);
            _page = page;
            _page.SetData(BitConverter.GetBytes(onlyChild), 0, PointerOffset(0), 8);
            KeyCount = 0;
#if DEBUG_BTREE
            _config.BTreeDebug("+Internal {0}", _page.Id);
#endif
        }
Пример #22
0
        /// <summary>
        /// Creates a leaf node that will be backed by a new page
        /// </summary>
        /// <param name="reservedPage">The backing page for this node. Must be writeable</param>
        /// <param name="prevPointer">UNUSED</param>
        /// <param name="nextPointer">UNUSED</param>
        /// <param name="treeConfiguration">The tree configuration parameters</param>
        public LeafNode(IPage reservedPage, ulong prevPointer, ulong nextPointer,
                              BPlusTreeConfiguration treeConfiguration)
        {
            _config = treeConfiguration;
            AssertWriteable(reservedPage);
            _page = reservedPage;
            KeyCount = 0;
            Prev = prevPointer;
            Next = nextPointer;
#if DEBUG_BTREE
            _config.BTreeDebug("+Leaf1 {0}", _page.Id);
#endif
        }
 private IEnumerable <KeyValuePair <byte[], byte []> > WritePredicateIndexes(IPageStore pageStore, ulong transactionId, BrightstarProfiler profiler)
 {
     foreach (var entry in EnumeratePredicateIndexes(profiler))
     {
         var predicateId         = entry.Key;
         var targetConfiguration = new BPlusTreeConfiguration(pageStore, entry.Value.Configuration.KeySize,
                                                              entry.Value.Configuration.ValueSize,
                                                              entry.Value.Configuration.PageSize);
         var   builder             = new BPlusTreeBuilder(pageStore, targetConfiguration);
         ulong newPredicateIndexId = builder.Build(transactionId, entry.Value.Scan(profiler), profiler);
         yield return(new KeyValuePair <byte[], byte[]>(BitConverter.GetBytes(predicateId), BitConverter.GetBytes(newPredicateIndexId)));
     }
 }
Пример #24
0
        /// <summary>
        /// Creates a new node backed by the specified persistent storage page with a single
        /// key and left and right pointers.
        /// </summary>
        /// <param name="page">The page used to back the node. Must be writeable.</param>
        /// <param name="splitKey">The key that separates left and right child pointers</param>
        /// <param name="leftPageId">The left child node pointer</param>
        /// <param name="rightPageId">The right child node pointer</param>
        /// <param name="treeConfiguration">The tree configuration</param>
        /// <exception cref="InvalidOperationException">Raised if <paramref name="page"/> is not a writeable page</exception>
        public InternalNode(IPage page, byte[] splitKey, ulong leftPageId, ulong rightPageId,
                                  BPlusTreeConfiguration treeConfiguration)
        {
            _config = treeConfiguration;
            AssertWriteable(page);
            _page = page;
            _page.SetData(splitKey, 0, KeyOffset(0), _config.KeySize);
            _page.SetData(BitConverter.GetBytes(leftPageId), 0, PointerOffset(0), 8);
            _page.SetData(BitConverter.GetBytes(rightPageId), 0, PointerOffset(1), 8);
            KeyCount = 1;
#if DEBUG_BTREE
            _config.BTreeDebug("+Internal {0}", _page.Id);
#endif
        }
Пример #25
0
        public void TestCoalesceRootLeafNode()
        {
            const string storeName = "Coalesce.RootLeafNode.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; 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 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);
                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));
                }
            }
        }
Пример #26
0
        public void TestCoalesceRootLeafNode()
        {
            const string storeName = "Coalesce.RootLeafNode.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; 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 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);
                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));
                }
            }
        }
Пример #27
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");
     }
 }
Пример #28
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");
            }
        }
Пример #29
0
 /// <summary>
 /// Creates a new leaf node with content loaded from an ordered enumeration of key/value pairs
 /// </summary>
 /// <param name="reservedPageId"></param>
 /// <param name="prevPointer"></param>
 /// <param name="nextPointer"></param>
 /// <param name="treeConfiguration"></param>
 /// <param name="orderedValues">The enumerateion of key-value pairs to load into the leaf node</param>
 /// <param name="numValuesToLoad">The maximum number of key-value pairs to insert into the new leaf node</param>
 public LeafNode(ulong reservedPageId, ulong prevPointer, ulong nextPointer, BPlusTreeConfiguration treeConfiguration, IEnumerable<KeyValuePair<byte[], byte []>> orderedValues, int numValuesToLoad)
 {
     _config = treeConfiguration;
     _prevPointer = prevPointer;
     _nextPointer = nextPointer;
     _keys = new byte[_config.LeafLoadFactor][];
     _dataSegments = new byte[_config.LeafLoadFactor][];
     PageId = reservedPageId;
     IsDirty = true;
     _keyCount = 0;
     foreach(var kvp in orderedValues.Take(numValuesToLoad))
     {
         _keys[_keyCount] = new byte[_config.KeySize];
         _dataSegments[_keyCount] = new byte[_config.ValueSize];
         Array.Copy(kvp.Key, _keys[_keyCount], _config.KeySize);
         if (_config.ValueSize > 0)
         {
             Array.Copy(kvp.Value, _dataSegments[_keyCount], _config.ValueSize);
         }
         _keyCount++;
     }
 }
Пример #30
0
        public LeafNode(IPage page, ulong prevPointer, ulong nextPointer,
                              BPlusTreeConfiguration treeConfiguration,
                              IEnumerable<KeyValuePair<byte[], byte[]>> orderedValues, int numValuesToLoad)
        {
            _page = page;
            _config = treeConfiguration;
            Prev = prevPointer;
            Next = nextPointer;
            int numLoaded = 0;
            foreach (var kvp in orderedValues.Take(numValuesToLoad))
            {
                SetKey(numLoaded, kvp.Key);
                if (_config.ValueSize > 0)
                {
                    SetValue(numLoaded, kvp.Value);
                }
                numLoaded++;
            }
            KeyCount = numLoaded;
#if DEBUG_BTREE
            _config.BTreeDebug("+Leaf3 {0}", _page.Id);
#endif
        }
Пример #31
0
        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
            }
        }
Пример #32
0
 private InternalNode(ulong pageId, BPlusTreeConfiguration treeConfiguration)
 {
     _config = treeConfiguration;
     PageId = pageId;
     _keys = new byte[_config.InternalBranchFactor][];
     _childPointers = new ulong[_config.InternalBranchFactor + 1];
     _keyCount = 0;
     IsDirty = true;
 }
Пример #33
0
 public ulong Write(IPageStore pageStore, ulong  transactionId, BrightstarProfiler profiler)
 {
     var targetConfiguration = new BPlusTreeConfiguration(pageStore, Configuration.KeySize,
                                                          Configuration.ValueSize, Configuration.PageSize);
     var builder = new BPlusTreeBuilder(pageStore, targetConfiguration);
     return builder.Build(transactionId, Scan(profiler), profiler);
 }
Пример #34
0
 public InternalNode(ulong pageId, byte[] key, ulong leftChild, ulong rightChild,
                     BPlusTreeConfiguration treeConfiguration)
 {
     _config = treeConfiguration;
     PageId = pageId;
     _keys = new byte[_config.InternalBranchFactor][];
     _childPointers = new ulong[_config.InternalBranchFactor + 1];
     _keys[0] = key; // TODO: copy key ?
     _childPointers[0] = leftChild;
     _childPointers[1] = rightChild;
     _keyCount = 1;
     IsDirty = true;
 }
Пример #35
0
 private IEnumerable<KeyValuePair<byte[], byte []>> WritePredicateIndexes(IPageStore pageStore, ulong transactionId, BrightstarProfiler profiler)
 {
     foreach (var entry in EnumeratePredicateIndexes(profiler))
     {
         var predicateId = entry.Key;
         var targetConfiguration = new BPlusTreeConfiguration(pageStore, entry.Value.Configuration.KeySize,
                                                              entry.Value.Configuration.ValueSize,
                                                              entry.Value.Configuration.PageSize);
         var builder = new BPlusTreeBuilder(pageStore, targetConfiguration);
         ulong newPredicateIndexId = builder.Build(transactionId, entry.Value.Scan(profiler), profiler);
         yield return new KeyValuePair<byte[], byte[]>(BitConverter.GetBytes(predicateId), BitConverter.GetBytes(newPredicateIndexId));
     }
 }
Пример #36
0
 public ulong Write(IPageStore pageStore, ulong transactionId, BrightstarProfiler profiler)
 {
     using (profiler.Step("RelatedResourceIndex.Write"))
     {
         var targetConfiguration = new BPlusTreeConfiguration(pageStore, Configuration.KeySize,
                                                              Configuration.ValueSize, Configuration.PageSize);
         var indexBuilder = new BPlusTreeBuilder(pageStore, targetConfiguration);
         return indexBuilder.Build(transactionId, WritePredicateIndexes(pageStore, transactionId, profiler),
                                   profiler);
     }
 }
Пример #37
0
        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
            }
            
        }
Пример #38
0
 public InternalNode(ulong id, ulong onlyChild, BPlusTreeConfiguration treeConfiguration)
 {
     _config = treeConfiguration;
     PageId = id;
     _keyCount = 0;
     _keys = new byte[_config.InternalBranchFactor][];
     _childPointers = new ulong[_config.InternalBranchFactor+1];
     _childPointers[0] = onlyChild;
 }
Пример #39
0
 public InternalNode(ulong id, byte[] nodePage, int keyCount, BPlusTreeConfiguration treeConfiguration)
 {
     _config = treeConfiguration;
     PageId = id;
     _keyCount = keyCount;
     _keys = new byte[_config.InternalBranchFactor][];
     for (int i = 0, offset = BPlusTreeConfiguration.InternalNodeHeaderSize;
          i < _keyCount;
          i++, offset += _config.KeySize)
     {
         _keys[i] = new byte[_config.KeySize];
         Array.Copy(nodePage, offset, _keys[i], 0, _config.KeySize);
     }
     _childPointers = ByteArrayHelper.ToUlongArray(nodePage, _config.InternalNodeChildStartOffset,
                                                   _config.InternalBranchFactor + 1);
 }
Пример #40
0
 public InternalNode(ulong id, List<byte[]> keys, List<ulong >childPointers, BPlusTreeConfiguration treeConfiguration)
 {
     _config = treeConfiguration;
     PageId = id;
     _keyCount = keys.Count;
     _keys = new byte[_config.InternalBranchFactor][];
     _childPointers = new ulong[_config.InternalBranchFactor + 1];
     for (int i = 0; i < _keyCount; i++)
     {
         _keys[i] = keys[i];
     }
     for(int i = 0; i <= _keyCount; i++)
     {
         _childPointers[i] = childPointers[i];
     }
 }