public string DebugDump(RawDataSmallPageHeader *pageHeader) { var sb = new StringBuilder( $"Page {pageHeader->PageNumber}, {pageHeader->NumberOfEntries} entries, next allocation: {pageHeader->NextAllocation}") .AppendLine(); for (int i = sizeof(RawDataSmallPageHeader); i < pageHeader->NextAllocation;) { var oldSize = (RawDataEntrySizes *)((byte *)pageHeader + i); sb.Append($"{i} - {oldSize->AllocatedSize} / {oldSize->UsedSize} - "); if (oldSize->UsedSize > 0) { var tvr = new TableValueReader((byte *)pageHeader + i + sizeof(RawDataEntrySizes), oldSize->UsedSize); sb.Append(tvr.Count); } sb.AppendLine(); i += oldSize->AllocatedSize + sizeof(RawDataEntrySizes); } return(sb.ToString()); }
private RawDataSmallPageHeader *DefragPage(RawDataSmallPageHeader *pageHeader) { pageHeader = ModifyPage(pageHeader); if (pageHeader->NumberOfEntries == 0) { pageHeader->NextAllocation = (ushort)sizeof(RawDataSmallPageHeader); Memory.Set((byte *)pageHeader + pageHeader->NextAllocation, 0, Constants.Storage.PageSize - pageHeader->NextAllocation); return(pageHeader); } TemporaryPage tmp; using (_tx.Environment.GetTemporaryPage(_tx, out tmp)) { var maxUsedPos = pageHeader->NextAllocation; Memory.Copy(tmp.TempPagePointer, (byte *)pageHeader, Constants.Storage.PageSize); pageHeader->NextAllocation = (ushort)sizeof(RawDataSmallPageHeader); Memory.Set((byte *)pageHeader + pageHeader->NextAllocation, 0, Constants.Storage.PageSize - pageHeader->NextAllocation); pageHeader->NumberOfEntries = 0; var pos = pageHeader->NextAllocation; while (pos < maxUsedPos) { var oldSize = (RawDataEntrySizes *)(tmp.TempPagePointer + pos); if (oldSize->AllocatedSize <= 0) { VoronUnrecoverableErrorException.Raise(_tx, $"Allocated size cannot be zero or negative, but was {oldSize->AllocatedSize} in page {pageHeader->PageNumber}"); } if (oldSize->UsedSize < 0) { pos += (ushort)(oldSize->AllocatedSize + sizeof(RawDataEntrySizes)); continue; // this was freed } var prevId = (pageHeader->PageNumber) * Constants.Storage.PageSize + pos; var newId = (pageHeader->PageNumber) * Constants.Storage.PageSize + pageHeader->NextAllocation; if (prevId != newId) { OnDataMoved(prevId, newId, tmp.TempPagePointer + pos + sizeof(RawDataEntrySizes), oldSize->UsedSize); } var newSize = (RawDataEntrySizes *)(((byte *)pageHeader) + pageHeader->NextAllocation); newSize->AllocatedSize = oldSize->AllocatedSize; newSize->UsedSize = oldSize->UsedSize; pageHeader->NextAllocation += (ushort)sizeof(RawDataEntrySizes); pageHeader->NumberOfEntries++; Memory.Copy(((byte *)pageHeader) + pageHeader->NextAllocation, tmp.TempPagePointer + pos + sizeof(RawDataEntrySizes), oldSize->UsedSize); pageHeader->NextAllocation += (ushort)oldSize->AllocatedSize; pos += (ushort)(oldSize->AllocatedSize + sizeof(RawDataEntrySizes)); } } return(pageHeader); }
protected RawDataSmallPageHeader *ModifyPage(RawDataSmallPageHeader *pageHeader) { var page = _pageLocator.GetWritablePage(pageHeader->PageNumber); return((RawDataSmallPageHeader *)page.Pointer); }
protected RawDataSmallPageHeader *ModifyPage(RawDataSmallPageHeader *pageHeader) { var page = _tx.ModifyPage(pageHeader->PageNumber); return((RawDataSmallPageHeader *)page.Pointer); }
private RawDataSmallPageHeader *DefragPage(RawDataSmallPageHeader *pageHeader) { pageHeader = ModifyPage(pageHeader); if (pageHeader->NumberOfEntries == 0) { pageHeader->NextAllocation = (ushort)sizeof(RawDataSmallPageHeader); Memory.Set((byte *)pageHeader + pageHeader->NextAllocation, 0, Constants.Storage.PageSize - pageHeader->NextAllocation); return(pageHeader); } using (_llt.Environment.GetTemporaryPage(_llt, out TemporaryPage tmp)) { var maxUsedPos = pageHeader->NextAllocation; Memory.Copy(tmp.TempPagePointer, (byte *)pageHeader, Constants.Storage.PageSize); pageHeader->NextAllocation = (ushort)sizeof(RawDataSmallPageHeader); Memory.Set((byte *)pageHeader + pageHeader->NextAllocation, 0, Constants.Storage.PageSize - pageHeader->NextAllocation); pageHeader->NumberOfEntries = 0; var pos = pageHeader->NextAllocation; while (pos < maxUsedPos) { var oldSize = (RawDataEntrySizes *)(tmp.TempPagePointer + pos); if (oldSize->AllocatedSize <= 0) { VoronUnrecoverableErrorException.Raise(_llt, $"Allocated size cannot be zero or negative, but was {oldSize->AllocatedSize} in page {pageHeader->PageNumber}"); } if (oldSize->IsFreed) { pos += (ushort)(oldSize->AllocatedSize + sizeof(RawDataEntrySizes)); continue; // this was freed } var prevId = (pageHeader->PageNumber) * Constants.Storage.PageSize + pos; var newId = (pageHeader->PageNumber) * Constants.Storage.PageSize + pageHeader->NextAllocation; byte *entryPos = tmp.TempPagePointer + pos + sizeof(RawDataEntrySizes); if (prevId != newId) { var size = oldSize->UsedSize; if (oldSize->IsCompressed) { using var __ = Table.DecompressValue(_transaction, entryPos, size, out var buffer); OnDataMoved(prevId, newId, buffer.Ptr, buffer.Length); } else { OnDataMoved(prevId, newId, entryPos, oldSize->UsedSize); } } var newSize = (RawDataEntrySizes *)(((byte *)pageHeader) + pageHeader->NextAllocation); newSize->AllocatedSize = oldSize->AllocatedSize; newSize->UsedSize_Buffer = oldSize->UsedSize_Buffer; pageHeader->NextAllocation += (ushort)sizeof(RawDataEntrySizes); pageHeader->NumberOfEntries++; Memory.Copy(((byte *)pageHeader) + pageHeader->NextAllocation, entryPos, oldSize->UsedSize); pageHeader->NextAllocation += (ushort)oldSize->AllocatedSize; pos += (ushort)(oldSize->AllocatedSize + sizeof(RawDataEntrySizes)); } } return(pageHeader); }