public void InsertVariableSizeItemAfterDelete() { int pageSize = 4096; var dummyPageManager = new FileSystemPageManager(pageSize); var p = new Page(dummyPageManager, 0, new byte[pageSize]); var header = new RadixTreeNodesPageHeader { FreeSpace = (ushort)PageFormatter.GetMaximalFreeSpace((PageSize)p.Length) }; PageFormatter.InitPage(p, header); var r = new Random(); var items = new List <byte[]>(); var item = new byte[r.Next(100) + 1]; r.NextBytes(item); short itemIndex = 0; while (itemIndex != -1) { itemIndex = PageFormatter.AddVariableSizeItem(p, item); items.Add(item); item = new byte[r.Next(100) + 1]; r.NextBytes(item); } bool hasRemainingItems; // replace with the same PageFormatter.DeleteVariableSizeItem(p, 1, out hasRemainingItems); Assert.AreEqual(1, PageFormatter.AddVariableSizeItem(p, items[1])); item = PageFormatter.ReadVariableSizeItem(p, 1); Assert.IsTrue(AreEqualByteArrays(items[1], item)); // replace with smaller one PageFormatter.DeleteVariableSizeItem(p, 1, out hasRemainingItems); var smallItem = new byte[items[1].Length / 2 + 1]; r.NextBytes(smallItem); Assert.AreEqual(1, PageFormatter.AddVariableSizeItem(p, smallItem)); item = PageFormatter.ReadVariableSizeItem(p, 1); Assert.IsTrue(AreEqualByteArrays(smallItem, item)); // and put original again PageFormatter.DeleteVariableSizeItem(p, 1, out hasRemainingItems); PageFormatter.AddVariableSizeItem(p, items[1]); item = PageFormatter.ReadVariableSizeItem(p, 1); Assert.IsTrue(AreEqualByteArrays(items[1], item)); }
public void PageHasNoRemainingItemsAfterDelete() { int pageSize = 4096; var dummyPageManager = new FileSystemPageManager(pageSize); var p = new Page(dummyPageManager, 0, new byte[pageSize]); var header = new RadixTreeNodesPageHeader { FreeSpace = (ushort)PageFormatter.GetMaximalFreeSpace((PageSize)p.Length) }; PageFormatter.InitPage(p, header); var r = new Random(); var items = new List <byte[]>(); var item = new byte[r.Next(100) + 1]; r.NextBytes(item); short itemIndex = 0; while (itemIndex != -1) { itemIndex = PageFormatter.AddVariableSizeItem(p, item); if (itemIndex == -1) { continue; } items.Add(item); item = new byte[r.Next(100) + 1]; r.NextBytes(item); } bool hasRemainingItems; for (short i = 0; i < items.Count; i++) { PageFormatter.DeleteVariableSizeItem(p, i, out hasRemainingItems); if (i < items.Count - 1) { Assert.IsTrue(hasRemainingItems); } else { Assert.IsFalse(hasRemainingItems); } } }
public void ReadVariableSizeItems() { int pageSize = 4096; var dummyPageManager = new FileSystemPageManager(pageSize); var p = new Page(dummyPageManager, 0, new byte[pageSize]); var header = new RadixTreeNodesPageHeader { FreeSpace = (ushort)PageFormatter.GetMaximalFreeSpace((PageSize)p.Length) }; PageFormatter.InitPage(p, header); var r = new Random(); var items = new List <byte[]>(); var item = new byte[r.Next(100) + 1]; r.NextBytes(item); while (PageFormatter.AddVariableSizeItem(p, item) != -1) { items.Add(item); item = new byte[r.Next(100) + 1]; r.NextBytes(item); } for (short i = 0; i < items.Count; i++) { item = PageFormatter.ReadVariableSizeItem(p, i); Assert.IsTrue(AreEqualByteArrays(items[i], item)); } bool hasRemainingItems; PageFormatter.DeleteVariableSizeItem(p, 0, out hasRemainingItems); PageFormatter.DeleteVariableSizeItem(p, 2, out hasRemainingItems); PageFormatter.DeleteVariableSizeItem(p, (short)(items.Count - 1), out hasRemainingItems); Assert.Throws <PageFormatException>(() => PageFormatter.ReadVariableSizeItem(p, 0)); Assert.Throws <PageFormatException>(() => PageFormatter.ReadVariableSizeItem(p, 2)); Assert.Throws <PageFormatException>(() => PageFormatter.ReadVariableSizeItem(p, (short)(items.Count - 1))); }
protected override void Init() { base.Init(); //add access-method page IPage amPage = PageManager.CreatePage(); Debug.Assert(amPage.Index == 2, "The first access method page should have index 2"); var header = new RadixTreeNodesPageHeader { FreeSpace = (ushort)PageFormatter.GetMaximalFreeSpace((PageSize)PageManager.PageSize) }; PageFormatter.InitPage(amPage, header); PageManager.UpdatePage(amPage); }
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); }
public void CorrectWriteAndReadAllHeaders() { int pageSize = 4096; var dummyPageManager = new FileSystemPageManager(pageSize); var p = new Page(dummyPageManager, 0, new byte[pageSize]); var hph = new HeadingPageHeader(); PageFormatter.InitPage(p, hph); PageHeaderBase phb = PageFormatter.GetPageHeader(p); Assert.IsInstanceOf <HeadingPageHeader>(phb); Assert.AreEqual(hph.Length, phb.Length); Assert.AreEqual(hph.PageType, phb.PageType); Assert.AreEqual(hph.SizeRange, phb.SizeRange); var fsiph = new FixedSizeItemsPageHeader(); PageFormatter.InitPage(p, fsiph); phb = PageFormatter.GetPageHeader(p); Assert.IsInstanceOf <FixedSizeItemsPageHeader>(phb); Assert.AreEqual(fsiph.Length, phb.Length); Assert.AreEqual(fsiph.PageType, phb.PageType); Assert.AreEqual(fsiph.SizeRange, phb.SizeRange); var mpph = new MultipageItemPageHeader(); PageFormatter.InitPage(p, mpph); phb = PageFormatter.GetPageHeader(p); Assert.IsInstanceOf <MultipageItemPageHeader>(phb); Assert.AreEqual(mpph.Length, phb.Length); Assert.AreEqual(mpph.PageType, phb.PageType); Assert.AreEqual(mpph.SizeRange, phb.SizeRange); Assert.AreEqual(mpph.StartPageIndex, ((MultipageItemPageHeader)phb).StartPageIndex); Assert.AreEqual(mpph.PreviousPageIndex, ((MultipageItemPageHeader)phb).PreviousPageIndex); Assert.AreEqual(mpph.NextPageIndex, ((MultipageItemPageHeader)phb).NextPageIndex); var fsmph = new FreeSpaceMapPageHeader(); PageFormatter.InitPage(p, fsmph); phb = PageFormatter.GetPageHeader(p); Assert.IsInstanceOf <FreeSpaceMapPageHeader>(phb); Assert.AreEqual(fsmph.Length, phb.Length); Assert.AreEqual(fsmph.PageType, phb.PageType); Assert.AreEqual(fsmph.SizeRange, phb.SizeRange); Assert.AreEqual(fsmph.BasePageIndex, ((FreeSpaceMapPageHeader)phb).BasePageIndex); var tnph = new BPlusTreeNodePageHeader(); PageFormatter.InitPage(p, tnph); phb = PageFormatter.GetPageHeader(p); Assert.IsInstanceOf <BPlusTreeNodePageHeader>(phb); Assert.AreEqual(tnph.Length, phb.Length); Assert.AreEqual(tnph.PageType, phb.PageType); Assert.AreEqual(tnph.SizeRange, phb.SizeRange); Assert.AreEqual(tnph.ParentPageIndex, ((BPlusTreeNodePageHeader)phb).ParentPageIndex); Assert.AreEqual(tnph.PreviousPageIndex, ((BPlusTreeNodePageHeader)phb).PreviousPageIndex); Assert.AreEqual(tnph.NextPageIndex, ((BPlusTreeNodePageHeader)phb).NextPageIndex); var rtnph = new RadixTreeNodesPageHeader(); PageFormatter.InitPage(p, rtnph); phb = PageFormatter.GetPageHeader(p); Assert.IsInstanceOf <RadixTreeNodesPageHeader>(phb); Assert.AreEqual(rtnph.Length, phb.Length); Assert.AreEqual(rtnph.PageType, phb.PageType); Assert.AreEqual(rtnph.SizeRange, phb.SizeRange); Assert.AreEqual(rtnph.FreeSpace, ((RadixTreeNodesPageHeader)phb).FreeSpace); }