Пример #1
0
        public static ushort GetFreeSpace(IPage page)
        {
            PageType pageType = PageHeaderBase.GetPageType(page);

            if (pageType != PageType.RadixTree)
            {
                throw new PageFormatException("Page is not dedicated to variable size items.");
            }

            return(RadixTreeNodesPageHeader.ReadFreeSpace(page));
        }
Пример #2
0
        public static PageHeaderBase GetPageHeader(IPage page)
        {
            PageHeaderBase ph;
            PageType       pt = PageHeaderBase.GetPageType(page);

            switch (pt)
            {
            case PageType.FreeSpaceMap:
                ph = new FreeSpaceMapPageHeader();
                ph.Read(page);
                return(ph);

            case PageType.Heading:
                ph = new HeadingPageHeader();
                ph.Read(page);
                return(ph);

            case PageType.MultipageItem:
                ph = new MultipageItemPageHeader();
                ph.Read(page);
                return(ph);

            case PageType.FixedSizeItem:
                ph = new FixedSizeItemsPageHeader();
                ph.Read(page);
                return(ph);

            case PageType.BPlusTree:
                ph = new BPlusTreeNodePageHeader();
                ph.Read(page);
                return(ph);

            case PageType.RadixTree:
                ph = new RadixTreeNodesPageHeader();
                ph.Read(page);
                return(ph);
            }
            return(null);
        }
Пример #3
0
        public static short AddVariableSizeItem(IPage page, byte[] itemContent)
        {
            ushort freeSpace  = GetFreeSpace(page);
            var    itemLength = itemContent.Length;

            if (freeSpace < itemLength)
            {
                return(-1);
            }

            short headerLength = BitConverter.ToInt16(page.Content, OnPageOffsets.HeaderLength);

            var lengthMarkers = ReadMarkers(page, headerLength);

            int offset = 0;

            for (short i = 0; i < lengthMarkers.Length; i++)
            {
                offset += Math.Abs(lengthMarkers[i]);
                if (lengthMarkers[i] <= 0)
                {
                    // we have an empty slot
                    if (itemLength == -lengthMarkers[i])
                    {
                        // simple case: a new item has exactly the same size as deleted one, rewrite it
                        RewriteVariableSizeItem(page, itemContent, headerLength, i, offset, freeSpace);
                    }
                    else
                    {
                        PlaceItemToSlot(page, headerLength, itemContent, lengthMarkers, i);
                    }

                    return(i);
                }
            }

            // here we need two extra bytes
            if (freeSpace < itemLength + OnPagePointerSize)
            {
                return(-1);
            }


            // write length of the marker array
            var markersLengthBytes = BitConverter.GetBytes((short)(lengthMarkers.Length + 1));

            markersLengthBytes.CopyTo(page.Content, headerLength);

            // write new length marker
            var newMarkerBytes = BitConverter.GetBytes((short)itemContent.Length);

            newMarkerBytes.CopyTo(page.Content, headerLength + OnPagePointerSize * (lengthMarkers.Length + 1));

            // write item itself
            Buffer.BlockCopy(itemContent, 0, page.Content, page.Content.Length - offset - itemLength, itemLength);

            // write free space
            RadixTreeNodesPageHeader.WriteFreeSpace(page, (ushort)(freeSpace - itemLength - OnPagePointerSize));

            return((short)lengthMarkers.Length);
        }
Пример #4
0
 private static void WriteFreeSpace(IPage page, ushort freeSpace)
 {
     RadixTreeNodesPageHeader.WriteFreeSpace(page, freeSpace);
 }