The IO system that the entire file structure uses to acomplish it's IO operations. This class hands data one block at a time to requesting classes and is responsible for checking the footer data of the file for corruption.
Inheritance: IDisposable
        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();
        }
Example #2
0
        /// <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);
        }
Example #7
0
 /// <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>
 /// 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 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();
        }