Example #1
0
        private void Read(uint physicalBlockIndex, uint blockIndex)
        {
            if (m_currentPhysicalBlock == physicalBlockIndex)
            {
                return;
            }

            Flush();

            if (blockIndex >= m_subFile.DataBlockCount)
            {
                uint additionalBlocks = blockIndex - m_subFile.DataBlockCount + 1;
                Memory.Clear(m_memory.Address, m_blockSize);

                m_header.AllocateFreeBlocks(additionalBlocks);
                m_subFile.DataBlockCount += additionalBlocks;
            }
            else
            {
                ReadBlockCount++;
                m_stream.Position = physicalBlockIndex * m_blockSize;
                int bytesRead = m_stream.Read(m_buffer, 0, m_blockSize);
                if (bytesRead < m_buffer.Length)
                {
                    Array.Clear(m_buffer, bytesRead, m_buffer.Length - bytesRead);
                }
                Marshal.Copy(m_buffer, 0, m_memory.Address, m_buffer.Length);
            }

            //I don't need to verify any of the footer data since I've written it all correctly.
            m_currentPhysicalBlock = physicalBlockIndex;
            m_currentBlockIndex    = blockIndex;
        }
        /// <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);
            }
        }