public long Update(long id, TableValueBuilder builder) { int size = builder.Size; // first, try to fit in place, either in small or large sections var prevIsSmall = id % _pageSize != 0; if (size < ActiveDataSmallSection.MaxItemSize) { byte *pos; if (prevIsSmall && ActiveDataSmallSection.TryWriteDirect(id, size, out pos)) { int oldDataSize; var oldData = ActiveDataSmallSection.DirectRead(id, out oldDataSize); DeleteValueFromIndex(id, new TableValueReader(oldData, oldDataSize)); // MemoryCopy into final position. builder.CopyTo(pos); InsertIndexValuesFor(id, new TableValueReader(pos, size)); return(id); } } else if (prevIsSmall == false) { var pageNumber = id / _pageSize; var page = _tx.LowLevelTransaction.GetPage(pageNumber); var existingNumberOfPages = _tx.LowLevelTransaction.DataPager.GetNumberOfOverflowPages(page.OverflowSize); var newNumberOfPages = _tx.LowLevelTransaction.DataPager.GetNumberOfOverflowPages(size); if (existingNumberOfPages == newNumberOfPages) { page.OverflowSize = size; var pos = page.Pointer + sizeof(PageHeader); DeleteValueFromIndex(id, new TableValueReader(pos, size)); // MemoryCopy into final position. builder.CopyTo(pos); InsertIndexValuesFor(id, new TableValueReader(pos, size)); return(id); } } // can't fit in place, will just delete & insert instead Delete(id); return(Insert(builder)); }
private static void AssertValueMatches(ActiveRawDataSmallSection section, long id, string expected) { int size; var p = section.DirectRead(id, out size); var buffer = new byte[size]; fixed(byte *bp = buffer) { Memory.Copy(bp, p, size); } var actual = Encoding.UTF8.GetString(buffer, 0, size); Assert.Equal(expected, actual); }