/// <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;
 }
Esempio n. 2
0
        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 void SetHeaderTab(FileHeaderBlock fileHeaderBlock)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("File Type: ").Append(fileHeaderBlock.FileTypeToASCII()).AppendLine();
            sb.Append("File Version: ").Append(fileHeaderBlock.FileVersion.ToString()).AppendLine();
            if (fileHeaderBlock.CreationMethod == 0)
            {
                sb.Append("Creation Method: ").Append("Simulation").AppendLine();
            }
            else
            {
                sb.Append("Creation Method: ").Append("Measurement").AppendLine();
            }
            sb.Append("Total Luminous Flux: ").Append(fileHeaderBlock.TotalLuminousFlux.ToString()).AppendLine();
            sb.Append("Total Radiant Flux: ").Append(fileHeaderBlock.TotalRadiantFlux.ToString()).AppendLine();
            sb.Append("Number of Rays: ").Append(fileHeaderBlock.NumberOfRays.ToString()).AppendLine();
            sb.Append("File Creation Data: ").Append(fileHeaderBlock.FileCreationDatetoASCII().ToString()).AppendLine();
            sb.Append("Ray Start Position: ").Append(RayStartOptions[fileHeaderBlock.RayStartPosition].ToString()).AppendLine();
            sb.Append("Spectral Data Identifier: ").Append(SpectralDataOptions[fileHeaderBlock.SpectralDataIdentifier].ToString()).AppendLine();
            sb.Append("Single Wavelength: ").Append(fileHeaderBlock.SingleWavelength.ToString()).AppendLine();
            sb.Append("Minimum Wavelength: ").Append(fileHeaderBlock.MinimumWavelength.ToString()).AppendLine();
            sb.Append("Maximum Wavelength: ").Append(fileHeaderBlock.MaximumWavelength.ToString()).AppendLine();
            sb.Append("Number of Spectral Tables: ").Append(fileHeaderBlock.NumberOfSpectralTables.ToString()).AppendLine();
            sb.Append("Number of Additiona Ray Data Items: ").Append(fileHeaderBlock.NumberOfAdditionalRayDataItemsPerRay.ToString()).AppendLine();
            sb.Append("Size of Additional Text Block: ").Append(fileHeaderBlock.SizeOfAdditionalTextBlock.ToString()).AppendLine();
            sb.Append("Reserved for Additional Use: ").AppendLine();

            string headerString = sb.ToString();

            richTextBoxHeader.Text = headerString;
        }
Esempio n. 4
0
 /// <summary>
 /// Executes a commit of data. This will flush the data to the disk use the provided header data to properly
 /// execute this function.
 /// </summary>
 /// <param name="headerBlock"></param>
 public void CommitChanges(FileHeaderBlock headerBlock)
 {
     if (IsDisposed)
     {
         throw new ObjectDisposedException("MemoryStream");
     }
 }
        public void Test()
        {
            Assert.AreEqual(Globals.MemoryPool.AllocatedBytes, 0L);

            string fileName = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".tmp");

            try
            {
                using (DiskIo stream = DiskIo.CreateFile(fileName, Globals.MemoryPool, BlockSize))
                {
                    FileHeaderBlock fat = stream.LastCommittedHeader;
                    //obtain a readonly copy of the file allocation table.
                    fat = stream.LastCommittedHeader;
                    TestCreateNewFile(stream, fat);
                    fat = stream.LastCommittedHeader;
                    TestOpenExistingFile(stream, fat);
                    fat = stream.LastCommittedHeader;
                    TestRollback(stream, fat);
                    fat = stream.LastCommittedHeader;
                    TestVerifyRollback(stream, fat);
                    Assert.IsTrue(true);
                }
            }
            finally
            {
                File.Delete(fileName);
            }

            Assert.AreEqual(Globals.MemoryPool.AllocatedBytes, 0L);
        }
Esempio n. 6
0
        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();
        }
Esempio n. 7
0
        /// <summary>
        /// Creates a file backed memory stream.
        /// </summary>
        /// <param name="stream">The <see cref="CustomFileStream"/> to buffer</param>
        /// <param name="pool">The <see cref="MemoryPool"/> to allocate memory from</param>
        /// <param name="header">The <see cref="FileHeaderBlock"/> to be managed when modifications occur</param>
        /// <param name="isNewFile">Tells if this is a newly created file. This will make sure that the
        /// first 10 pages have the header data copied to it.</param>
        public BufferedFile(CustomFileStream stream, MemoryPool pool, FileHeaderBlock header, bool isNewFile)
        {
            m_fileStructureBlockSize = header.BlockSize;
            m_diskBlockSize          = pool.PageSize;
            m_lengthOfHeader         = header.BlockSize * header.HeaderBlockCount;
            m_writeBuffer            = new MemoryPoolStreamCore(pool);
            m_pool     = pool;
            m_queue    = stream;
            m_syncRoot = new object();
            m_pageReplacementAlgorithm = new PageReplacementAlgorithm(pool);
            pool.RequestCollection    += m_pool_RequestCollection;

            if (isNewFile)
            {
                try
                {
                    m_queue.Open();
                    byte[] headerBytes = header.GetBytes();
                    for (int x = 0; x < header.HeaderBlockCount; x++)
                    {
                        m_queue.WriteRaw(0, headerBytes, headerBytes.Length);
                    }
                }
                finally
                {
                    m_queue.Close();
                }
            }
            m_lengthOfCommittedData = (header.LastAllocatedBlock + 1) * header.BlockSize;
            m_writeBuffer.ConfigureAlignment(m_lengthOfCommittedData, pool.PageSize);
        }
Esempio n. 8
0
 private static void CheckEqual(FileHeaderBlock RO, FileHeaderBlock RW)
 {
     if (!AreEqual(RW, RO))
     {
         throw new Exception();
     }
 }
Esempio n. 9
0
 /// <summary>
 /// Occurs when committing the following data to the disk.
 /// This will copy any pending data to the disk in a manner that
 /// will protect against corruption.
 /// </summary>
 /// <param name="header"></param>
 public void CommitChanges(FileHeaderBlock header)
 {
     header.IsReadOnly = true;
     m_disk.CommitChanges(header);
     Thread.MemoryBarrier();
     m_header = header;
 }
        /// <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;
        }
Esempio n. 11
0
        /// <summary>
        /// Creates a <see cref="DiskMedium"/> that is entirely based in memory.
        /// </summary>
        /// <param name="pool">the <see cref="MemoryPool"/> to allocate data from</param>
        /// <param name="fileStructureBlockSize">the block size of the file structure. Usually 4kb.</param>
        /// <param name="flags">Flags to write to the file</param>
        /// <returns></returns>
        public static DiskMedium CreateMemoryFile(MemoryPool pool, int fileStructureBlockSize, params Guid[] flags)
        {
            FileHeaderBlock header = FileHeaderBlock.CreateNew(fileStructureBlockSize, flags);
            MemoryPoolFile  disk   = new MemoryPoolFile(pool);

            return(new DiskMedium(disk, header));
        }
        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();
        }
Esempio n. 13
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;
        }
Esempio n. 14
0
        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();
        }
Esempio n. 15
0
 /// <summary>
 /// Creates a <see cref="DiskIoSession"/> that can be used to perform basic read/write functions.
 /// </summary>
 /// <returns></returns>
 public DiskIoSession CreateDiskIoSession(FileHeaderBlock header, SubFileHeader file)
 {
     if (m_disposed)
     {
         throw new ObjectDisposedException(GetType().FullName);
     }
     return(new DiskIoSession(this, m_stream.CreateIoSession(), header, file));
 }
Esempio n. 16
0
        /// <summary>
        /// Creates a <see cref="DiskMedium"/> from a <see cref="stream"/>.
        /// This will initialize the <see cref="stream"/> as an empty file structure.
        /// </summary>
        /// <param name="stream">An open <see cref="FileStream"/> to use. The <see cref="DiskMedium"/>
        ///     will assume ownership of this <see cref="FileStream"/>.</param>
        /// <param name="pool">the <see cref="MemoryPool"/> to allocate data from</param>
        /// <param name="fileStructureBlockSize">the block size of the file structure. Usually 4kb.</param>
        /// <param name="flags">Flags to write to the file</param>
        /// <returns></returns>
        /// <remarks>
        /// This will not check if the file is truely a new file. If calling this with an existing
        /// archive file, it will overwrite the table of contents, corrupting the file.
        /// </remarks>
        public static DiskMedium CreateFile(CustomFileStream stream, MemoryPool pool, int fileStructureBlockSize, params Guid[] flags)
        {
            FileHeaderBlock header = FileHeaderBlock.CreateNew(fileStructureBlockSize, flags);

            BufferedFile disk = new BufferedFile(stream, pool, header, isNewFile: true);

            return(new DiskMedium(disk, header));
        }
 /// <summary>
 /// Creates a simplified file writer.
 /// </summary>
 /// <param name="pendingFileName"></param>
 /// <param name="completeFileName"></param>
 /// <param name="blockSize"></param>
 /// <param name="flags"></param>
 public SimplifiedFileWriter(string pendingFileName, string completeFileName, int blockSize, params Guid[] flags)
 {
     m_pendingFileName = pendingFileName;
     m_completeFileName = completeFileName;
     m_fileHeaderBlock = FileHeaderBlock.CreateNewSimplified(blockSize, flags).CloneEditable();
     m_fileHeaderBlock.ArchiveType = SortedTreeFile.FileType;
     m_stream = new FileStream(pendingFileName, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None);
 }
Esempio n. 18
0
        /// <summary>
        /// Creates a <see cref="DiskMedium"/> from a <see cref="stream"/>.
        /// This will read the existing header from the <see cref="stream"/>.
        /// </summary>
        /// <param name="stream">An open <see cref="FileStream"/> to use. The <see cref="DiskMedium"/>
        /// will assume ownership of this <see cref="FileStream"/>.</param>
        /// <param name="pool">The <see cref="MemoryPool"/> to allocate data from.</param>
        /// <param name="fileStructureBlockSize">the block size of the file structure. Usually 4kb.</param>
        /// <returns></returns>
        public static DiskMedium OpenFile(CustomFileStream stream, MemoryPool pool, int fileStructureBlockSize)
        {
            byte[] buffer = new byte[fileStructureBlockSize];
            stream.ReadRaw(0, buffer, fileStructureBlockSize);
            FileHeaderBlock header = FileHeaderBlock.Open(buffer);
            BufferedFile    disk   = new BufferedFile(stream, pool, header, isNewFile: false);

            return(new DiskMedium(disk, header));
        }
Esempio n. 19
0
        /// <summary>
        /// Opens a file
        /// </summary>
        /// <param name="fileName">the name of the file.</param>
        /// <param name="ioBlockSize">the number of bytes to do all of the io</param>
        /// <param name="fileStructureBlockSize">The number of bytes in the file structure</param>
        /// <param name="isReadOnly">if the file should be opened in read only</param>
        /// <param name="isSharingEnabled">if the file should be opened with read sharing permissions.</param>
        /// <returns></returns>
        public static CustomFileStream OpenFile(string fileName, int ioBlockSize, out int fileStructureBlockSize, bool isReadOnly, bool isSharingEnabled)
        {
            using (FileStream fileStream = new FileStream(fileName, FileMode.Open, isReadOnly ? FileAccess.Read : FileAccess.ReadWrite, isSharingEnabled ? FileShare.Read : FileShare.None, 2048, true))
            {
                fileStructureBlockSize = FileHeaderBlock.SearchForBlockSize(fileStream);
            }

            return(new CustomFileStream(ioBlockSize, fileStructureBlockSize, fileName, isReadOnly, isSharingEnabled));
        }
Esempio n. 20
0
 /// <summary>
 /// Occurs when committing the following data to the disk.
 /// This will copy any pending data to the disk in a manner that
 /// will protect against corruption.
 /// </summary>
 /// <param name="header"></param>
 public void CommitChanges(FileHeaderBlock header)
 {
     if (m_disposed)
     {
         throw new ObjectDisposedException(GetType().FullName);
     }
     if (m_isReadOnly)
     {
         throw new ReadOnlyException();
     }
     m_stream.CommitChanges(header);
 }
 /// <summary>
 /// Creates a <see cref="ShadowCopyAllocator"/> that is used make shadow copies of blocks.
 /// </summary>
 /// <param name="ioSessions"></param>
 public ShadowCopyAllocator(SubFileDiskIoSessionPool ioSessions)
     : base(ioSessions)
 {
     if (ioSessions == null)
         throw new ArgumentNullException("ioSessions");
     if (ioSessions.IsReadOnly)
         throw new ArgumentException("DataReader is read only", "ioSessions");
     m_lastReadOnlyBlock = ioSessions.LastReadonlyBlock;
     m_fileHeaderBlock = ioSessions.Header;
     m_subFileHeader = ioSessions.File;
     m_ioSessions = ioSessions;
 }
        public void CheckFileTypeToASCII()
        {
            //Arrange
            FileHeaderBlock headerBlock = new FileHeaderBlock();

            headerBlock.FileType = Helpers.GetFixedSizeByteArrayFromBinaryString("TM25", 4);
            var expected = "TM25";

            //Act
            string result = headerBlock.FileTypeToASCII();

            //Assert
            Assert.AreEqual(expected, result);
        }
        public void CheckFileCreationDateToASCII()
        {
            //Arrange
            FileHeaderBlock headerBlock = new FileHeaderBlock();

            headerBlock.FileCreationDateAndTime = Helpers.GetFixedSizeByteArrayFromBinaryString("2013-09-04T08:30:29+01:00", 28);
            var expected = "2013-09-04T08:30:29+01:00   ";

            //Act
            string result = headerBlock.FileCreationDatetoASCII();

            //Assert
            Assert.AreEqual(expected, result);
        }
        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);
        }
Esempio n. 25
0
        /// <summary>
        /// Opens a file
        /// </summary>
        /// <param name="fileName">the name of the file.</param>
        /// <param name="ioBlockSize">the number of bytes to do all of the io</param>
        /// <param name="fileStructureBlockSize">The number of bytes in the file structure</param>
        /// <param name="isReadOnly">if the file should be opened in read only</param>
        /// <param name="isSharingEnabled">if the file should be opened with read sharing permissions.</param>
        /// <returns></returns>
        public static CustomFileStream OpenFile(string fileName, int ioBlockSize, out int fileStructureBlockSize, bool isReadOnly, bool isSharingEnabled)
        {
            //Exclusive opening to prevent duplicate opening.

            FileStream fileStream = new FileStream(fileName, FileMode.Open, isReadOnly ? FileAccess.Read : FileAccess.ReadWrite, isSharingEnabled ? FileShare.Read : FileShare.None, 2048, true);

            try
            {
                fileStructureBlockSize = FileHeaderBlock.SearchForBlockSize(fileStream);
            }
            catch (Exception)
            {
                fileStream.Dispose();
                throw;
            }
            return(new CustomFileStream(fileStream, ioBlockSize, fileStructureBlockSize, fileName, isReadOnly, isSharingEnabled));
        }
Esempio n. 26
0
        public void Test()
        {
            MemoryPoolTest.TestMemoryLeak();
            Assert.AreEqual(Globals.MemoryPool.AllocatedBytes, 0L);
            FileHeaderBlock header = FileHeaderBlock.CreateNew(4096);

            header = header.CloneEditable();
            header.CreateNewFile(SubFileName.CreateRandom());
            header.CreateNewFile(SubFileName.CreateRandom());
            header.CreateNewFile(SubFileName.CreateRandom());
            header.IsReadOnly = true;

            FileHeaderBlock header2 = FileHeaderBlock.Open(header.GetBytes());

            CheckEqual(header2, header);
            Assert.AreEqual(Globals.MemoryPool.AllocatedBytes, 0L);
            //verify they are the same;
            MemoryPoolTest.TestMemoryLeak();
        }
Esempio n. 27
0
        public void Test()
        {
            Assert.AreEqual(Globals.MemoryPool.AllocatedBytes, 0L);
            DiskIo          stream = DiskIo.CreateMemoryFile(Globals.MemoryPool, BlockSize);
            FileHeaderBlock fat    = stream.LastCommittedHeader;

            //obtain a readonly copy of the file allocation table.
            fat = stream.LastCommittedHeader;
            TestCreateNewFile(stream, fat);
            fat = stream.LastCommittedHeader;
            TestOpenExistingFile(stream, fat);
            fat = stream.LastCommittedHeader;
            TestRollback(stream, fat);
            fat = stream.LastCommittedHeader;
            TestVerifyRollback(stream, fat);
            Assert.IsTrue(true);
            stream.Dispose();
            Assert.AreEqual(Globals.MemoryPool.AllocatedBytes, 0L);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        /// <remarks>A debug function</remarks>
        internal static bool AreEqual(FileHeaderBlock other, FileHeaderBlock self)
        {
            if (other == null)
                return false;
            if (self == null)
                return false;
            if (self.CanWrite != other.CanWrite) return false;
            if (self.CanRead != other.CanRead) return false;
            if (self.ArchiveId != other.ArchiveId) return false;
            if (self.ArchiveType != other.ArchiveType) return false;
            if (self.SnapshotSequenceNumber != other.SnapshotSequenceNumber) return false;
            if (self.LastAllocatedBlock != other.LastAllocatedBlock) return false;
            if (self.FileCount != other.FileCount) return false;

            //compare files.
            if (self.Files == null)
            {
                if (other.Files != null) return false;
            }
            else
            {
                if (other.Files == null) return false;
                if (self.Files.Count != other.Files.Count) return false;
                for (int x = 0; x < self.Files.Count; x++)
                {
                    SubFileHeader subFile = self.Files[x];
                    SubFileHeader subFileOther = other.Files[x];

                    if (subFile == null)
                    {
                        if (subFileOther != null) return false;
                    }
                    else
                    {
                        if (subFileOther == null) return false;
                        if (!SubFileMetaDataTest.AreEqual(subFile, subFileOther)) return false;
                    }
                }
            }

            return (self.GetBytes().SequenceEqual(other.GetBytes()));
        }
        public SimplifiedSubFileStreamIoSession(FileStream stream, SubFileHeader subFile, FileHeaderBlock header)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");
            if (subFile == null)
                throw new ArgumentNullException("subFile");
            if (header == null)
                throw new ArgumentNullException("header");
            if (subFile.DirectBlock == 0)
                throw new Exception("Must assign subFile.DirectBlock");

            m_stream = stream;
            m_header = header;
            m_blockSize = header.BlockSize;
            m_subFile = subFile;
            m_memory = new Memory(m_blockSize);
            m_buffer = new byte[m_blockSize];
            m_currentPhysicalBlock = -1;
            m_blockDataLength = m_blockSize - FileStructureConstants.BlockFooterLength;
        }
        /// <summary>
        /// Creates an SimplifiedSubFileStream
        /// </summary>
        /// <param name="stream">The location to read from.</param>
        /// <param name="subFile">The file to read.</param>
        /// <param name="fileHeaderBlock">The FileAllocationTable</param>
        internal SimplifiedSubFileStream(FileStream stream, SubFileHeader subFile, FileHeaderBlock fileHeaderBlock)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");
            if (subFile == null)
                throw new ArgumentNullException("subFile");
            if (fileHeaderBlock == null)
                throw new ArgumentNullException("fileHeaderBlock");
            if (subFile.DirectBlock == 0)
                throw new Exception("Must assign subFile.DirectBlock");

            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");

            m_blockSize = fileHeaderBlock.BlockSize;
            m_stream = stream;
            m_subFile = subFile;
            m_fileHeaderBlock = fileHeaderBlock;
        }
        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>
        /// 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;
        }
Esempio n. 33
0
        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();
        }
 /// <summary>
 /// Occurs when committing the following data to the disk.
 /// This will copy any pending data to the disk in a manner that
 /// will protect against corruption.
 /// </summary>
 /// <param name="header"></param>
 public void CommitChanges(FileHeaderBlock header)
 {
     if (m_disposed)
         throw new ObjectDisposedException(GetType().FullName);
     if (m_isReadOnly)
         throw new ReadOnlyException();
     m_stream.CommitChanges(header);
 }
Esempio n. 35
0
 /// <summary>
 /// Class is created through static methods of this class.
 /// </summary>
 /// <param name="disk">the underlying disk medium</param>
 /// <param name="header">the header data to use.</param>
 private DiskMedium(IDiskMediumCoreFunctions disk, FileHeaderBlock header)
 {
     m_header    = header;
     m_disk      = disk;
     m_blockSize = header.BlockSize;
 }
Esempio n. 36
0
        /// <summary>
        /// Executes a commit of data. This will flush the data to the disk use the provided header data to properly
        /// execute this function.
        /// </summary>
        /// <param name="header"></param>
        public void CommitChanges(FileHeaderBlock header)
        {
            using (var pageLock = new IoSession(this, m_pageReplacementAlgorithm))
            {
                //Determine how much committed data to write
                long lengthOfAllData = (header.LastAllocatedBlock + 1) * (long)m_fileStructureBlockSize;
                long copyLength      = lengthOfAllData - m_lengthOfCommittedData;

                //Write the uncommitted data.
                m_queue.Write(m_lengthOfCommittedData, m_writeBuffer, copyLength, waitForWriteToDisk: true);

                byte[] bytes = header.GetBytes();
                if (header.HeaderBlockCount == 10)
                {
                    //Update the new header to position 0, position 1, and one of position 2-9
                    m_queue.WriteRaw(0, bytes, m_fileStructureBlockSize);
                    m_queue.WriteRaw(m_fileStructureBlockSize, bytes, m_fileStructureBlockSize);
                    m_queue.WriteRaw(m_fileStructureBlockSize * ((header.SnapshotSequenceNumber & 7) + 2), bytes, m_fileStructureBlockSize);
                }
                else
                {
                    for (int x = 0; x < header.HeaderBlockCount; x++)
                    {
                        m_queue.WriteRaw(x * m_fileStructureBlockSize, bytes, m_fileStructureBlockSize);
                    }
                }

                m_queue.FlushFileBuffers();

                long startPos;

                //Copy recently committed data to the buffer pool
                if ((m_lengthOfCommittedData & (m_diskBlockSize - 1)) != 0) //Only if there is a split page.
                {
                    startPos = m_lengthOfCommittedData & (~(long)(m_diskBlockSize - 1));
                    //Finish filling up the split page in the buffer.
                    IntPtr ptrDest;

                    if (pageLock.TryGetSubPage(startPos, out ptrDest))
                    {
                        int    length;
                        IntPtr ptrSrc;
                        m_writeBuffer.ReadBlock(m_lengthOfCommittedData, out ptrSrc, out length);
                        Footer.WriteChecksumResultsToFooter(ptrSrc, m_fileStructureBlockSize, length);
                        ptrDest += (m_diskBlockSize - length);
                        Memory.Copy(ptrSrc, ptrDest, length);
                    }
                    startPos += m_diskBlockSize;
                }
                else
                {
                    startPos = m_lengthOfCommittedData;
                }

                while (startPos < lengthOfAllData)
                {
                    //If the address doesn't exist in the current list. Read it from the disk.
                    int    poolPageIndex;
                    IntPtr poolAddress;
                    m_pool.AllocatePage(out poolPageIndex, out poolAddress);
                    m_writeBuffer.CopyTo(startPos, poolAddress, m_diskBlockSize);
                    Footer.WriteChecksumResultsToFooter(poolAddress, m_fileStructureBlockSize, m_diskBlockSize);

                    if (!m_pageReplacementAlgorithm.TryAddPage(startPos, poolAddress, poolPageIndex))
                    {
                        m_pool.ReleasePage(poolPageIndex);
                    }

                    startPos += m_diskBlockSize;
                }
                m_lengthOfCommittedData = lengthOfAllData;
            }
            ReleaseWriteBufferSpace();
        }
        /// <summary>
        /// Executes a commit of data. This will flush the data to the disk use the provided header data to properly
        /// execute this function.
        /// </summary>
        /// <param name="header"></param>
        public void CommitChanges(FileHeaderBlock header)
        {
            using (var pageLock = new IoSession(this, m_pageReplacementAlgorithm))
            {
                //Determine how much committed data to write
                long lengthOfAllData = (header.LastAllocatedBlock + 1) * (long)m_fileStructureBlockSize;
                long copyLength = lengthOfAllData - m_lengthOfCommittedData;

                //Write the uncommitted data.
                m_queue.Write(m_lengthOfCommittedData, m_writeBuffer, copyLength, waitForWriteToDisk: true);

                byte[] bytes = header.GetBytes();
                if (header.HeaderBlockCount == 10)
                {
                    //Update the new header to position 0, position 1, and one of position 2-9
                    m_queue.WriteRaw(0, bytes, m_fileStructureBlockSize);
                    m_queue.WriteRaw(m_fileStructureBlockSize, bytes, m_fileStructureBlockSize);
                    m_queue.WriteRaw(m_fileStructureBlockSize * ((header.SnapshotSequenceNumber & 7) + 2), bytes, m_fileStructureBlockSize);
                }
                else
                {
                    for (int x = 0; x < header.HeaderBlockCount; x++)
                    {
                        m_queue.WriteRaw(x * m_fileStructureBlockSize, bytes, m_fileStructureBlockSize);
                    }
                }

                m_queue.FlushFileBuffers();

                long startPos;

                //Copy recently committed data to the buffer pool
                if ((m_lengthOfCommittedData & (m_diskBlockSize - 1)) != 0) //Only if there is a split page.
                {
                    startPos = m_lengthOfCommittedData & (~(long)(m_diskBlockSize - 1));
                    //Finish filling up the split page in the buffer.
                    IntPtr ptrDest;

                    if (pageLock.TryGetSubPage(startPos, out ptrDest))
                    {
                        int length;
                        IntPtr ptrSrc;
                        m_writeBuffer.ReadBlock(m_lengthOfCommittedData, out ptrSrc, out length);
                        Footer.WriteChecksumResultsToFooter(ptrSrc, m_fileStructureBlockSize, length);
                        ptrDest += (m_diskBlockSize - length);
                        Memory.Copy(ptrSrc, ptrDest, length);
                    }
                    startPos += m_diskBlockSize;
                }
                else
                {
                    startPos = m_lengthOfCommittedData;
                }

                while (startPos < lengthOfAllData)
                {
                    //If the address doesn't exist in the current list. Read it from the disk.
                    int poolPageIndex;
                    IntPtr poolAddress;
                    m_pool.AllocatePage(out poolPageIndex, out poolAddress);
                    m_writeBuffer.CopyTo(startPos, poolAddress, m_diskBlockSize);
                    Footer.WriteChecksumResultsToFooter(poolAddress, m_fileStructureBlockSize, m_diskBlockSize);

                    if (!m_pageReplacementAlgorithm.TryAddPage(startPos, poolAddress, poolPageIndex))
                        m_pool.ReleasePage(poolPageIndex);

                    startPos += m_diskBlockSize;
                }
                m_lengthOfCommittedData = lengthOfAllData;
            }
            ReleaseWriteBufferSpace();
        }
        /// <summary>
        /// Creates a file backed memory stream.
        /// </summary>
        /// <param name="stream">The <see cref="CustomFileStream"/> to buffer</param>
        /// <param name="pool">The <see cref="MemoryPool"/> to allocate memory from</param>
        /// <param name="header">The <see cref="FileHeaderBlock"/> to be managed when modifications occur</param>
        /// <param name="isNewFile">Tells if this is a newly created file. This will make sure that the 
        /// first 10 pages have the header data copied to it.</param>
        public BufferedFile(CustomFileStream stream, MemoryPool pool, FileHeaderBlock header, bool isNewFile)
        {
            m_fileStructureBlockSize = header.BlockSize;
            m_diskBlockSize = pool.PageSize;
            m_lengthOfHeader = header.BlockSize * header.HeaderBlockCount;
            m_writeBuffer = new MemoryPoolStreamCore(pool);
            m_pool = pool;
            m_queue = stream;
            m_syncRoot = new object();
            m_pageReplacementAlgorithm = new PageReplacementAlgorithm(pool);
            pool.RequestCollection += m_pool_RequestCollection;

            if (isNewFile)
            {
                byte[] headerBytes = header.GetBytes();
                for (int x = 0; x < header.HeaderBlockCount; x++)
                {
                    m_queue.WriteRaw(0, headerBytes, headerBytes.Length);
                }
            }
            m_lengthOfCommittedData = (header.LastAllocatedBlock + 1) * (long)header.BlockSize;
            m_writeBuffer.ConfigureAlignment(m_lengthOfCommittedData, pool.PageSize);
        }
Esempio n. 39
0
        private unsafe string TestFile(string fileName)
        {
            ShortTime lastReport          = ShortTime.Now;
            int       errorBlocks         = 0;
            uint      firstBlockWithError = uint.MaxValue;

            try
            {
                using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    int blockSize = FileHeaderBlock.SearchForBlockSize(stream);
                    stream.Position = 0;
                    byte[] data = new byte[blockSize];
                    stream.ReadAll(data, 0, blockSize);
                    var header = FileHeaderBlock.Open(data);

                    fixed(byte *lp = data)
                    {
                        stream.Position = header.HeaderBlockCount * blockSize;

                        uint startingBlock = header.HeaderBlockCount;

                        if (m_shouldQuickScan)
                        {
                            uint blocksToScan = (uint)Math.Ceiling(m_mbToScan * 1024 * 1024 / blockSize);
                            if (blocksToScan < header.LastAllocatedBlock)
                            {
                                startingBlock = Math.Max(header.HeaderBlockCount, header.LastAllocatedBlock - blocksToScan);
                            }
                        }

                        for (uint x = startingBlock; x <= header.LastAllocatedBlock; x++)
                        {
                            long checksum1;
                            int  checksum2;

                            stream.ReadAll(data, 0, blockSize);

                            Footer.ComputeChecksum((IntPtr)lp, out checksum1, out checksum2, blockSize - 16);

                            long checksumInData1 = *(long *)(lp + blockSize - 16);
                            int  checksumInData2 = *(int *)(lp + blockSize - 8);
                            if (!(checksum1 == checksumInData1 && checksum2 == checksumInData2))
                            {
                                firstBlockWithError = Math.Min(firstBlockWithError, x);
                                errorBlocks++;
                            }
                            if (m_quit)
                            {
                                if (errorBlocks == 0)
                                {
                                    return("Quit Early - No Errors Found");
                                }
                                return($"Quit Early - Blocks With Errors {errorBlocks} Starting At {firstBlockWithError}");
                            }
                            if (lastReport.ElapsedSeconds() > .25)
                            {
                                lastReport       = ShortTime.Now;
                                lblProgress.Text = $"Completed {m_filesScanned} of {m_filesToScan} files. Current File: {(stream.Position / (double)stream.Length).ToString("0.0%")}";
                                Application.DoEvents();
                            }
                        }
                    }
                }

                if (errorBlocks == 0)
                {
                    return("No Errors Found");
                }
                return($"Blocks With Errors {errorBlocks} Starting At {firstBlockWithError}");
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
                return("Error");
            }
        }
 private static void CheckEqual(FileHeaderBlock RO, FileHeaderBlock RW)
 {
     if (!AreEqual(RW, RO))
         throw new Exception();
 }
Esempio n. 41
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        /// <remarks>A debug function</remarks>
        internal static bool AreEqual(FileHeaderBlock other, FileHeaderBlock self)
        {
            if (other is null)
            {
                return(false);
            }
            if (self is null)
            {
                return(false);
            }
            if (self.CanWrite != other.CanWrite)
            {
                return(false);
            }
            if (self.CanRead != other.CanRead)
            {
                return(false);
            }
            if (self.ArchiveId != other.ArchiveId)
            {
                return(false);
            }
            if (self.ArchiveType != other.ArchiveType)
            {
                return(false);
            }
            if (self.SnapshotSequenceNumber != other.SnapshotSequenceNumber)
            {
                return(false);
            }
            if (self.LastAllocatedBlock != other.LastAllocatedBlock)
            {
                return(false);
            }
            if (self.FileCount != other.FileCount)
            {
                return(false);
            }

            //compare files.
            if (self.Files is null)
            {
                if (other.Files != null)
                {
                    return(false);
                }
            }
            else
            {
                if (other.Files is null)
                {
                    return(false);
                }
                if (self.Files.Count != other.Files.Count)
                {
                    return(false);
                }
                for (int x = 0; x < self.Files.Count; x++)
                {
                    SubFileHeader subFile      = self.Files[x];
                    SubFileHeader subFileOther = other.Files[x];

                    if (subFile is null)
                    {
                        if (subFileOther != null)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        if (subFileOther is null)
                        {
                            return(false);
                        }
                        if (!SubFileMetaDataTest.AreEqual(subFile, subFileOther))
                        {
                            return(false);
                        }
                    }
                }
            }

            return(self.GetBytes().SequenceEqual(other.GetBytes()));
        }
        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();
        }
 /// <summary>
 /// Creates a <see cref="DiskIoSession"/> that can be used to perform basic read/write functions.
 /// </summary>
 /// <returns></returns>
 public DiskIoSession CreateDiskIoSession(FileHeaderBlock header, SubFileHeader file)
 {
     if (m_disposed)
         throw new ObjectDisposedException(GetType().FullName);
     return new DiskIoSession(this, m_stream.CreateIoSession(), header, file);
 }
        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();
        }
 /// <summary>
 /// Occurs when committing the following data to the disk.
 /// This will copy any pending data to the disk in a manner that
 /// will protect against corruption.
 /// </summary>
 /// <param name="header"></param>
 public void CommitChanges(FileHeaderBlock header)
 {
     header.IsReadOnly = true;
     m_disk.CommitChanges(header);
     Thread.MemoryBarrier();
     m_header = header;
 }
        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();
        }
 /// <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);
     }
 }
 /// <summary>
 /// Class is created through static methods of this class.
 /// </summary>
 /// <param name="disk">the underlying disk medium</param>
 /// <param name="header">the header data to use.</param>
 private DiskMedium(IDiskMediumCoreFunctions disk, FileHeaderBlock header)
 {
     m_header = header;
     m_disk = disk;
     m_blockSize = header.BlockSize;
 }
 /// <summary>
 /// Executes a commit of data. This will flush the data to the disk use the provided header data to properly
 /// execute this function.
 /// </summary>
 /// <param name="headerBlock"></param>
 public void CommitChanges(FileHeaderBlock headerBlock)
 {
     if (IsDisposed)
         throw new ObjectDisposedException("MemoryStream");
 }