/// <summary>
 /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
 /// </summary>
 /// <filterpriority>2</filterpriority>
 public void Dispose()
 {
     GC.SuppressFinalize(this);
     IsDisposed = true;
     if (SourceData != null)
     {
         SourceData.Dispose();
         SourceData = null;
     }
     if (DestinationData != null)
     {
         DestinationData.Dispose();
         DestinationData = null;
     }
     if (SourceIndex != null)
     {
         SourceIndex.Dispose();
         SourceIndex = null;
     }
     if (DestinationIndex != null)
     {
         DestinationIndex.Dispose();
         DestinationIndex = null;
     }
 }
            /// <summary>
            /// Releases the unmanaged resources used by the <see cref="IoSession"/> object and optionally releases the managed resources.
            /// </summary>
            /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
            protected override void Dispose(bool disposing)
            {
                if (!m_disposed)
                {
                    try
                    {
                        // This will be done regardless of whether the object is finalized or disposed.

                        if (disposing)
                        {
                            if (m_dataIoSession != null)
                            {
                                m_dataIoSession.Dispose();
                                m_dataIoSession = null;
                            }

                            // This will be done only when the object is disposed by calling Dispose().
                        }
                    }
                    finally
                    {
                        m_dataIoSession = null;
                        m_disposed      = true;     // Prevent duplicate dispose.
                        base.Dispose(disposing);    // Call base class Dispose().
                    }
                }
            }
        /// <summary>
        /// Swaps the source and destination Data I/O Sessions
        /// </summary>
        public void SwapData()
        {
            if (IsReadOnly)
            {
                throw new NotSupportedException("Not supported when in read only mode");
            }
            DiskIoSession swap = SourceData;

            SourceData      = DestinationData;
            DestinationData = swap;
        }
        /// <summary>
        /// Swaps the source and destination index I/O Sessions.
        /// </summary>
        public void SwapIndex()
        {
            if (IsReadOnly)
            {
                throw new NotSupportedException("Not supported when in read only mode");
            }
            DiskIoSession swap = SourceIndex;

            SourceIndex      = DestinationIndex;
            DestinationIndex = swap;
        }
 /// <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);
     }
 }
Ejemplo n.º 6
0
        /// <summary>
        /// This uses the (blockIndex,offset) values to determine what the next block index is.
        /// This also has consistency checks to determine if the file is inconsistent (potentially corruption)
        /// </summary>
        /// <param name="blockIndex">the index of the block to read</param>
        /// <param name="offset">the offset inside the block to use to determine the next index block</param>
        /// <param name="blockType">the value 1-4 which tell what indirect block this is</param>
        /// <param name="blockBaseIndex">the lowest virtual address that can be referenced from this indirect block</param>
        /// <returns></returns>
        private uint GetBlockIndexValue(uint blockIndex, int offset, BlockType blockType, uint blockBaseIndex)
        {
            DiskIoSession buffer = m_ioSessions.SourceIndex;

            if (blockIndex == 0)
            {
                return(0);
            }

            //Skip the redundant read if this block is still cached.
            if (!buffer.IsValid || buffer.BlockIndex != blockIndex)
            {
                buffer.Read(blockIndex, blockType, blockBaseIndex);
            }
            return(*(uint *)(buffer.Pointer + (offset << 2)));
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Makes a shadow copy of a data cluster.
 /// </summary>
 /// <param name="sourceClusterAddress">the address of the first block in the cluster.
 /// If address is zero, it simply creates an empty cluster.</param>
 /// <param name="indexValue">the index value of this first block</param>
 /// <param name="destinationClusterAddress">the first block of the destination cluster</param>
 private void ShadowCopyDataCluster(uint sourceClusterAddress, uint indexValue, uint destinationClusterAddress)
 {
     //if source exist
     if (sourceClusterAddress != 0)
     {
         DiskIoSession sourceData      = m_ioSessions.SourceData;
         DiskIoSession destinationData = m_ioSessions.DestinationData;
         sourceData.ReadOld(sourceClusterAddress, BlockType.DataBlock, indexValue);
         destinationData.WriteToNewBlock(destinationClusterAddress, BlockType.DataBlock, indexValue);
         Memory.Copy(sourceData.Pointer, destinationData.Pointer, sourceData.Length);
         m_ioSessions.SwapData();
     }
     //if source cluster does not exist.
     else
     {
         m_ioSessions.SourceData.WriteToNewBlock(destinationClusterAddress, BlockType.DataBlock, indexValue);
         Memory.Clear(m_ioSessions.SourceData.Pointer, m_ioSessions.SourceData.Length);
     }
 }
Ejemplo n.º 8
0
        /// <summary>
        /// Makes a shadow copy of the indirect index passed to this function. If the block does not exists, it creates it.
        /// </summary>
        /// <param name="sourceBlockAddress">The block to be copied</param>
        /// <param name="indexValue">the index value that goes in the footer of the file.</param>
        /// <param name="blockType">Gets the expected block type</param>
        /// <param name="remoteAddressOffset">the offset of the remote address that needs to be updated.</param>
        /// <param name="remoteBlockAddress">the value of the remote address.</param>
        /// <returns>Returns true if the block had to be shadowed, false if it did not change</returns>
        private bool ShadowCopyIndexIndirect(ref uint sourceBlockAddress, uint indexValue, BlockType blockType, int remoteAddressOffset, uint remoteBlockAddress)
        {
            uint indexIndirectBlock;

            //Make a copy of the index block referenced

            //if the block does not exist, create it.
            if (sourceBlockAddress == 0)
            {
                DiskIoSession buffer = m_ioSessions.SourceIndex;
                indexIndirectBlock = m_fileHeaderBlock.AllocateFreeBlocks(1);
                m_subFileHeader.TotalBlockCount++;

                buffer.WriteToNewBlock(indexIndirectBlock, blockType, indexValue);
                Memory.Clear(buffer.Pointer, buffer.Length);
                WriteIndexIndirectBlock(buffer.Pointer, remoteAddressOffset, remoteBlockAddress);

                sourceBlockAddress = indexIndirectBlock;
                return(true);
            }
            //if the data page is an old page, allocate space to create a new copy
            else if (sourceBlockAddress <= m_lastReadOnlyBlock)
            {
                indexIndirectBlock = m_fileHeaderBlock.AllocateFreeBlocks(1);
                m_subFileHeader.TotalBlockCount++;

                ReadThenWriteIndexIndirectBlock(sourceBlockAddress, indexIndirectBlock, indexValue, blockType, remoteAddressOffset, remoteBlockAddress);
                sourceBlockAddress = indexIndirectBlock;
                return(true);
            }
            //The page has already been copied, use the existing address.
            else
            {
                ReadThenWriteIndexIndirectBlock(sourceBlockAddress, sourceBlockAddress, indexValue, blockType, remoteAddressOffset, remoteBlockAddress);
                return(false);
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Makes a shadow copy of an index indirect block and updates a remote address.
        /// </summary>
        /// <param name="sourceBlockAddress">the address of the source.</param>
        /// <param name="destinationBlockAddress">the address of the destination. This can be the same as the source.</param>
        /// <param name="indexValue">the index value that goes in the footer of the file.</param>
        /// <param name="blockType">Gets the expected block type</param>
        /// <param name="remoteAddressOffset">the offset of the remote address that needs to be updated.</param>
        /// <param name="remoteBlockAddress">the value of the remote address.</param>
        private void ReadThenWriteIndexIndirectBlock(uint sourceBlockAddress, uint destinationBlockAddress, uint indexValue, BlockType blockType, int remoteAddressOffset, uint remoteBlockAddress)
        {
            DiskIoSession bufferSource = m_ioSessions.SourceIndex;

            if (sourceBlockAddress == destinationBlockAddress)
            {
                if (*(int *)(bufferSource.Pointer + (remoteAddressOffset << 2)) != remoteBlockAddress)
                {
                    bufferSource.WriteToExistingBlock(destinationBlockAddress, blockType, indexValue);

                    WriteIndexIndirectBlock(bufferSource.Pointer, remoteAddressOffset, remoteBlockAddress);
                }
            }
            else
            {
                bufferSource.ReadOld(sourceBlockAddress, blockType, indexValue);

                DiskIoSession destination = m_ioSessions.DestinationIndex;
                destination.WriteToNewBlock(destinationBlockAddress, blockType, indexValue);
                Memory.Copy(bufferSource.Pointer, destination.Pointer, destination.Length);
                WriteIndexIndirectBlock(destination.Pointer, remoteAddressOffset, remoteBlockAddress);
                m_ioSessions.SwapIndex();
            }
        }
 public SimplifiedIoSession(SubFileStream stream)
 {
     m_stream          = stream;
     m_dataIoSession   = stream.m_dataReader.CreateDiskIoSession(stream.m_fileHeaderBlock, stream.m_subFile);
     m_blockDataLength = m_stream.m_blockSize - FileStructureConstants.BlockFooterLength;
 }