internal void Apply(MemTable memTable, Reference<ulong> seq)
		{
			foreach (var operation in _operations)
			{
				var itemType = operation.Op == Operations.Delete ? ItemType.Deletion : ItemType.Value;
				memTable.Add(seq.Value++, itemType, operation.Key, operation.Handle);
			}
		}
		public void T1()
		{
			var storageState = new StorageState("test", new StorageOptions());
			var random = new Random();
			var tables = new List<MemTable>();
			var expectedCount = 0;

			try
			{
				ulong seq = 0;
				for (var i = 0; i < 100; i++)
				{
					var table = new MemTable(storageState);
					for (var j = 0; j < 1000; j++)
					{
						var k = random.Next();
						var key = string.Format("{0:0000000000000000}", k);
						table.Add(seq++, ItemType.Value, key, null);
						expectedCount++;
					}

					tables.Add(table);
				}

				var iterators = tables.Select(table => table.NewIterator()).ToList();
				var comparator = new InternalKeyComparator(new CaseInsensitiveComparator());

				using (var iterator = new MergingIterator(comparator, iterators))
				{
					var actualCount = 0;
					iterator.SeekToFirst();
					Assert.True(iterator.IsValid);

					Slice prev = string.Empty;

					while (iterator.IsValid)
					{
						if (!prev.IsEmpty())
						{
							Assert.True(comparator.Compare(iterator.Key, prev) > 0);
						}

						prev = iterator.Key.Clone();
						iterator.Next();
						actualCount++;
					}

					Assert.Equal(expectedCount, actualCount);
				}
			}
			finally
			{
				foreach (var table in tables)
					table.Dispose();
			}

			
		}
		public void WillNotShowValueFromLaterSnapshot()
		{
			var storageState = new StorageState("test", new StorageOptions());
			using (var memtable = new MemTable(storageState))
			{
				memtable.Add(2, ItemType.Value, "test", memtable.Write(new MemoryStream(new byte[] { 1, 2, 3 })));
				Stream stream;
				Assert.False(memtable.TryGet("test", 1, out stream));
			}
		}
		public void Empty()
		{
			var storageState = new StorageState("test", new StorageOptions());
			using (var memtable = new MemTable(storageState))
			{
				Stream stream;
				Assert.False(memtable.TryGet("test", 1, out stream));
				Assert.Null(stream);
			}
		}
		public void DeletesWillHideValues()
		{
			var storageState = new StorageState("test", new StorageOptions());
			using (var memtable = new MemTable(storageState))
			{
				memtable.Add(2, ItemType.Value, "test", memtable.Write(new MemoryStream(new byte[] { 1, 2, 3 })));
				memtable.Add(3, ItemType.Deletion, "test", null);

				Stream stream;
				Assert.True(memtable.TryGet("test", 5, out stream));
				Assert.Null(stream);
			}
		}
		public StorageState(string name, StorageOptions options)
		{
			_perfCounters = new PerfCounters(name);
			_cancellationTokenSource = new CancellationTokenSource();
			CancellationToken = _cancellationTokenSource.Token;
			Options = options;
			InternalKeyComparator = new InternalKeyComparator(options.Comparator);
			DatabaseName = name;
			Lock = new AsyncLock();
			FileSystem = new FileSystem(DatabaseName);
			MemTable = new MemTable(this);
			TableCache = new TableCache(this);
			VersionSet = new VersionSet(this);
			Compactor = new BackgroundCompactor(this);
			Snapshooter = new Snapshooter(this);
		}
		public void CanAddAndGetUsingLaterSnapshot()
		{
			var storageState = new StorageState("test", new StorageOptions());
			using (var memtable = new MemTable(storageState))
			{
				memtable.Add(1, ItemType.Value, "test", memtable.Write(new MemoryStream(new byte[] { 1, 2, 3 })));
				Stream stream;
				Assert.True(memtable.TryGet("test", 2, out stream));
				using (stream)
				{
					Assert.Equal(1, stream.ReadByte());
					Assert.Equal(2, stream.ReadByte());
					Assert.Equal(3, stream.ReadByte());
				}

			}
		}
		public void Remove(MemTable memTable, Reference<ulong> seq)
		{
			foreach (var operation in _operations)
			{
				var itemType = operation.Op == Operations.Delete ? ItemType.Deletion : ItemType.Value;
				memTable.Remove(seq.Value++, itemType, operation.Key);
			}
		}
		internal void Prepare(MemTable memTable)
		{
			foreach (var operation in _operations)
			{
				operation.Handle = memTable.Write(operation.Value);
				if (DontDisposeStreamsAfterWrite)
					continue;
				operation.Value.Dispose();
			}
		}
		private static IEnumerable<RavenJObject> YieldMemTableContents(MemTable memTable, Reference<Slice> target)
		{
			using (var iterator = memTable.NewIterator())
			{
				iterator.Seek(target.Value);
				while (iterator.IsValid)
				{
					target.Value = iterator.Key;
					using (var stream = iterator.CreateValueStream())
					{
						yield return RavenJObject.Load(new BsonReader(stream));
					}
					iterator.Next();
				}
			}
		}
示例#11
0
		public void WriteLevel0Table(MemTable memTable, Version currentVersion, VersionEdit edit)
		{
			var stopwatch = Stopwatch.StartNew();
			var fileNumber = state.VersionSet.NewFileNumber();

			pendingOutputs.Add(fileNumber);

			var fileMetadata = state.BuildTable(memTable, fileNumber);

			pendingOutputs.Remove(fileNumber);

			// Note that if file_size is zero, the file has been deleted and
			// should not be added to the manifest.
			int level = 0;
			if (fileMetadata.FileSize > 0)
			{
				var minUserKey = fileMetadata.SmallestKey.UserKey;
				var maxUserKey = fileMetadata.LargestKey.UserKey;

				if (currentVersion != null)
				{
					level = currentVersion.PickLevelForMemTableOutput(minUserKey, maxUserKey);
				}

				edit.AddFile(level, fileMetadata);
			}

			state.CompactionStats[level].Add(new CompactionStats
			{
				Milliseconds = stopwatch.ElapsedMilliseconds,
				BytesRead = 0,
				BytesWritten = fileMetadata.FileSize
			});
		}
		public MemoryIterator(MemTable table, SkipList<InternalKey, UnamangedMemoryAccessor.MemoryHandle>.Iterator iterator)
		{
			_table = table;
			_iterator = iterator;
		}
		internal async Task MakeRoomForWriteAsync(bool force, AsyncLock.LockScope lockScope)
		{
			bool allowDelay = force == false;
			while (true)
			{
				using (await lockScope.LockAsync())
				{
					if (BackgroundTask.IsCanceled || BackgroundTask.IsFaulted)
					{
						BackgroundTask.Wait(); // throws
					}
					else if (allowDelay && VersionSet.GetNumberOfFilesAtLevel(0) >= Config.SlowdownWritesTrigger)
					{
						// We are getting close to hitting a hard limit on the number of
						// L0 files.  Rather than delaying a single write by several
						// seconds when we hit the hard limit, start delaying each
						// individual write by 1ms to reduce latency variance.  Also,
						// this delay hands over some CPU to the compaction thread in
						// case it is sharing the same core as the writer.
						lockScope.Exit();
						{
							await Task.Delay(TimeSpan.FromMilliseconds(1)).ConfigureAwait(false);
						}
						await lockScope.LockAsync().ConfigureAwait(false);
						allowDelay = false; // Do not delay a single write more than once
					}
					else if (force == false && MemTable.ApproximateMemoryUsage <= Options.WriteBatchSize)
					{
						// There is room in current memtable
						break;
					}
					else if (ImmutableMemTable != null)
					{
						Compactor.MaybeScheduleCompaction(lockScope);
						lockScope.Exit();

						// We have filled up the current memtable, but the previous
						// one is still being compacted, so we wait.
						await BackgroundTask.ConfigureAwait(false);
					}
					else if (VersionSet.GetNumberOfFilesAtLevel(0) >= Config.StopWritesTrigger)
					{
						Compactor.MaybeScheduleCompaction(lockScope);
						lockScope.Exit();

						// There are too many level-0 files.
						await BackgroundTask.ConfigureAwait(false);
					}
					else
					{
						// Attempt to switch to a new memtable and trigger compaction of old
						Debug.Assert(VersionSet.PrevLogNumber == 0);

						LogWriter.Dispose();

						CreateNewLog();
						ImmutableMemTable = MemTable;
						MemTable = new MemTable(this);
						force = false;
						Compactor.MaybeScheduleCompaction(lockScope);
					}
				}
			}
		}
		/// <summary>
		/// Build a Table file from the contents of *iter.  The generated file
		/// will be named according to meta->number.  On success, the rest of
		/// *meta will be filled with metadata about the generated table.
		/// If no data is present in *iter, meta->file_size will be set to
		/// zero, and no Table file will be produced.
		/// </summary>
		/// <param name="memTable"></param>
		/// <param name="fileNumber"></param>
		/// <returns></returns>
		public FileMetadata BuildTable(MemTable memTable, ulong fileNumber)
		{
			CancellationToken.ThrowIfCancellationRequested();

			TableBuilder builder = null;
			var meta = new FileMetadata
						   {
							   FileNumber = fileNumber
						   };

			var tableFileName = FileSystem.GetTableFileName(fileNumber);
			try
			{
				var iterator = memTable.NewIterator();
				iterator.SeekToFirst();

				if (Log.IsDebugEnabled)
					Log.Debug("Writing table with {0:#,#;;00} items to {1}", memTable.Count, tableFileName);

				if (iterator.IsValid)
				{
					var tableFile = FileSystem.NewWritable(tableFileName);
					builder = new TableBuilder(this, tableFile, new TemporaryFiles(FileSystem, fileNumber));

					meta.SmallestKey = new InternalKey(iterator.Key);
					while (iterator.IsValid)
					{
						CancellationToken.ThrowIfCancellationRequested();
						var key = iterator.Key;

						meta.LargestKey = new InternalKey(key);

						if (Log.IsDebugEnabled)
							Log.Debug("Writing item with key {0}", meta.LargestKey.DebugVal);

						using (var stream = iterator.CreateValueStream())
							builder.Add(key, stream);

						iterator.Next();
					}

					builder.Finish();

					meta.FileSize = builder.FileSize;
					Debug.Assert(meta.FileSize > 0);
				}
			}
			finally
			{
				if (builder != null)
					builder.Dispose();

				if (meta.FileSize == 0)
				{
					FileSystem.DeleteFile(tableFileName);
				}
			}

			return meta;
		}
		private ulong RecoverLogFile(ulong logNumber, VersionEdit edit, ulong maxSequence)
		{
			var logFileName = FileSystem.GetLogFileName(logNumber);

			Log.Info("Starting to recover from log: {0}", logFileName);

			MemTable mem = null;
			using (var logFile = FileSystem.OpenForReading(logFileName))
			{
				foreach (var item in WriteBatch.ReadFromLog(logFile, Options.BufferPool))
				{
					var lastSequence = item.WriteSequence + (ulong)item.WriteBatch.OperationCount - 1;

					if (lastSequence > maxSequence)
					{
						maxSequence = lastSequence;
					}

					if (mem == null)
					{
						mem = new MemTable(this);
					}

					item.WriteBatch.Prepare(mem);
					item.WriteBatch.Apply(mem, new Reference<ulong> { Value = item.WriteSequence });

					if (mem.ApproximateMemoryUsage > Options.WriteBatchSize)
					{
						Compactor.WriteLevel0Table(mem, null, edit);
						mem = null;
					}
				}
			}

			if (mem != null)
			{
				Compactor.WriteLevel0Table(mem, null, edit);
			}

			return maxSequence;
		}