/// <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); } }
/// <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))); }
/// <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); } }
/// <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); } }
/// <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; }