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