public void ShouldEncodeAndDecode() { var versionEdit = new VersionEdit(); versionEdit.SetComparatorName("testComparator"); versionEdit.SetLastSequence(10); versionEdit.SetLogNumber(2); versionEdit.SetNextFile(3); versionEdit.SetPrevLogNumber(1); versionEdit.SetLastSequence(1); versionEdit.AddFile(0, new FileMetadata() { FileNumber = 0, FileSize = 128, LargestKey = new InternalKey("begin", Format.MaxSequenceNumber, ItemType.Value), SmallestKey = new InternalKey("end", Format.MaxSequenceNumber, ItemType.Value), }); versionEdit.AddFile(1, new FileMetadata() { FileNumber = 1, FileSize = 128, LargestKey = new InternalKey("begin", Format.MaxSequenceNumber, ItemType.Value), SmallestKey = new InternalKey("end", Format.MaxSequenceNumber, ItemType.Value), }); versionEdit.DeleteFile(0, 3); versionEdit.DeleteFile(1, 4); versionEdit.SetCompactionPointer(0, new InternalKey("begin", Format.MaxSequenceNumber, ItemType.Value)); versionEdit.SetCompactionPointer(1, new InternalKey("end", Format.MaxSequenceNumber, ItemType.Value)); var memoryStream = new MemoryStream(); var logWriter = new LogWriter(new InMemoryFileSystem("test"),memoryStream, new BufferPool()); versionEdit.EncodeTo(logWriter); memoryStream.Position = 0; var afterDecode = VersionEdit.DecodeFrom(new LogRecordStream(memoryStream, true, new BufferPool())); Assert.Equal(versionEdit.Comparator, afterDecode.Comparator); Assert.Equal(versionEdit.LogNumber, afterDecode.LogNumber); Assert.Equal(versionEdit.NextFileNumber, afterDecode.NextFileNumber); Assert.Equal(versionEdit.PrevLogNumber, afterDecode.PrevLogNumber); Assert.Equal(versionEdit.LogNumber, afterDecode.LogNumber); Assert.Equal(versionEdit.PrevLogNumber, afterDecode.PrevLogNumber); Assert.Equal(versionEdit.LastSequence, afterDecode.LastSequence); Assert.Equal(versionEdit.NewFiles[0][0].FileNumber, afterDecode.NewFiles[0][0].FileNumber); Assert.Equal(versionEdit.NewFiles[0][0].FileSize, afterDecode.NewFiles[0][0].FileSize); Assert.Equal(versionEdit.NewFiles[0][0].LargestKey, afterDecode.NewFiles[0][0].LargestKey); Assert.Equal(versionEdit.NewFiles[0][0].SmallestKey, afterDecode.NewFiles[0][0].SmallestKey); Assert.Equal(versionEdit.NewFiles[1][0].FileNumber, afterDecode.NewFiles[1][0].FileNumber); Assert.Equal(versionEdit.NewFiles[1][0].FileSize, afterDecode.NewFiles[1][0].FileSize); Assert.Equal(versionEdit.NewFiles[1][0].LargestKey, afterDecode.NewFiles[1][0].LargestKey); Assert.Equal(versionEdit.NewFiles[1][0].SmallestKey, afterDecode.NewFiles[1][0].SmallestKey); Assert.Equal(versionEdit.DeletedFiles[0][0], afterDecode.DeletedFiles[0][0]); Assert.Equal(versionEdit.DeletedFiles[1][0], afterDecode.DeletedFiles[1][0]); Assert.Equal(versionEdit.CompactionPointers[0][0], afterDecode.CompactionPointers[0][0]); Assert.Equal(versionEdit.CompactionPointers[1][0], afterDecode.CompactionPointers[1][0]); }
public static VersionEdit DecodeFrom(Stream stream) { var result = new VersionEdit(); while (true) { Tag tag; try { tag = (Tag)stream.Read7BitEncodedInt(); } catch (EndOfStreamException) { break; } int level; switch (tag) { case Tag.Comparator: var slice = stream.ReadLengthPrefixedSlice(); result.SetComparatorName(slice); break; case Tag.LogNumber: result.SetLogNumber((ulong)stream.Read7BitEncodedLong()); break; case Tag.PrevLogNumber: result.SetPrevLogNumber((ulong)stream.Read7BitEncodedLong()); break; case Tag.NextFileNumber: result.SetNextFile((ulong)stream.Read7BitEncodedLong()); break; case Tag.LastSequence: result.SetLastSequence((ulong)stream.Read7BitEncodedLong()); break; case Tag.CompactPointer: level = stream.Read7BitEncodedInt(); var compactionPointer = stream.ReadLengthPrefixedInternalKey(); result.SetCompactionPointer(level, compactionPointer); break; case Tag.DeletedFile: level = stream.Read7BitEncodedInt(); var fileNumber = (ulong)stream.Read7BitEncodedLong(); result.DeleteFile(level, fileNumber); break; case Tag.NewFile: level = stream.Read7BitEncodedInt(); var fileMetadata = new FileMetadata { FileNumber = (ulong)stream.Read7BitEncodedLong(), FileSize = stream.Read7BitEncodedLong(), SmallestKey = stream.ReadLengthPrefixedInternalKey(), LargestKey = stream.ReadLengthPrefixedInternalKey() }; result.AddFile(level, fileMetadata); break; } } return result; }
public async Task LogAndApplyAsync(VersionEdit edit, AsyncLock.LockScope locker) { string newManifestFile = null; try { Version version; using (await locker.LockAsync()) { if (!edit.LogNumber.HasValue) edit.SetLogNumber(VersionSet.LogNumber); else if (edit.LogNumber < VersionSet.LogNumber || edit.LogNumber >= VersionSet.NextFileNumber) throw new InvalidOperationException("LogNumber"); if (!edit.PrevLogNumber.HasValue) edit.SetPrevLogNumber(VersionSet.PrevLogNumber); edit.SetNextFile(VersionSet.NextFileNumber); edit.SetLastSequence(VersionSet.LastSequence); version = new Version(this, VersionSet); var builder = new Builder(this, VersionSet, VersionSet.Current); builder.Apply(edit); builder.SaveTo(version); Version.Finalize(version); // Initialize new descriptor log file if necessary by creating // a temporary file that contains a snapshot of the current version. if (DescriptorLogWriter == null) { // No reason to unlock *mu here since we only hit this path in the // first call to LogAndApply (when opening the database). newManifestFile = FileSystem.DescriptorFileName(VersionSet.ManifestFileNumber); edit.SetNextFile(VersionSet.NextFileNumber); var descriptorFile = FileSystem.NewWritable(newManifestFile); DescriptorLogWriter = new LogWriter(FileSystem, descriptorFile, Options.BufferPool); Snapshooter.WriteSnapshot(DescriptorLogWriter, VersionSet); } } // Write new record to MANIFEST log edit.EncodeTo(DescriptorLogWriter); // If we just created a new descriptor file, install it by writing a // new CURRENT file that points to it. if (!string.IsNullOrEmpty(newManifestFile)) { SetCurrentFile(VersionSet.ManifestFileNumber); // No need to double-check MANIFEST in case of error since it // will be discarded below. } using (await locker.LockAsync()) { // Install the new version VersionSet.AppendVersion(version); VersionSet.SetLogNumber(edit.LogNumber.Value); VersionSet.SetPrevLogNumber(edit.PrevLogNumber.Value); } } catch (Exception) { if (!string.IsNullOrEmpty(newManifestFile)) { if (DescriptorLogWriter != null) { DescriptorLogWriter.Dispose(); DescriptorLogWriter = null; } FileSystem.DeleteFile(newManifestFile); } throw; } }