private long? TryFindLargeValue(Transaction tx, TreeIterator it, int num) { int numberOfNeededFullSections = num / NumberOfPagesInSection; int numberOfExtraBitsNeeded = num % NumberOfPagesInSection; int foundSections = 0; MemorySlice startSection = null; long? startSectionId = null; var sections = new List<Slice>(); do { var stream = it.CreateReaderForCurrent(); { var current = new StreamBitArray(stream); var currentSectionId = it.CurrentKey.CreateReader().ReadBigEndianInt64(); //need to find full free pages if (current.SetCount < NumberOfPagesInSection) { ResetSections(ref foundSections, sections, ref startSection, ref startSectionId); continue; } //those sections are not following each other in the memory if (startSectionId != null && currentSectionId != startSectionId + foundSections) { ResetSections(ref foundSections, sections, ref startSection, ref startSectionId); } //set the first section of the sequence if (startSection == null) { startSection = it.CurrentKey; startSectionId = currentSectionId; } sections.Add(it.CurrentKey); foundSections++; if (foundSections != numberOfNeededFullSections) continue; //we found enough full sections now we need just a bit more if (numberOfExtraBitsNeeded == 0) { foreach (var section in sections) { tx.FreeSpaceRoot.Delete(section); } return startSectionId * NumberOfPagesInSection; } var nextSectionId = currentSectionId + 1; var nextId = new Slice(EndianBitConverter.Big.GetBytes(nextSectionId)); var read = tx.FreeSpaceRoot.Read(nextId); if (read == null) { //not a following next section ResetSections(ref foundSections, sections, ref startSection, ref startSectionId); continue; } var next = new StreamBitArray(read.Reader); if (next.HasStartRangeCount(numberOfExtraBitsNeeded) == false) { //not enough start range count ResetSections(ref foundSections, sections, ref startSection, ref startSectionId); continue; } //mark selected bits to false if (next.SetCount == numberOfExtraBitsNeeded) { tx.FreeSpaceRoot.Delete(nextId); } else { for (int i = 0; i < numberOfExtraBitsNeeded; i++) { next.Set(i, false); } tx.FreeSpaceRoot.Add(nextId, next.ToStream()); } foreach (var section in sections) { tx.FreeSpaceRoot.Delete(section); } return startSectionId * NumberOfPagesInSection; } } while (it.MoveNext()); return null; }
private long? TryFindSmallValue(Transaction tx, TreeIterator it, int num) { do { var stream = it.CreateReaderForCurrent(); { var current = new StreamBitArray(stream); var currentSectionId = it.CurrentKey.CreateReader().ReadBigEndianInt64(); long? page; if (current.SetCount < num) { if (TryFindSmallValueMergingTwoSections(tx, it.CurrentKey, num, current, currentSectionId, out page)) return page; continue; } if (TryFindContinuousRange(tx, it, num, current, currentSectionId, out page)) return page; //could not find a continuous so trying to merge if (TryFindSmallValueMergingTwoSections(tx, it.CurrentKey, num, current, currentSectionId, out page)) return page; } } while (it.MoveNext()); return null; }