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)); }
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); }
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); }
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); }
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); }
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); } } }
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); }