コード例 #1
0
        public LfsRecord WriteRecord(int clientIndex, LfsRecordType recordType, ulong clientPreviousLsn, ulong clientUndoNextLsn, uint transactionId, byte[] clientData, bool flushToDisk)
        {
            if (m_restartPage == null)
            {
                m_restartPage = ReadRestartPage();
            }

            // It's perfectly valid to clear the CleanDismount flag after writing the transfer.
            // Note that CurrentLsn is used to determine which is restart page recent so we should not update the restart page without incrementing CurrentLsn first.

            ushort clientSeqNumber = m_restartPage.RestartArea.LogClientArray[clientIndex].SeqNumber;

            LfsRecord record = new LfsRecord();

            record.ClientSeqNumber   = clientSeqNumber;
            record.ClientIndex       = (ushort)clientIndex;
            record.RecordType        = recordType;
            record.ClientPreviousLsn = clientPreviousLsn;
            record.ClientUndoNextLsn = clientUndoNextLsn;
            record.TransactionId     = transactionId;
            record.ClientDataLength  = (uint)clientData.Length;
            record.Data    = clientData;
            record.ThisLsn = GetNextLsn();
            m_recordsPendingWrite.Add(record);
            bool endOfTransferRecorded = false;

            if (flushToDisk)
            {
                FlushRecords(m_recordsPendingWrite, out endOfTransferRecorded);
                m_recordsPendingWrite.Clear();
            }

            // Update CurrentLsn / LastLsnDataLength
            m_restartPage.RestartArea.CurrentLsn        = record.ThisLsn;
            m_restartPage.RestartArea.LastLsnDataLength = (uint)record.Data.Length;

            // If the client is writing a ClientRestart, the call to write a restart page (when updating the client record) is imminent, so no need to write a restart page now.
            // Note that CurrentLsn is used to determine which restart page is more recent so we should not update the restart page without incrementing CurrentLsn.
            if (recordType != LfsRecordType.ClientRestart && endOfTransferRecorded)
            {
                // When the NTFS v5.1 driver restarts a dirty log file, it does not expect to find more than one transfer after the last flushed LSN.
                // If more than one transfer is encountered, it is treated as a fatal error and the driver will report STATUS_DISK_CORRUPT_ERROR.
                // Updating the CurrentLsn / LastLsnDataLength in the restart area will make the NTFS driver see the next page we write as the only transfer after the flushed LSN.
                WriteRestartPage(false);
            }
            return(record);
        }
コード例 #2
0
 public LfsRecord(byte[] buffer, int offset)
 {
     ThisLsn           = LittleEndianConverter.ToUInt64(buffer, offset + 0x00);
     ClientPreviousLsn = LittleEndianConverter.ToUInt64(buffer, offset + 0x08);
     ClientUndoNextLsn = LittleEndianConverter.ToUInt64(buffer, offset + 0x10);
     ClientDataLength  = LittleEndianConverter.ToUInt32(buffer, offset + 0x18);
     ClientSeqNumber   = LittleEndianConverter.ToUInt16(buffer, offset + 0x1C);
     ClientIndex       = LittleEndianConverter.ToUInt16(buffer, offset + 0x1E);
     RecordType        = (LfsRecordType)LittleEndianConverter.ToUInt32(buffer, offset + 0x20);
     TransactionId     = LittleEndianConverter.ToUInt32(buffer, offset + 0x24);
     Flags             = (LfsRecordFlags)LittleEndianConverter.ToUInt16(buffer, offset + 0x28);
     if (IsMultiPageRecord)
     {
         Data = ByteReader.ReadBytes(buffer, offset + HeaderLength, buffer.Length - (offset + HeaderLength));
     }
     else
     {
         Data = ByteReader.ReadBytes(buffer, offset + HeaderLength, (int)ClientDataLength);
     }
 }
コード例 #3
0
ファイル: LogFile.cs プロジェクト: zwj4031/iSCSIConsole
        public LfsRecord WriteRecord(int clientIndex, LfsRecordType recordType, ulong clientPreviousLsn, ulong clientUndoNextLsn, uint transactionId, byte[] clientData)
        {
            if (m_restartPage == null)
            {
                m_restartPage = ReadRestartPage();
            }

            if (m_restartPage.LogRestartArea.IsClean)
            {
                // We should clear the CleanDismount flag before making changes to the log file
                WriteRestartPage(false);
            }

            ushort clientSeqNumber = m_restartPage.LogRestartArea.LogClientArray[clientIndex].SeqNumber;

            LfsRecord record = new LfsRecord();

            record.ClientSeqNumber   = clientSeqNumber;
            record.ClientIndex       = (ushort)clientIndex;
            record.RecordType        = recordType;
            record.ClientPreviousLsn = clientPreviousLsn;
            record.ClientUndoNextLsn = clientUndoNextLsn;
            record.TransactionId     = transactionId;
            record.ClientDataLength  = (uint)clientData.Length;
            record.Data    = clientData;
            record.ThisLsn = GetNextLsn();
            WriteRecord(record);

            // Update CurrentLsn / LastLsnDataLength
            m_restartPage.LogRestartArea.CurrentLsn        = record.ThisLsn;
            m_restartPage.LogRestartArea.LastLsnDataLength = (uint)record.Data.Length;
            if (record.IsMultiPageRecord)
            {
                // We can optimize by only writing the restart page if we already had one transfer after the last flushed LSN.
                WriteRestartPage(false);
            }
            return(record);
        }