void TestRecoveryOnExisting(BPlusTree <Guid, TestInfo> .OptionsV2 options, int count, int added) { BPlusTree <Guid, TestInfo> tree = null; var temp = TempFile.Attach(options.FileName); Dictionary <Guid, TestInfo> dataFirst, data = new Dictionary <Guid, TestInfo>(); try { temp.Delete(); Assert.IsNotNull(options.TransactionLog); using (tree = new BPlusTree <Guid, TestInfo>(options)) { Insert(tree, data, 1, 100, TimeSpan.MaxValue); TestInfo.AssertEquals(data, tree); Assert.IsFalse(temp.Exists); } tree = null; Assert.IsTrue(File.Exists(options.TransactionLogFileName)); // All data commits to output file Assert.IsTrue(temp.Exists); TestInfo.AssertEquals(data, BPlusTree <Guid, TestInfo> .EnumerateFile(options)); dataFirst = new Dictionary <Guid, TestInfo>(data); DateTime modified = temp.Info.LastWriteTimeUtc; tree = new BPlusTree <Guid, TestInfo>(options); using (var log = options.TransactionLog) { using ((IDisposable) new PropertyValue(tree, "_storage").Value) Insert(tree, data, Environment.ProcessorCount, count, TimeSpan.MaxValue); //Add extra data... AppendToLog(log, TestInfo.Create(added, data)); } tree = null; //Still only contains original data Assert.AreEqual(modified, temp.Info.LastWriteTimeUtc); TestInfo.AssertEquals(dataFirst, BPlusTree <Guid, TestInfo> .EnumerateFile(options)); //Now recover... using (var recovered = new BPlusTree <Guid, TestInfo>(options)) { TestInfo.AssertEquals(data, recovered); } } finally { temp.Dispose(); if (tree != null) { tree.Dispose(); } } }
public void TestWriteToTemporaryCopy() { Dictionary <Guid, TestInfo> first, data = new Dictionary <Guid, TestInfo>(); using (TempFile temp = new TempFile()) { temp.Delete(); var options = GetOptions(temp); options.TransactionLogFileName = Path.ChangeExtension(options.FileName, ".tlog"); using (var tree = new BPlusTree <Guid, TestInfo>(options)) { Insert(tree, data, 1, 100, TimeSpan.MaxValue); TestInfo.AssertEquals(data, tree); Assert.IsFalse(temp.Exists); } // All data commits to output file Assert.IsTrue(temp.Exists); TestInfo.AssertEquals(data, BPlusTree <Guid, TestInfo> .EnumerateFile(options)); first = new Dictionary <Guid, TestInfo>(data); using (var tree = new BPlusTree <Guid, TestInfo>(options)) { Insert(tree, data, 1, 100, TimeSpan.MaxValue); //We are writing to a backup, the original file still contains 100 items: TestInfo.AssertEquals(first, BPlusTree <Guid, TestInfo> .EnumerateFile(options)); //Commit the changes and the original file will now contain our changes: tree.CommitChanges(); TestInfo.AssertEquals(data, BPlusTree <Guid, TestInfo> .EnumerateFile(options)); //Add a few more records... Insert(tree, data, 1, 100, TimeSpan.MaxValue); } //Dispose of the tree will commit changes... TestInfo.AssertEquals(data, BPlusTree <Guid, TestInfo> .EnumerateFile(options)); } }
public void TestRestoreLargeLog() { using (TempFile savelog = new TempFile()) using (TempFile temp = new TempFile()) { var options = GetOptions(temp); options.FileBlockSize = 512; options.StoragePerformance = StoragePerformance.Fastest; options.CalcBTreeOrder(Marshal.SizeOf(typeof(Guid)), Marshal.SizeOf(typeof(TestInfo))); options.TransactionLog = new TransactionLog <Guid, TestInfo>( new TransactionLogOptions <Guid, TestInfo>( options.TransactionLogFileName, options.KeySerializer, options.ValueSerializer ) ); //Now recover... Dictionary <Guid, TestInfo> first = new Dictionary <Guid, TestInfo>(); Dictionary <Guid, TestInfo> sample; using (var tree = new BPlusTree <Guid, TestInfo>(options)) { tree.EnableCount(); Insert(tree, first, 1, 100, TimeSpan.FromMinutes(1)); tree.Commit(); Assert.AreEqual(100, tree.Count); sample = new Dictionary <Guid, TestInfo>(first); Insert(tree, sample, 7, 5000, TimeSpan.FromMinutes(1)); Assert.AreEqual(35100, tree.Count); for (int i = 0; i < 1; i++) { foreach (var rec in tree) { var value = rec.Value; value.UpdateCount++; value.ReadCount++; tree[rec.Key] = value; } } File.Copy(options.TransactionLog.FileName, savelog.TempPath, true); tree.Rollback(); TestInfo.AssertEquals(first, tree); } //file still has initial committed data TestInfo.AssertEquals(first, BPlusTree <Guid, TestInfo> .EnumerateFile(options)); //restore the log and verify all data. File.Copy(savelog.TempPath, options.TransactionLog.FileName, true); using (var tree = new BPlusTree <Guid, TestInfo>(options)) { TestInfo.AssertEquals(sample, tree); } //file still has initial committed data TestInfo.AssertEquals(sample, BPlusTree <Guid, TestInfo> .EnumerateFile(options)); } }
public void TestSyncFromLogging() { using (var tempFile = new TempFile()) using (var logfile = new TempFile()) using (var tempCopy = new TempFile()) { var options = new BPlusTree <int, string> .OptionsV2(new PrimitiveSerializer(), new PrimitiveSerializer()) { CreateFile = CreatePolicy.Always, FileName = tempFile.TempPath, TransactionLogFileName = logfile.TempPath, } .CalcBTreeOrder(4, 10); var readcopy = options.Clone(); readcopy.FileName = tempCopy.TempPath; readcopy.StoragePerformance = StoragePerformance.Fastest; using (var tree = new BPlusTree <int, string>(options)) using (var copy = new BPlusTree <int, string>(readcopy)) using (var tlog = new TransactionLog <int, string>( new TransactionLogOptions <int, string>(logfile.TempPath, PrimitiveSerializer.Int32, PrimitiveSerializer.String) { ReadOnly = true })) { tree.Add(0, "0"); tree.Commit(); long logpos = 0; copy.EnableCount(); //start by copying the data from tree's file into the copy instance: copy.BulkInsert( BPlusTree <int, string> .EnumerateFile(options), new BulkInsertOptions { InputIsSorted = true, CommitOnCompletion = false, ReplaceContents = true } ); Assert.AreEqual(1, copy.Count); Assert.AreEqual("0", copy[0]); tlog.ReplayLog(copy, ref logpos); Assert.AreEqual(1, copy.Count); //insert some data... tree.AddRange(MakeValues(1, 99)); tlog.ReplayLog(copy, ref logpos); Assert.AreEqual(100, copy.Count); //insert some data... for (int i = 0; i < 100; i++) { tree.Remove(i); } tlog.ReplayLog(copy, ref logpos); Assert.AreEqual(0, copy.Count); tree.AddRange(MakeValues(1000, 1000)); tlog.ReplayLog(copy, ref logpos); Assert.AreEqual(1000, copy.Count); } } }