Example #1
0
        public short AddNode(RadixTreePageBackingObject backingObject, IRadixTreeNode node, int prefixSize, int childCapacity)
        {
            var size     = backingObject.Size;
            var nodeSize = GetNodeSize((short)prefixSize, childCapacity);

            if (size + nodeSize > _pageManager.PageSize)
            {
                return(-1);
            }

            for (short i = 0; i < backingObject.Items.Count; i++)
            {
                if (backingObject.Items[i] == null)
                {
                    backingObject.Items[i] = node;
                    return(i);
                }
            }

            if (size + nodeSize + PageFormatter.OnPagePointerSize > _pageManager.PageSize)
            {
                return(-1);
            }

            backingObject.Items.Add(node);

            return((short)(backingObject.Items.Count - 1));
        }
Example #2
0
        public IRadixTreeNode Fetch(DbItemReference reference)
        {
            if (DbItemReference.IsNull(reference))
            {
                return(null);
            }

            var page = _pageManager.FetchPage(reference.PageIndex);

            if (page.BackingObject == null)
            {
                var obj1 = RadixTreePageBackingObject.FromPage(page);
                page = new Page(_pageManager, page.Index, () => Serialize(obj1), obj1);
            }

            var backingObject = (RadixTreePageBackingObject)page.BackingObject;

            var obj = backingObject.Items[reference.ItemIndex];

            var result = obj as IRadixTreeNode;

            if (result == null)
            {
                result           = NodeFromBytes((byte[])obj);
                result.Reference = (DbItemReference)reference.Clone();
                backingObject.Items[reference.ItemIndex] = result;
            }

            return(result);
        }
Example #3
0
        public bool Update(IRadixTreeNode node)
        {
            var page = _pageManager.FetchPage(node.Reference.PageIndex);

            if (page.BackingObject == null)
            {
                var obj = RadixTreePageBackingObject.FromPage(page);
                page = new Page(_pageManager, node.Reference.PageIndex, () => Serialize(obj), obj);
            }

            var backingObject = (RadixTreePageBackingObject)page.BackingObject;
            var oldNodeSize   = backingObject.GetNodeSize(node.Reference.ItemIndex);

            var newNodeSize = GetNodeSize((short)node.Prefix.Length, node.Entries.Count);

            var oldObjectSize = backingObject.Size;

            var newObjectSize = oldObjectSize + newNodeSize - oldNodeSize;

            if (newObjectSize > _pageManager.PageSize)
            {
                return(false);
            }

            backingObject.Items[node.Reference.ItemIndex] = node;

            _pageManager.UpdatePage(page);
            return(true);
        }
Example #4
0
        public static RadixTreePageBackingObject FromPage(IPage page)
        {
            var result = new RadixTreePageBackingObject(page.Index);
            var items  = PageFormatter.ReadVariableSizeItems(page);

            foreach (var item in items)
            {
                result.Items.Add(item);
            }

            return(result);
        }
Example #5
0
        public IRadixTreeNode Create(int prefixSize, int childCapacity)
        {
            CheckRoot();

            IPage page;
            short itemIndex;
            var   node = NewNode(DbItemReference.Null);

            foreach (var pageIndex in _recentPages)
            {
                page = _pageManager.FetchPage(pageIndex);

                if (page.BackingObject == null)
                {
                    var obj = RadixTreePageBackingObject.FromPage(page);
                    page = new Page(_pageManager, pageIndex, () => Serialize(obj), obj);
                }

                var backingObject = (RadixTreePageBackingObject)page.BackingObject;

                itemIndex = AddNode(backingObject, node, prefixSize, childCapacity);

                if (itemIndex != -1)
                {
                    UpdateRecentPage(page.Index);
                    node.Reference = new DbItemReference(page.Index, itemIndex);
                    _pageManager.UpdatePage(page);
                    return(node);
                }
            }

            page = _pageManager.CreatePage();
            var  obj1   = new RadixTreePageBackingObject(page.Index);
            long index1 = page.Index;

            page = new Page(_pageManager, index1, () => Serialize(obj1), obj1);

            itemIndex = AddNode((RadixTreePageBackingObject)page.BackingObject, node, prefixSize, childCapacity);
            if (itemIndex != -1)
            {
                UpdateRecentPage(page.Index);
                node.Reference = new DbItemReference(page.Index, itemIndex);
                _pageManager.UpdatePage(page);
                return(node);
            }

            Debug.Fail("Should never get here");
            return(null);
        }
Example #6
0
        public void Remove(DbItemReference reference)
        {
            if (_rootNodeReference.Equals(reference))
            {
                throw new ArgumentOutOfRangeException(nameof(reference), "Unable to delete the root node");
            }

            var page = _pageManager.FetchPage(reference.PageIndex);

            if (page.BackingObject == null)
            {
                var obj = RadixTreePageBackingObject.FromPage(page);
                page = new Page(_pageManager, reference.PageIndex, () => Serialize(obj), obj);
            }

            var backingObject = (RadixTreePageBackingObject)page.BackingObject;

            if (backingObject.Items.Count == reference.ItemIndex + 1)
            {
                backingObject.Items.RemoveAt(reference.ItemIndex);
            }
            else
            {
                backingObject.Items[reference.ItemIndex] = null;
            }

            if (backingObject.Items.Any(item => item != null))
            {
                _pageManager.UpdatePage(page);
            }
            else
            {
                _pageManager.RemovePage(page.Index);
                if (_recentPages.Contains(page.Index))
                {
                    _recentPages.Remove(page.Index);
                }
            }
        }
Example #7
0
        private byte[] Serialize(RadixTreePageBackingObject backingObject)
        {
            var header = new RadixTreeNodesPageHeader();

            var page = new Page(_pageManager, backingObject.PageIndex, new byte[_pageManager.PageSize]);

            var items = backingObject.Items.Select(item =>
            {
                if (item is byte[] bytes)
                {
                    return(bytes);
                }
                if (item == null)
                {
                    return(new byte[0]);
                }
                return(GetNodeBytes((IRadixTreeNode)item, 0));
            }).ToList();

            PageFormatter.FormatVariableSizeItemsPage(page, header, items);

            return(page.Content);
        }