예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        /// <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));
        }