public void CorrectlyRecoverSequentiallyUpdatedPage() { long index; using (var fileSystemPageManager = new FileSystemPageManager(4096)) using (var storage = new Storage(fileSystemPageManager)) { storage.OpenOrCreate(StoragePath); var page = fileSystemPageManager.CreatePage(); index = page.Index; } string fileName; using (var fileSystemPageManager = new FileSystemPageManager(4096)) using (var storage = new Storage(fileSystemPageManager)) using (var recoveryFile = new RecoveryFile(fileSystemPageManager, fileSystemPageManager.PageSize)) { storage.OpenOrCreate(StoragePath); var page = fileSystemPageManager.FetchPage(index); index = page.Index; fileSystemPageManager.Dispose(); Assert.AreEqual(index, page.Index); Assert.AreNotEqual(0xff, page.Content[10]); // Update twice with different bytes to make sure the latest one wins page.Content[9] = 0xaa; page.Content[10] = 0xaa; recoveryFile.WriteUpdatePageRecord(page); page.Content[10] = 0xff; recoveryFile.WriteUpdatePageRecord(page); recoveryFile.WriteFinalMarker(); fileName = recoveryFile.FileName; } Assert.True(File.Exists(fileName)); Assert.GreaterOrEqual(new FileInfo(fileName).Length, 1); Assert.AreNotEqual(index, 0); using (var manager = new FileSystemPageManager(4096)) using (var storage = new Storage(manager)) { storage.OpenOrCreate(StoragePath); var page = manager.FetchPage(index); Assert.AreEqual(index, page.Index); Assert.AreEqual(0xaa, page.Content[9]); Assert.AreEqual(0xff, page.Content[10]); } }
/// <summary> /// Updates a page. /// </summary> /// <param name="page">A page instance to update</param> public void UpdatePage(IPage page) { CheckDisposed(); if (page == null) { throw new ArgumentNullException(nameof(page)); } Lock(); try { CheckStorage(); if (_deferredUpdatesMode) { _recoveryFile.WriteUpdatePageRecord(page); } else { long pageAllocation = _pagemap.GetPageAllocation(page.Index); if (pageAllocation == -1) { throw new PageMapException("Page is removed"); } CheckRemovalMarker(page.Index); _storageStream.Seek(pageAllocation, SeekOrigin.Begin); _storageStream.Write(page.ContentCopy, 0, _pageSize); _pagemap.Flush(); Flush(_storageStream); } } finally { Unlock(); } }
public void CorrectlyRecoverResurrectedPage() { long index; long resurrectIndex; using (var fileSystemPageManager = new FileSystemPageManager(4096)) using (var storage = new Storage(fileSystemPageManager)) { storage.OpenOrCreate(StoragePath); var page = fileSystemPageManager.CreatePage(); index = page.Index; } using (var fileSystemPageManager = new FileSystemPageManager(4096)) using (var storage = new Storage(fileSystemPageManager)) { storage.OpenOrCreate(StoragePath); var page = fileSystemPageManager.FetchPage(index); Assert.AreEqual(index, page.Index); Assert.AreNotEqual(0xff, page.Content[10]); } string fileName; using (var fileSystemPageManager = new FileSystemPageManager(4096)) using (var storage = new Storage(fileSystemPageManager)) using (var recoveryFile = new RecoveryFile(fileSystemPageManager, fileSystemPageManager.PageSize)) { storage.OpenOrCreate(StoragePath); var page = fileSystemPageManager.FetchPage(index); index = page.Index; page.Content[10] = 0xaf; fileSystemPageManager.RemovePage(index); var resurrectedPage = fileSystemPageManager.CreatePage(); resurrectIndex = resurrectedPage.Index; //check we're not going wrong way Assert.AreEqual(index, resurrectIndex); resurrectedPage.Content[10] = 0xff; Assert.AreNotEqual(0xff, page.Content[10]); fileSystemPageManager.Dispose(); recoveryFile.WriteUpdatePageRecord(page); recoveryFile.WriteDeletePageRecord(index); recoveryFile.WriteUpdatePageRecord(resurrectedPage); recoveryFile.WriteFinalMarker(); fileName = recoveryFile.FileName; } Assert.True(File.Exists(fileName)); Assert.GreaterOrEqual(new FileInfo(fileName).Length, 1); using (var manager = new FileSystemPageManager(4096)) using (var storage = new Storage(manager)) { storage.OpenOrCreate(StoragePath); var page = manager.FetchPage(index); Assert.AreEqual(resurrectIndex, page.Index); Assert.AreEqual(0xff, page.Content[10]); } }