private static void TestCreateNewFile(DiskIo stream, FileHeaderBlock fat) { SubFileName id1 = SubFileName.CreateRandom(); SubFileName id2 = SubFileName.CreateRandom(); SubFileName id3 = SubFileName.CreateRandom(); TransactionalEdit trans = new TransactionalEdit(stream); //create 3 files SubFileStream fs1 = trans.CreateFile(id1); SubFileStream fs2 = trans.CreateFile(id2); SubFileStream fs3 = trans.CreateFile(id3); if (fs1.SubFile.FileName != id1) throw new Exception(); //write to the three files SubFileStreamTest.TestSingleByteWrite(fs1); SubFileStreamTest.TestCustomSizeWrite(fs2, 5); SubFileStreamTest.TestCustomSizeWrite(fs3, BlockDataLength + 20); //read from them and verify content. SubFileStreamTest.TestCustomSizeRead(fs3, BlockDataLength + 20); SubFileStreamTest.TestCustomSizeRead(fs2, 5); SubFileStreamTest.TestSingleByteRead(fs1); fs1.Dispose(); fs2.Dispose(); fs3.Dispose(); trans.CommitAndDispose(); }
/// <summary> /// Creates a new DiskIoSession that can be used to read from the disk subsystem. /// </summary> /// <param name="diskIo">owner of the disk</param> /// <param name="ioSession">the base ioSession to use for this io session</param> /// <param name="file">The file that will be read from this diskIoSession</param> public DiskIoSession(DiskIo diskIo, BinaryStreamIoSessionBase ioSession, FileHeaderBlock header, SubFileHeader file) { if (diskIo == null) { throw new ArgumentNullException("diskIo"); } if (diskIo.IsDisposed) { throw new ObjectDisposedException(diskIo.GetType().FullName); } if (ioSession == null) { throw new ArgumentNullException("ioSession"); } if (file == null) { throw new ArgumentNullException("file"); } m_args = new BlockArguments(); m_lastReadonlyBlock = diskIo.LastReadonlyBlock; m_diskMediumIoSession = ioSession; m_snapshotSequenceNumber = header.SnapshotSequenceNumber; m_fileIdNumber = file.FileIdNumber; m_isReadOnly = file.IsReadOnly || diskIo.IsReadOnly; m_blockSize = diskIo.BlockSize; m_diskIo = diskIo; IsValid = false; IsDisposed = false; }
/// <summary> /// Creates a readonly copy of a transaction. /// </summary> /// <param name="dataReader"></param> internal ReadSnapshot(DiskIo dataReader) { if (dataReader == null) throw new ArgumentNullException("dataReader"); m_fileHeaderBlock = dataReader.LastCommittedHeader; m_dataReader = dataReader; }
/// <summary> /// Creates an SubFileStream /// </summary> /// <param name="dataReader">The location to read from.</param> /// <param name="subFile">The file to read.</param> /// <param name="fileHeaderBlock">The FileAllocationTable</param> /// <param name="isReadOnly">Determines if the stream allows editing.</param> internal SubFileStream(DiskIo dataReader, SubFileHeader subFile, FileHeaderBlock fileHeaderBlock, bool isReadOnly) { if (dataReader == null) throw new ArgumentNullException("dataReader"); if (subFile == null) throw new ArgumentNullException("subFile"); if (fileHeaderBlock == null) throw new ArgumentNullException("subFile"); if (!isReadOnly) { if (dataReader.IsReadOnly) throw new ArgumentException("This parameter cannot be read only when opening for writing", "dataReader"); if (fileHeaderBlock.IsReadOnly) throw new ArgumentException("This parameter cannot be read only when opening for writing", "fileHeaderBlock"); if (subFile.IsReadOnly) throw new ArgumentException("This parameter cannot be read only when opening for writing", "subFile"); } if (isReadOnly) { if (!fileHeaderBlock.IsReadOnly) throw new ArgumentException("This parameter must be read only when opening for reading", "fileHeaderBlock"); if (!subFile.IsReadOnly) throw new ArgumentException("This parameter must be read only when opening for reading", "subFile"); } m_blockSize = dataReader.BlockSize; m_dataReader = dataReader; m_subFile = subFile; m_fileHeaderBlock = fileHeaderBlock; m_isReadOnly = isReadOnly; }
private static void TestBinaryStream(DiskIo stream) { FileHeaderBlock header = stream.LastCommittedHeader; header = header.CloneEditable(); SubFileHeader node = header.CreateNewFile(SubFileName.CreateRandom()); header.CreateNewFile(SubFileName.CreateRandom()); header.CreateNewFile(SubFileName.CreateRandom()); SubFileStream ds = new SubFileStream(stream, node, header, false); BinaryStreamTest.Test(ds); }
private static void TestReadAndWrites(DiskIo stream) { FileHeaderBlock header = stream.LastCommittedHeader; header = header.CloneEditable(); SubFileHeader node = header.CreateNewFile(SubFileName.CreateRandom()); header.CreateNewFile(SubFileName.CreateRandom()); header.CreateNewFile(SubFileName.CreateRandom()); SubFileStream ds = new SubFileStream(stream, node, header, false); TestSingleByteWrite(ds); TestSingleByteRead(ds); TestCustomSizeWrite(ds, 5); TestCustomSizeRead(ds, 5); TestCustomSizeWrite(ds, BlockDataLength + 20); TestCustomSizeRead(ds, BlockDataLength + 20); stream.CommitChanges(header); }
/// <summary> /// Releases all the resources used by the <see cref="DiskIoSession"/> object. /// </summary> public void Dispose() { if (!IsDisposed) { try { if (m_diskMediumIoSession != null) { m_diskMediumIoSession.Dispose(); m_diskMediumIoSession = null; } m_diskIo = null; } finally { GC.SuppressFinalize(this); IsValid = false; IsDisposed = true; // Prevent duplicate dispose. } } }
/// <summary> /// Creates a new DiskIoSession that can be used to read from the disk subsystem. /// </summary> /// <param name="diskIo">owner of the disk</param> /// <param name="ioSession">the base ioSession to use for this io session</param> /// <param name="file">The file that will be read from this diskIoSession</param> public DiskIoSession(DiskIo diskIo, BinaryStreamIoSessionBase ioSession, FileHeaderBlock header, SubFileHeader file) { if (diskIo == null) throw new ArgumentNullException("diskIo"); if (diskIo.IsDisposed) throw new ObjectDisposedException(diskIo.GetType().FullName); if (ioSession == null) throw new ArgumentNullException("ioSession"); if (file == null) throw new ArgumentNullException("file"); m_args = new BlockArguments(); m_lastReadonlyBlock = diskIo.LastReadonlyBlock; m_diskMediumIoSession = ioSession; m_snapshotSequenceNumber = header.SnapshotSequenceNumber; m_fileIdNumber = file.FileIdNumber; m_isReadOnly = file.IsReadOnly | diskIo.IsReadOnly; m_blockSize = diskIo.BlockSize; m_diskIo = diskIo; IsValid = false; IsDisposed = false; }
private static void TestReadAndWritesToDifferentFilesWithCommit(DiskIo stream) { FileHeaderBlock header; SubFileStream ds; //Open The File For Editing header = stream.LastCommittedHeader.CloneEditable(); ds = new SubFileStream(stream, header.Files[0], header, false); TestSingleByteWrite(ds); ds = new SubFileStream(stream, header.Files[1], header, false); TestCustomSizeWrite(ds, 5); ds = new SubFileStream(stream, header.Files[2], header, false); TestCustomSizeWrite(ds, BlockDataLength + 20); stream.CommitChanges(header); header = stream.LastCommittedHeader; ds = new SubFileStream(stream, header.Files[0], header, true); TestSingleByteRead(ds); ds = new SubFileStream(stream, header.Files[1], header, true); TestCustomSizeRead(ds, 5); ds = new SubFileStream(stream, header.Files[2], header, true); TestCustomSizeRead(ds, BlockDataLength + 20); }
private static void TestOpenExistingFile(DiskIo stream, FileHeaderBlock fat) { Guid id = Guid.NewGuid(); TransactionalEdit trans = new TransactionalEdit(stream); //create 3 files SubFileStream fs1 = trans.OpenFile(0); SubFileStream fs2 = trans.OpenFile(1); SubFileStream fs3 = trans.OpenFile(2); //read from them and verify content. SubFileStreamTest.TestSingleByteRead(fs1); SubFileStreamTest.TestCustomSizeRead(fs2, 5); SubFileStreamTest.TestCustomSizeRead(fs3, BlockDataLength + 20); //rewrite bad data. SubFileStreamTest.TestSingleByteWrite(fs2); SubFileStreamTest.TestCustomSizeWrite(fs3, 5); SubFileStreamTest.TestCustomSizeWrite(fs1, BlockDataLength + 20); fs1.Dispose(); fs2.Dispose(); fs3.Dispose(); trans.CommitAndDispose(); }
private static void TestRollback(DiskIo stream, FileHeaderBlock fat) { SubFileName id1 = SubFileName.CreateRandom(); SubFileName id2 = SubFileName.CreateRandom(); SubFileName id3 = SubFileName.CreateRandom(); TransactionalEdit trans = new TransactionalEdit(stream); //create 3 files additional files SubFileStream fs21 = trans.CreateFile(id1); SubFileStream fs22 = trans.CreateFile(id2); SubFileStream fs23 = trans.CreateFile(id3); //open files SubFileStream fs1 = trans.OpenFile(0); SubFileStream fs2 = trans.OpenFile(1); SubFileStream fs3 = trans.OpenFile(2); //read from them and verify content. SubFileStreamTest.TestSingleByteRead(fs2); SubFileStreamTest.TestCustomSizeRead(fs3, 5); SubFileStreamTest.TestCustomSizeRead(fs1, BlockDataLength + 20); //rewrite bad data. SubFileStreamTest.TestSingleByteWrite(fs3); SubFileStreamTest.TestCustomSizeWrite(fs1, 5); SubFileStreamTest.TestCustomSizeWrite(fs2, BlockDataLength + 20); fs1.Dispose(); fs2.Dispose(); fs3.Dispose(); fs21.Dispose(); fs22.Dispose(); fs23.Dispose(); trans.RollbackAndDispose(); }
private TransactionalFileStructure(DiskIo diskIo) { m_diskIo = diskIo; m_currentReadTransaction = new ReadSnapshot(diskIo); }
/// <summary> /// Releases all the resources used by the <see cref="TransactionalFileStructure"/> object. /// </summary> public void Dispose() { if (!m_disposed) { try { if (m_currentTransaction != null) { m_currentTransaction.Dispose(); m_currentTransaction = null; } if (m_diskIo != null) { m_diskIo.Dispose(); m_diskIo = null; } } finally { GC.SuppressFinalize(this); m_disposed = true; // Prevent duplicate dispose. } } }
/// <summary> /// Creates this file with the following data. /// </summary> /// <param name="diskIo"></param> /// <param name="header"></param> /// <param name="file"></param> /// <param name="isReadOnly"></param> public SubFileDiskIoSessionPool(DiskIo diskIo, FileHeaderBlock header, SubFileHeader file, bool isReadOnly) { LastReadonlyBlock = diskIo.LastCommittedHeader.LastAllocatedBlock; File = file; Header = header; IsReadOnly = isReadOnly; SourceData = diskIo.CreateDiskIoSession(header, file); SourceIndex = diskIo.CreateDiskIoSession(header, file); if (!isReadOnly) { DestinationData = diskIo.CreateDiskIoSession(header, file); DestinationIndex = diskIo.CreateDiskIoSession(header, file); } }
private static void TestReadAndWritesWithCommit(DiskIo stream) { FileHeaderBlock header; SubFileHeader node; SubFileStream ds, ds1, ds2; //Open The File For Editing header = stream.LastCommittedHeader.CloneEditable(); node = header.Files[0]; ds = new SubFileStream(stream, node, header, false); TestSingleByteWrite(ds); stream.CommitChanges(header); header = stream.LastCommittedHeader; node = header.Files[0]; ds1 = ds = new SubFileStream(stream, node, header, true); TestSingleByteRead(ds); //Open The File For Editing header = stream.LastCommittedHeader.CloneEditable(); node = header.Files[0]; ds = new SubFileStream(stream, node, header, false); TestCustomSizeWrite(ds, 5); stream.CommitChanges(header); header = stream.LastCommittedHeader; node = header.Files[0]; ds2 = ds = new SubFileStream(stream, node, header, true); TestCustomSizeRead(ds, 5); //Open The File For Editing header = stream.LastCommittedHeader.CloneEditable(); node = header.Files[0]; ds = new SubFileStream(stream, node, header, false); TestCustomSizeWrite(ds, BlockDataLength + 20); stream.CommitChanges(header); header = stream.LastCommittedHeader; node = header.Files[0]; ds = new SubFileStream(stream, node, header, true); TestCustomSizeRead(ds, BlockDataLength + 20); //check old versions of the file TestSingleByteRead(ds1); TestCustomSizeRead(ds2, 5); }
private static void TestVerifyRollback(DiskIo stream, FileHeaderBlock fat) { Guid id = Guid.NewGuid(); TransactionalEdit trans = new TransactionalEdit(stream); if (trans.Files.Count != 3) throw new Exception(); //open files SubFileStream fs1 = trans.OpenFile(0); SubFileStream fs2 = trans.OpenFile(1); SubFileStream fs3 = trans.OpenFile(2); //read from them and verify content. SubFileStreamTest.TestSingleByteRead(fs2); SubFileStreamTest.TestCustomSizeRead(fs3, 5); SubFileStreamTest.TestCustomSizeRead(fs1, BlockDataLength + 20); fs1.Dispose(); fs2.Dispose(); fs3.Dispose(); trans.Dispose(); }