Esempio n. 1
0
		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;
		}
Esempio n. 2
0
		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;
		}
Esempio n. 3
0
		private bool TryFindContinuousRange(Transaction tx, TreeIterator it, int num, StreamBitArray current, long currentSectionId, out long? page)
		{
			page = -1;
			var start = -1;
			var count = 0;
			for (int i = 0; i < NumberOfPagesInSection; i++)
			{
				if (current.Get(i))
				{
					if (start == -1)
						start = i;
					count++;
					if (count == num)
					{
						page = currentSectionId * NumberOfPagesInSection + start;
						break;
					}
				}
				else
				{
					start = -1;
					count = 0;
				}
			}

			if (count != num)
				return false;

			if (current.SetCount == num)
			{
				tx.FreeSpaceRoot.Delete(it.CurrentKey);
			}
			else
			{
				for (int i = 0; i < num; i++)
				{
					current.Set(i + start, false);
				}

				tx.FreeSpaceRoot.Add(it.CurrentKey, current.ToStream());
			}

			return true;
		}
Esempio n. 4
0
		private static bool TryFindSmallValueMergingTwoSections(Transaction tx, TreeIterator it, int num, StreamBitArray current, long currentSectionId, out long? result)
		{
			result = -1;
			var currentRange = current.GetEndRangeCount();
			if (currentRange == 0)
				return false;

			var nextSectionId = currentSectionId + 1;

			var nextId = new Slice(EndianBitConverter.Big.GetBytes(nextSectionId));
			var read = tx.State.FreeSpaceRoot.Read(nextId);
			if (read == null)
				return false;

			var next = new StreamBitArray(read.Reader);

			var nextRange = num - currentRange;
			if (next.HasStartRangeCount(nextRange) == false)
				return false;

			if (next.SetCount == nextRange)
			{
				tx.State.FreeSpaceRoot.Delete(nextId);
			}
			else
			{
				for (int i = 0; i < nextRange; i++)
				{
					next.Set(i, false);
				}
				tx.State.FreeSpaceRoot.Add(nextId, next.ToStream());
			}

			if (current.SetCount == currentRange)
			{
				tx.State.FreeSpaceRoot.Delete(it.CurrentKey);
			}
			else
			{
				for (int i = 0; i < currentRange; i++)
				{
					current.Set(NumberOfPagesInSection - 1 - i, false);
				}
				tx.State.FreeSpaceRoot.Add(nextId, next.ToStream());
			}


			result = currentSectionId * NumberOfPagesInSection + currentRange;
			return true;
		}