private DbItemReference AllocateMultiPage(DbItem item) { long bytesWritten = 0; long startPageIndex = -1; DbItemReference result = null; IPage page = null; IPage previousPage = null; while (bytesWritten < item.RawData.LongLength) { page = _pageManager.CreatePage(); if (startPageIndex == -1) { startPageIndex = page.Index; result = new DbItemReference(page.Index, 0); } var header = new MultipageItemPageHeader { StartPageIndex = startPageIndex, PreviousPageIndex = previousPage?.Index ?? -1, NextPageIndex = -1, SizeRange = SizeRange.MultiPage }; PageFormatter.InitPage(page, header); bytesWritten += PageFormatter.WriteMultipageItemBlock(page, item, bytesWritten); if (previousPage != null) { header = (MultipageItemPageHeader)PageFormatter.GetPageHeader(previousPage); header.NextPageIndex = page.Index; header.WriteToPage(previousPage); _pageManager.UpdatePage(previousPage); } previousPage = page; } if (page != null) { _pageManager.UpdatePage(page); } return(result); }
private DbItemReference AllocateSinglePage(DbItem item) { DbItemReference result; IPage page; var fsmValue = EnumHelper.FsmValueFromSizeRange(item.SizeRange); var index = _fsm.GetFreePageIndex(fsmValue); bool spaceRemains; if (index != -1) { // place object to existing page page = _pageManager.FetchPage(index); result = PageFormatter.AddFixedSizeItem(page, item, out spaceRemains); if (!spaceRemains) { _fsm.Set(index, FsmValue.Full); } } else { // allocate on a new page page = _pageManager.CreatePage(); var header = new FixedSizeItemsPageHeader { SizeRange = item.SizeRange }; PageFormatter.InitPage(page, header); result = PageFormatter.AddFixedSizeItem(page, item, out spaceRemains); _fsm.Set(result.PageIndex, spaceRemains ? fsmValue : FsmValue.Full); } _pageManager.UpdatePage(page); return(result); }
/// <summary> /// Reallocates already allocated db item with specified content and produces reference to it. /// </summary> /// <param name="reference">Reference to already allocated item</param> /// <param name="newContent">Content of item to reallocate</param> /// <returns>Reference to the reallocated item</returns> public DbItemReference Reallocate(DbItemReference reference, byte[] newContent) { var item = new DbItem(newContent); if (item.GetAllocationType(_pageManager.PageSize) == AllocationType.SinglePage) { IPage page = _pageManager.FetchPage(reference.PageIndex); if (PageFormatter.GetPageHeader(page).SizeRange == item.SizeRange) { PageFormatter.RewriteFixedSizeItem(page, reference.ItemIndex, item); _pageManager.UpdatePage(page); return(reference); } Free(reference); return(AllocateSinglePage(item)); } Free(reference); return(AllocateMultiPage(item)); }