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)); }
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); }
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); }
private static void WriteFreeSpace(IPage page, ushort freeSpace) { RadixTreeNodesPageHeader.WriteFreeSpace(page, freeSpace); }