public void ShouldReturnValidIdsOfEntriesInSectionThatAreReadable() { long pageNumber; using (var tx = Env.WriteTransaction()) { var section = ActiveRawDataSmallSection.Create(tx.LowLevelTransaction, "test", (byte)TableType.None); pageNumber = section.PageNumber; tx.Commit(); } long idWhichIsGoingToBeDeleted1; long idWhichIsGoingToBeDeleted2; long existingId; using (var tx = Env.WriteTransaction()) { var section = new ActiveRawDataSmallSection(tx.LowLevelTransaction, pageNumber); Assert.True(section.TryAllocate(2000, out idWhichIsGoingToBeDeleted1)); WriteValue(section, idWhichIsGoingToBeDeleted1, 1.ToString("0000000000000")); Assert.True(section.TryAllocate(2000, out idWhichIsGoingToBeDeleted2)); WriteValue(section, idWhichIsGoingToBeDeleted2, 2.ToString("0000000000000")); Assert.True(section.TryAllocate(2000, out existingId)); WriteValue(section, existingId, 3.ToString("0000000000000")); tx.Commit(); } using (var tx = Env.WriteTransaction()) { var section = new ActiveRawDataSmallSection(tx.LowLevelTransaction, pageNumber); section.Free(idWhichIsGoingToBeDeleted1); section.Free(idWhichIsGoingToBeDeleted2); tx.Commit(); } using (var tx = Env.WriteTransaction()) { var section = new ActiveRawDataSmallSection(tx.LowLevelTransaction, pageNumber); var ids = section.GetAllIdsInSectionContaining(existingId); Assert.Equal(1, ids.Count); Assert.Equal(existingId, ids[0]); AssertValueMatches(section, existingId, 3.ToString("0000000000000")); } }
public void CanAllocateEnoughToFillEntireSection() { long pageNumber; using (var tx = Env.WriteTransaction()) { var section = ActiveRawDataSmallSection.Create(tx.LowLevelTransaction, "test", (byte)TableType.None); pageNumber = section.PageNumber; tx.Commit(); } using (var tx = Env.WriteTransaction()) { var section = new ActiveRawDataSmallSection(tx.LowLevelTransaction, pageNumber); section.DataMoved += (previousId, newId, data, size) => { }; int allocationSize = 1020; long id; var list = new List <long>(); while (section.TryAllocate(allocationSize, out id)) { list.Add(id); } Assert.False(section.TryAllocate(allocationSize, out id)); var idToFree = list[list.Count / 2]; section.Free(idToFree); Assert.True(section.TryAllocate(allocationSize, out id)); } }
public void WhatShouldWeDoHere() { long pageNumber; using (var tx = Env.WriteTransaction()) { var section = ActiveRawDataSmallSection.Create(tx.LowLevelTransaction, "test", (byte)TableType.None); pageNumber = section.PageNumber; tx.Commit(); } using (var tx = Env.WriteTransaction()) { var section = new ActiveRawDataSmallSection(tx.LowLevelTransaction, pageNumber); Assert.Throws <InvalidOperationException>(() => section.Free(0)); } }
public void Delete(long id) { int size; var ptr = DirectRead(id, out size); if (ptr == null) { return; } var stats = (TableSchemaStats *)_tableTree.DirectAdd(TableSchema.Stats, sizeof(TableSchemaStats)); NumberOfEntries--; stats->NumberOfEntries = NumberOfEntries; DeleteValueFromIndex(id, new TableValueReader(ptr, size)); var largeValue = (id % _pageSize) == 0; if (largeValue) { var page = _tx.LowLevelTransaction.GetPage(id / _pageSize); var numberOfPages = _tx.LowLevelTransaction.DataPager.GetNumberOfOverflowPages(page.OverflowSize); for (int i = 0; i < numberOfPages; i++) { _tx.LowLevelTransaction.FreePage(page.PageNumber + i); } return; } var density = ActiveDataSmallSection.Free(id); if (ActiveDataSmallSection.Contains(id) || density > 0.5) { return; } var sectionPageNumber = ActiveDataSmallSection.GetSectionPageNumber(id); if (density > 0.15) { ActiveCandidateSection.Add(sectionPageNumber); return; } // move all the data to the current active section (maybe creating a new one // if this is busy) // if this is in the active candidate list, remove it so it cannot be reused if the current // active is full and need a new one ActiveCandidateSection.Delete(sectionPageNumber); var idsInSection = ActiveDataSmallSection.GetAllIdsInSectionContaining(id); foreach (var idToMove in idsInSection) { int itemSize; var pos = ActiveDataSmallSection.DirectRead(idToMove, out itemSize); var newId = AllocateFromSmallActiveSection(itemSize); OnDataMoved(idToMove, newId, pos, itemSize); byte *writePos; if (ActiveDataSmallSection.TryWriteDirect(newId, itemSize, out writePos) == false) { throw new InvalidDataException($"Cannot write to newly allocated size in {Name} during delete"); } Memory.Copy(writePos, pos, itemSize); } ActiveDataSmallSection.DeleteSection(sectionPageNumber); }