public static List <DbItem> ReadFixedSizeItems(IPage page) { short[] itemLengths = ReadFixedSizeItemLengths(page); var result = new List <DbItem>(itemLengths.Length); short maxSize = DbItem.GetMaxSize(PageHeaderBase.GetSizeRange(page)); int offset = page.Content.Length - maxSize; var content = page.Content; int cnt = itemLengths.Length; for (int i = 0; i < cnt; i++) { var il = itemLengths[i]; if (il != -1) // item is actualy present on page, read it { var itemBytes = new byte[Math.Max(il, (short)0)]; Buffer.BlockCopy(content, offset, itemBytes, 0, itemBytes.Length); result.Add(new DbItem(itemBytes)); } offset -= maxSize; } return(result); }
public static bool HasFreeSpaceForFixedSizeItem(IPage page) { PageHeaderBase header = GetPageHeader(page); if (header.SizeRange == SizeRange.NotApplicable || header.SizeRange == SizeRange.MultiPage) { return(false); } short fixedSizeItemMarkersLength = ReadFixedSizeItemMarkersLength(page); short slotSize = DbItem.GetMaxSize(header.SizeRange); int remainingSpace = page.Length - // full page length header.Length - // subtract header length fixedSizeItemMarkersLength * OnPagePointerSize - OnPagePointerSize - // subtract item length markers array and its length ReadFixedSizeItemsCount(page) * slotSize // subtract non-deleted items - OnPagePointerSize; // subtruct new item length marker needed to add a new item if (remainingSpace < slotSize) { return(false); } return(true); }
public static short[] ReadFixedSizeItemLengths(IPage page) { SizeRange range = PageHeaderBase.GetSizeRange(page); if (range == SizeRange.MultiPage || range == SizeRange.NotApplicable) { throw new PageFormatException("Page is not dedicated to fixed size items."); } short headerLength = PageHeaderBase.GetHeaderLength(page); short itemSizesLength = BitConverter.ToInt16(page.Content, headerLength); var result = new short[itemSizesLength]; int offset = headerLength + OnPagePointerSize; var content = page.Content; for (int i = 0; i < itemSizesLength; i++) { result[i] = BitConverter.ToInt16(content, offset); offset += OnPagePointerSize; } return(result); }
public static List <byte[]> ReadVariableSizeItems(IPage page) { PageType pageType = PageHeaderBase.GetPageType(page); if (pageType != PageType.RadixTree) { throw new PageFormatException("Page is not dedicated to variable size items."); } short headerLength = BitConverter.ToInt16(page.Content, OnPageOffsets.HeaderLength); var result = new List <byte[]>(); var lengthMarkers = ReadMarkers(page, headerLength); int offset = 0; foreach (var length in lengthMarkers) { offset += Math.Abs(length); var bytes = new byte[length]; Buffer.BlockCopy(page.Content, page.Content.Length - offset, bytes, 0, length); result.Add(bytes); } return(result); }
public static void RewriteFixedSizeItem(IPage page, short itemIndex, DbItem item) { if (itemIndex < 0) { throw new ArgumentOutOfRangeException(nameof(itemIndex)); } PageHeaderBase header = GetPageHeader(page); if (header.SizeRange == SizeRange.MultiPage || header.SizeRange == SizeRange.NotApplicable) { throw new PageFormatException("Page is not dedicated to fixed size items."); } if (ReadFixedSizeItemMarkersLength(page) - 1 < itemIndex) { throw new PageFormatException("Unable to rewrite fixed size item. Index is too large."); } // write the item length marker byte[] lengthBytes = BitConverter.GetBytes((short)item.RawData.Length); lengthBytes.CopyTo(page.Content, header.Length + // length of header OnPagePointerSize + // length of length marker array itemIndex * OnPagePointerSize // offset in length marker array ); Buffer.BlockCopy(item.RawData, 0, page.Content, page.Length - DbItem.GetMaxSize(header.SizeRange) * (itemIndex + 1), item.RawData.Length); }
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)); }
private static MultipageItemPageHeader GetMultipageItemPageHeader(IPage page) { PageHeaderBase result = GetPageHeader(page); if (result.SizeRange != SizeRange.MultiPage) { throw new PageFormatException("Page is not dedicated to multipage items."); } return((MultipageItemPageHeader)result); }
private static FreeSpaceMapPageHeader GetFsmPageHeader(IPage page) { PageHeaderBase result = GetPageHeader(page); if (result.SizeRange != SizeRange.MultiPage || result.PageType != PageType.FreeSpaceMap) { throw new PageFormatException("Page is not dedicated to free-space-map."); } return((FreeSpaceMapPageHeader)result); }
public static void FormatVariableSizeItemsPage(IPage page, PageHeaderBase header, List <byte[]> items) { header.WriteToPage(page); short itemsLength = items.Aggregate <byte[], short>(0, (current, item) => (short)(current + (short)(item.Length))); int remainingSpace = page.Length - // full page length header.Length - // subtract header length itemsLength - // subtract items length items.Count * OnPagePointerSize + OnPagePointerSize; // subtract markers array and its length if (remainingSpace < 0) { throw new ArgumentException("Page have no space to add specified items", nameof(items)); } var content = page.Content; int contentLength = page.Length; int cnt = items.Count; int headerLength = header.Length; short offset = 0; for (int index = 0; index < cnt; index++) { var item = items[index]; byte[] bytes; if (item != null) { bytes = BitConverter.GetBytes((short)item.Length); offset += (short)item.Length; // write the body of item Buffer.BlockCopy(item, 0, content, contentLength - offset, item.Length); } else { bytes = zeroBytesShort; } // write the length marker Buffer.BlockCopy(bytes, 0, content, headerLength + OnPagePointerSize * (index + 1), sizeof(short)); } // write the length of length marker array byte[] lengthLengthMarkers = BitConverter.GetBytes((short)cnt); lengthLengthMarkers.CopyTo(content, headerLength); WriteFreeSpace(page, (ushort)remainingSpace); }
public static void InitPage(IPage page, PageHeaderBase header) { if (header.Length > page.Length) { throw new PageFormatException("Unable to format page. Too large header."); } // fill whole page with zero Array.Clear(page.Content, 0, page.Length); header.WriteToPage(page); }
public static short ReadItemMarkersLength(IPage page) { PageType pageType = PageHeaderBase.GetPageType(page); if (pageType != PageType.RadixTree) { throw new PageFormatException("Page is not dedicated to variable size items."); } short headerLength = BitConverter.ToInt16(page.Content, OnPageOffsets.HeaderLength); return(BitConverter.ToInt16(page.Content, headerLength)); }
public static short ReadFixedSizeItemMarkersLength(IPage page) { SizeRange sc = PageHeaderBase.GetSizeRange(page); if (sc == SizeRange.MultiPage || sc == SizeRange.NotApplicable) { throw new PageFormatException("Page is not dedicated to fixed size items."); } short headerLength = BitConverter.ToInt16(page.Content, OnPageOffsets.HeaderLength); return(BitConverter.ToInt16(page.Content, headerLength)); }
private static int GetNewSlotCount(IPage page, PageHeaderBase header) { short fixedSizeItemMarkersLength = BitConverter.ToInt16(page.Content, FixedSizeItemsPageHeader.FixedSizeItemsHeaderLength); short slotSize = DbItem.GetMaxSize(header.SizeRange); int remainingSpace = page.Length - // full page length header.Length - // subtract header length fixedSizeItemMarkersLength * OnPagePointerSize - OnPagePointerSize - // subtract item length markers array and its length fixedSizeItemMarkersLength * slotSize; // subtract items return(remainingSpace / (slotSize + OnPagePointerSize)); }
public static void DeleteFixedSizeItems(IPage page) { PageHeaderBase header = GetPageHeader(page); if (header.SizeRange == SizeRange.MultiPage || header.SizeRange == SizeRange.NotApplicable) { throw new PageFormatException("Page is not dedicated to fixed size items."); } // set length of item markers to zero zeroBytesShort.CopyTo(page.Content, header.Length); // set empty slot count to zero zeroBytesShort.CopyTo(page.Content, OnPageOffsets.FixedSizeItem.EmptySlotCount); }
public static void FormatFixedSizeItemsPage(IPage page, PageHeaderBase header, DbItem[] items) { var sizeRange = header.SizeRange; if (items.Any()) { if (items.Any(item => item.SizeRange != sizeRange)) { throw new ArgumentException("Size ranges should be equal", nameof(items)); } } header.WriteToPage(page); int remainingSpace = page.Length - // full page length header.Length - // subtract header length items.Length * OnPagePointerSize - OnPagePointerSize; // subtract item length markers array and its length if (remainingSpace < 0) { throw new ArgumentException("Page have no space to add specified items", nameof(items)); } var maxSize = DbItem.GetMaxSize(sizeRange); var content = page.Content; int contentLength = page.Length; int cnt = items.Length; int headerLength = header.Length; for (int index = 0; index < cnt; index++) { var rawData = items[index].RawData; // write the length marker Buffer.BlockCopy(BitConverter.GetBytes((short)rawData.Length), 0, content, headerLength + OnPagePointerSize * (index + 1), sizeof(short)); // write the body of item Buffer.BlockCopy(rawData, 0, content, contentLength - maxSize * (index + 1), rawData.Length); } // write the length of length marker array byte[] lengthLengthMarkers = BitConverter.GetBytes((short)cnt); lengthLengthMarkers.CopyTo(content, headerLength); }
public static DbItem ReadFixedSizeItem(IPage page, short itemIndex) { short itemLength = ReadFixedSizeItemLength(page, itemIndex); if (itemLength == -1) { throw new PageFormatException("Item has been deleted."); } var itemBytes = new byte[itemLength]; short slotSize = DbItem.GetMaxSize(PageHeaderBase.GetSizeRange(page)); int offset = page.Content.Length - slotSize * (itemIndex + 1); for (int j = 0; j < itemBytes.Length; j++) { itemBytes[j] = page.Content[j + offset]; } return(new DbItem(itemBytes)); }
public static bool IsFixedSizeItemAllocated(IPage page, short itemIndex) { SizeRange sc = PageHeaderBase.GetSizeRange(page); if (sc == SizeRange.MultiPage || sc == SizeRange.NotApplicable) { throw new PageFormatException("Page is not dedicated to fixed size items."); } short headerLength = BitConverter.ToInt16(page.Content, OnPageOffsets.HeaderLength); short itemSizesLength = BitConverter.ToInt16(page.Content, headerLength); if (itemIndex >= itemSizesLength) { return(false); } int offset = headerLength + OnPagePointerSize + itemIndex * OnPagePointerSize; return(BitConverter.ToInt16(page.Content, offset) != -1); }
public static short ReadFixedSizeItemLength(IPage page, short itemIndex) { SizeRange range = PageHeaderBase.GetSizeRange(page); if (range == SizeRange.MultiPage || range == SizeRange.NotApplicable) { throw new PageFormatException("Page is not dedicated to fixed size items."); } short headerLength = BitConverter.ToInt16(page.Content, OnPageOffsets.HeaderLength); short itemSizesLength = BitConverter.ToInt16(page.Content, headerLength); if (itemIndex >= itemSizesLength) { throw new ArgumentOutOfRangeException(nameof(itemIndex)); } int offset = headerLength + OnPagePointerSize + itemIndex * OnPagePointerSize; return(BitConverter.ToInt16(page.Content, offset)); }
public static byte[] ReadVariableSizeItem(IPage page, short itemIndex) { PageType pageType = PageHeaderBase.GetPageType(page); if (pageType != PageType.RadixTree) { throw new PageFormatException("Page is not dedicated to variable size items."); } short headerLength = BitConverter.ToInt16(page.Content, OnPageOffsets.HeaderLength); var lengthMarkers = ReadMarkers(page, headerLength); if (itemIndex >= lengthMarkers.Length) { throw new PageFormatException("Wrong item index."); } int offset = 0; int length = 0; for (int i = 0; i <= itemIndex; i++) { length = lengthMarkers[i]; offset += Math.Abs(length); } if (length <= 0) { throw new PageFormatException("Item has been deleted."); } var result = new byte[length]; Buffer.BlockCopy(page.Content, page.Content.Length - offset, result, 0, length); return(result); }
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); }