private long AllocateFromSmallActiveSection(int size) { long id; if (ActiveDataSmallSection.TryAllocate(size, out id) == false) { InactiveSections.Add(_activeDataSmallSection.PageNumber); using (var it = ActiveCandidateSection.Iterate()) { if (it.Seek(long.MinValue)) { do { var sectionPageNumber = it.CurrentKey; _activeDataSmallSection = new ActiveRawDataSmallSection(_tx.LowLevelTransaction, sectionPageNumber); _activeDataSmallSection.DataMoved += OnDataMoved; if (_activeDataSmallSection.TryAllocate(size, out id)) { ActiveCandidateSection.Delete(sectionPageNumber); return(id); } } while (it.MoveNext()); } } var newNumberOfPages = Math.Max((ushort)(ActiveDataSmallSection.NumberOfPages * 2), ushort.MaxValue); _activeDataSmallSection = ActiveRawDataSmallSection.Create(_tx.LowLevelTransaction, Name, newNumberOfPages); _activeDataSmallSection.DataMoved += OnDataMoved; Slice pageNumber; var val = _activeDataSmallSection.PageNumber; using (Slice.External(_tx.Allocator, (byte *)&val, sizeof(long), out pageNumber)) { _tableTree.Add(TableSchema.ActiveSectionSlice, pageNumber); } var allocationResult = _activeDataSmallSection.TryAllocate(size, out id); Debug.Assert(allocationResult); } return(id); }
private long AllocateFromSmallActiveSection(int size) { long id; if (ActiveDataSmallSection.TryAllocate(size, out id) == false) { InactiveSections.Add(_activeDataSmallSection.PageNumber); using (var it = ActiveCandidateSection.Iterate()) { if (it.Seek(long.MinValue)) { do { var sectionPageNumber = it.CurrentKey; _activeDataSmallSection = new ActiveRawDataSmallSection(_tx.LowLevelTransaction, sectionPageNumber); if (_activeDataSmallSection.TryAllocate(size, out id)) { ActiveCandidateSection.Delete(sectionPageNumber); return(id); } } while (it.MoveNext()); } } _activeDataSmallSection = ActiveRawDataSmallSection.Create(_tx.LowLevelTransaction, Name); var pageNumber = Slice.From(_tx.Allocator, EndianBitConverter.Little.GetBytes(_activeDataSmallSection.PageNumber), ByteStringType.Immutable); _tableTree.Add(TableSchema.ActiveSection, pageNumber); var allocationResult = _activeDataSmallSection.TryAllocate(size, out id); Debug.Assert(allocationResult); } return(id); }
public void Delete(long id) { int size; var ptr = DirectRead(id, out size); if (ptr == null) { return; } var stats = (TableSchemaStats *)_tableTree.DirectAdd(TableSchema.StatsSlice, 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); _overflowPageCount -= numberOfPages; stats->OverflowPageCount = _overflowPageCount; 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); }