public void VerifyCommitAsTransaction() { using (TempFile temp1 = new TempFile()) using (TempFile temp2 = new TempFile()) { var options = new TransactedCompoundFile.Options(temp1.TempPath) { BlockSize = 512 }; const int count = 4; byte[] sample1 = new byte[options.MaxWriteSize / 3]; byte[] sample2 = (byte[])sample1.Clone(); new Random().NextBytes(sample1); new Random().NextBytes(sample2); using (TransactedCompoundFile file = new TransactedCompoundFile(options)) { for (uint h = 1u; h < count; h++) { Assert.AreEqual(h, file.Create()); } for (uint h = 1u; h < count; h++) { file.Write(h, sample1, 0, sample1.Length); } file.Commit();//persist. for (uint h = 1u; h < count; h++) { file.Write(h, sample2, 0, sample2.Length); } file.Commit(x => temp1.CopyTo(temp2.TempPath, true), 0); } options = new TransactedCompoundFile.Options(temp2.TempPath) { BlockSize = 512, CommitOnDispose = false }; //Verify primary has sample2 data options.LoadingRule = TransactedCompoundFile.LoadingRule.Primary; using (TransactedCompoundFile file = new TransactedCompoundFile(options)) { for (uint h = 1u; h < count; h++) { CompareBytes(sample2, 0, sample2.Length, IOStream.ReadAllBytes(file.Read(h))); } } //Verify secondary has sample1 data options.LoadingRule = TransactedCompoundFile.LoadingRule.Secondary; using (TransactedCompoundFile file = new TransactedCompoundFile(options)) { for (uint h = 1u; h < count; h++) { CompareBytes(sample1, 0, sample1.Length, IOStream.ReadAllBytes(file.Read(h))); } } } }
public void TestCommit() { using (TempFile temp = new TempFile()) using (TempFile temp2 = new TempFile()) { byte[] sample = new byte[1024]; new Random().NextBytes(sample); List <uint> handles = new List <uint>(); using (TransactedCompoundFile file = new TransactedCompoundFile( new TransactedCompoundFile.Options(temp.TempPath) { FileOptions = FileOptions.WriteThrough } )) { for (int i = 0; i < 1000; i++) { var hid = file.Create(); handles.Add(hid); file.Write(hid, sample, i, sample.Length - i); } file.Commit(); File.Copy(temp.TempPath, temp2.TempPath, true); } using (TransactedCompoundFile file = new TransactedCompoundFile(temp2.TempPath)) { for (int i = 0; i < 1000; i++) { CompareBytes(sample, i, sample.Length - i, IOStream.ReadAllBytes(file.Read(handles[i]))); } } } }
public void TestRevertWithChanges() { using (TempFile temp = new TempFile()) { byte[] sample = new byte[1024]; new Random().NextBytes(sample); List <uint> handles = new List <uint>(); using (TransactedCompoundFile file = new TransactedCompoundFile(temp.TempPath)) { for (int i = 0; i < 1000; i++) { var hid = file.Create(); handles.Add(hid); file.Write(hid, sample, i, sample.Length - i); CompareBytes(sample, i, sample.Length - i, IOStream.ReadAllBytes(file.Read(hid))); } file.Commit(); } using (TransactedCompoundFile file = new TransactedCompoundFile(temp.TempPath)) { byte[] dummy = new byte[1024]; for (int i = 0; i < 1000; i++) { file.Write(handles[i], dummy, 0, dummy.Length); file.Delete(handles[i]); } file.Rollback(); for (int i = 0; i < 1000; i++) { CompareBytes(sample, i, sample.Length - i, IOStream.ReadAllBytes(file.Read(handles[i]))); } } } }
public void TestClear() { using (TempFile temp = new TempFile()) { byte[] sample = new byte[1024]; new Random().NextBytes(sample); List <uint> handles = new List <uint>(); using (TransactedCompoundFile file = new TransactedCompoundFile(temp.TempPath)) { for (int i = 0; i < 100; i++) { var hid = file.Create(); handles.Add(hid); file.Write(hid, sample, i, sample.Length - i); CompareBytes(sample, i, sample.Length - i, IOStream.ReadAllBytes(file.Read(hid))); file.Commit(); } file.Clear(); for (int i = 0; i < 100; i++) { try { IOStream.ReadAllBytes(file.Read(handles[i])); Assert.Fail(); } catch (ArgumentOutOfRangeException) { } } } } }
public void VerifyLoadRulesWithCorruptSecondary() { using (TempFile temp = new TempFile()) { var options = new TransactedCompoundFile.Options(temp.TempPath) { BlockSize = 512 }; const int count = 4; byte[] sample = new byte[options.MaxWriteSize / 3]; new Random().NextBytes(sample); using (TransactedCompoundFile file = new TransactedCompoundFile(options)) { for (uint h = 1u; h < count; h++) { Assert.AreEqual(h, file.Create()); } for (uint h = 1u; h < count; h++) { file.Write(h, sample, 0, sample.Length); } file.Commit(); } //Corrupts the secondary storage: using (Stream f = temp.Open()) { f.Seek(-100, SeekOrigin.End); f.Write(sample, 0, 100); } try { options.LoadingRule = TransactedCompoundFile.LoadingRule.Secondary; new TransactedCompoundFile(options).Dispose(); Assert.Fail("Should not load"); } catch (InvalidDataException) { } options.LoadingRule = TransactedCompoundFile.LoadingRule.Primary; using (TransactedCompoundFile file = new TransactedCompoundFile(options)) { for (uint h = 1u; h < count; h++) { CompareBytes(sample, 0, sample.Length, IOStream.ReadAllBytes(file.Read(h))); } //Commit fixes corruption file.Commit(); } options.LoadingRule = TransactedCompoundFile.LoadingRule.Secondary; new TransactedCompoundFile(options).Dispose(); } }
/// <summary> /// Opens an existing BPlusTree file at the path specified, for a new file use CreateNew() /// </summary> public BTreeFileStoreV2(TransactedCompoundFile.Options options) { _options = options; _file = new TransactedCompoundFile(options); _rootId = new FileId(TransactedCompoundFile.FirstIdentity); if (options.CreateNew) { CreateRoot(_file); } }
static void ExersizeFile(ManualResetEvent stop, TransactedCompoundFile file) { const int LIMIT = 512 * 512 / 4 - 512 * 3; Random r = new Random(); Dictionary <uint, byte[]> state = new Dictionary <uint, byte[]>(); while (true) { while (state.Count < 1000) { uint h = file.Create(); byte[] bytes = new byte[r.Next(5) == 0 ? r.Next(512) : r.Next(LIMIT)]; r.NextBytes(bytes); file.Write(h, bytes, 0, bytes.Length); state.Add(h, bytes); if (stop.WaitOne(0, false)) { return; } } foreach (var kv in state) { Assert.AreEqual(0, BinaryComparer.Compare(kv.Value, IOStream.ReadAllBytes(file.Read(kv.Key)))); if (stop.WaitOne(0, false)) { return; } } List <KeyValuePair <uint, byte[]> > capture = new List <KeyValuePair <uint, byte[]> >(state); for (int i = 0; i < capture.Count; i += r.Next(4)) { uint h = capture[i].Key; byte[] bytes = new byte[r.Next(512)]; r.NextBytes(bytes); file.Write(h, bytes, 0, bytes.Length); state[h] = bytes; Assert.AreEqual(0, BinaryComparer.Compare(bytes, IOStream.ReadAllBytes(file.Read(h)))); if (stop.WaitOne(0, false)) { return; } } for (int i = 0; i < capture.Count; i += 1 + r.Next(4)) { uint h = capture[i].Key; file.Delete(h); state.Remove(h); if (stop.WaitOne(0, false)) { return; } } } }
private static void CreateRoot(TransactedCompoundFile file) { uint rootId; rootId = file.Create(); if (rootId != TransactedCompoundFile.FirstIdentity) { throw new InvalidNodeHandleException(); } file.Write(rootId, new byte[0], 0, 0); file.Commit(); }
public void RandomTest() { Dictionary <uint, byte[]> store = new Dictionary <uint, byte[]>(); using (TempFile temp = new TempFile()) { uint id; byte[] bytes; using (TransactedCompoundFile test = new TransactedCompoundFile(new TransactedCompoundFile.Options(temp.TempPath) { BlockSize = 512, CreateNew = true })) { for (int i = 0; i < 10000; i++) { switch (i < 1000 ? 0 : rand.Next(3)) { case 0: { id = test.Create(); bytes = RandomBytes(rand.Next(1000)); store.Add(id, bytes); test.Write(id, bytes, 0, bytes.Length); break; } case 1: { id = RandomPick(store.Keys); bytes = store[id]; CompareBytes(bytes, 0, bytes.Length, IOStream.ReadAllBytes(test.Read(id))); break; } case 2: { id = RandomPick(store.Keys); Assert.IsTrue(store.Remove(id)); test.Delete(id); break; } } } foreach (var kv in store) { CompareBytes(kv.Value, 0, kv.Value.Length, IOStream.ReadAllBytes(test.Read(kv.Key))); } } } }
public void TestExceedWriteMax() { using (TempFile temp = new TempFile()) { var options = new TransactedCompoundFile.Options(temp.TempPath) { BlockSize = 512 }; byte[] sample = new byte[options.MaxWriteSize + 1]; new Random().NextBytes(sample); using (TransactedCompoundFile file = new TransactedCompoundFile(options)) { file.Write(file.Create(), sample, 0, sample.Length); } } }
public void TestLargeWrite() { using (TempFile temp = new TempFile()) { var options = new TransactedCompoundFile.Options(temp.TempPath) { BlockSize = 512 }; byte[] sample = new byte[options.MaxWriteSize]; new Random().NextBytes(sample); List <uint> handles = new List <uint>(); using (TransactedCompoundFile file = new TransactedCompoundFile(options)) { for (int i = 0; i < 2; i++) { var hid = file.Create(); handles.Add(hid); file.Write(hid, sample, i, sample.Length - i); CompareBytes(sample, i, sample.Length - i, IOStream.ReadAllBytes(file.Read(handles[i]))); } file.Commit(); } long size = temp.Info.Length; using (TransactedCompoundFile file = new TransactedCompoundFile(options)) { for (int i = 0; i < 2; i++) { CompareBytes(sample, i, sample.Length - i, IOStream.ReadAllBytes(file.Read(handles[i]))); file.Delete(handles[i]); } file.Commit(); Assert.AreEqual(size, temp.Info.Length); for (int i = 0; i < 252; i++) { var hid = file.Create(); handles.Add(hid); file.Write(hid, sample, i, 300); } file.Commit(); Assert.AreEqual(size, temp.Info.Length); file.Create(); Assert.AreNotEqual(size, temp.Info.Length); } } }
public void SimpleTest() { uint handle; byte[] bytes = RandomBytes(2140); using (TempFile temp = new TempFile()) { using (TransactedCompoundFile test = new TransactedCompoundFile(new TransactedCompoundFile.Options(temp.TempPath) { BlockSize = 512, CreateNew = true })) { Assert.AreEqual(TransactedCompoundFile.FirstIdentity, test.Create()); test.Write(TransactedCompoundFile.FirstIdentity, Encoding.UTF8.GetBytes("Roger was here."), 0, 15); Assert.AreEqual("Roger was here.", Encoding.UTF8.GetString(IOStream.ReadAllBytes(test.Read(TransactedCompoundFile.FirstIdentity)))); for (int i = 0; i < 10; i++) { var id = test.Create(); test.Write(id, bytes, i, 300); if (i % 2 == 0) { test.Delete(id); } } handle = test.Create(); test.Write(handle, bytes, 1000, bytes.Length - 1000); CompareBytes(bytes, 1000, bytes.Length - 1000, IOStream.ReadAllBytes(test.Read(handle))); test.Write(handle, bytes, 0, bytes.Length); CompareBytes(bytes, 0, bytes.Length, IOStream.ReadAllBytes(test.Read(handle))); test.Commit(); } using (TransactedCompoundFile test = new TransactedCompoundFile(new TransactedCompoundFile.Options(temp.TempPath) { BlockSize = 512, CreateNew = false })) { Assert.AreEqual("Roger was here.", Encoding.UTF8.GetString(IOStream.ReadAllBytes(test.Read(TransactedCompoundFile.FirstIdentity)))); CompareBytes(bytes, 0, bytes.Length, IOStream.ReadAllBytes(test.Read(handle))); } } }
void TestWriteWithOptions(TransactedCompoundFile.Options options) { byte[] sample = new byte[1024]; new Random().NextBytes(sample); List <uint> handles = new List <uint>(); using (TransactedCompoundFile file = new TransactedCompoundFile(options)) { for (int i = 0; i < 1000; i++) { var hid = file.Create(); handles.Add(hid); file.Write(hid, sample, i, sample.Length - i); CompareBytes(sample, i, sample.Length - i, IOStream.ReadAllBytes(file.Read(hid))); if (i == 500) { file.Commit(); } } } options.CreateNew = false; using (TransactedCompoundFile file = new TransactedCompoundFile(options)) { for (int i = 0; i < 1000; i++) { if (i <= 500 || options.CommitOnWrite || options.CommitOnDispose) { CompareBytes(sample, i, sample.Length - i, IOStream.ReadAllBytes(file.Read(handles[i]))); } else { try { IOStream.ReadAllBytes(file.Read(handles[i])); Assert.Fail(); } catch (ArgumentOutOfRangeException) { } } } } }
public void ConcurrencyTest() { using (TempFile temp = new TempFile()) using (ManualResetEvent stop = new ManualResetEvent(false)) using (TempFile copy = new TempFile()) using (TransactedCompoundFile test = new TransactedCompoundFile( new TransactedCompoundFile.Options(temp.TempPath) { BlockSize = 512, CreateNew = true })) using (WorkQueue workers = new WorkQueue(5)) { bool failed = false; workers.OnError += (o, e) => failed = true; for (int i = 0; i < 5; i++) { workers.Enqueue(() => ExersizeFile(stop, test)); } do { System.Threading.Thread.Sleep(1000); test.Commit(); File.Copy(temp.TempPath, copy.TempPath, true); Assert.AreEqual(0, copy.Length % 512); int hcount = (int)(copy.Length / 512); using (TransactedCompoundFile verify = new TransactedCompoundFile( new TransactedCompoundFile.Options(copy.TempPath) { BlockSize = 512, CreateNew = false })) { OrdinalList free = new OrdinalList(); free.Ceiling = hcount; for (int i = 0; i < hcount; i++) { uint h = verify.Create(); free.Add((int)h); if (h >= hcount) { break; } } int verifiedCount = 0; OrdinalList used = free.Invert(hcount); foreach (uint h in used) { // skip reserved offsets. if (h % (512 / 4) == 0 || (h + 1) % (512 / 4) == 0) { continue; } IOStream.ReadAllBytes(verify.Read(h)); verifiedCount++; } System.Diagnostics.Trace.WriteLine("Verified handle count: " + verifiedCount); } } while (!failed && System.Diagnostics.Debugger.IsAttached); stop.Set(); workers.Complete(false, 1000); Assert.IsFalse(failed); } }