コード例 #1
0
        private void __Test_WriteNewCheckpointAddress__(DurableFileStream.FailedCommitCode failedCommitCode)
        {
            NextTransactionID();

            // clear first block on disk before writing log
            _fsLog.Seek(0, SeekOrigin.Begin); // go to first block
            ClearBuffer();
            _bufferIdx = BLOCK_SIZE;
            FlushBuffer();

            // write log to the first block after clearing
            _fsLog.Seek(0, SeekOrigin.Begin); // go to first block

            WriteLogRecord ckpWriteRecord = new WriteLogRecord();
            ckpWriteRecord.filename = _logPath;
            ckpWriteRecord.blockNo = 1;
            ckpWriteRecord.count = 8;
            ckpWriteRecord.AFIM = BitConverter.GetBytes(_fsLog.Length);

            _LSN = 0;
            long prev_lsn = LogBegin();
            FlushBuffer();

            if (failedCommitCode == DurableFileStream.FailedCommitCode.CHECKPOINT_AFTER_LOG_BEGIN)
                throw new Exception("Failed Commit: Checkpoint After Log Begin");

            prev_lsn = LogWrite(prev_lsn, ckpWriteRecord);
            FlushBuffer();
            long lastLogPos = _fsLog.Position;

            if (failedCommitCode == DurableFileStream.FailedCommitCode.CHECKPOINT_AFTER_LOG_WRITE)
                throw new Exception("Failed Commit: Checkpoint After Log Write");

            _fsLog.Seek(BLOCK_SIZE, SeekOrigin.Begin);
            _fsLog.Write(ckpWriteRecord.AFIM, 0, 8);
            _fsLog.Flush(true);

            if (failedCommitCode == DurableFileStream.FailedCommitCode.CHECKPOINT_AFTER_DISK_WRITE)
                throw new Exception("Failed Commit: Checkpoint After Disk Write");

            _fsLog.Seek(lastLogPos, SeekOrigin.Begin); // go to first block
            prev_lsn = LogEnd(prev_lsn);
            FlushBuffer();

            if (failedCommitCode == DurableFileStream.FailedCommitCode.CHECKPOINT_AFTER_LOG_END)
                throw new Exception("Failed Commit: Checkpoint After Log End");

            _checkpointAddress = _fsLog.Length;

            // reset LSN
            _fsLog.Seek(0, SeekOrigin.End);
            _LSN = _fsLog.Position;
        }
コード例 #2
0
        private void WriteNewCheckpointAddress()
        {
            NextTransactionID();

            // clear first block on disk before writing log
            _fsLog.Seek(0, SeekOrigin.Begin); // go to first block
            ClearBuffer();
            _bufferIdx = 0;
            //_bufferIdx = BLOCK_SIZE;
            //FlushBuffer();

            // write log to the first block after clearing
            _fsLog.Seek(0, SeekOrigin.Begin); // go to first block

            WriteLogRecord ckpWriteRecord = new WriteLogRecord();
            ckpWriteRecord.filename = _logPath;
            ckpWriteRecord.blockNo = 1;
            ckpWriteRecord.count = 8;
            ckpWriteRecord.AFIM = BitConverter.GetBytes(_fsLog.Length);

            _LSN = 0;
            long prev_lsn = LogBegin();
            prev_lsn = LogWrite(prev_lsn, ckpWriteRecord);
            FlushBuffer();
            long lastLogPos = _fsLog.Position;

            // write checkpoint address to log disk
            _fsLog.Seek(CHECKPOINT_POSITION, SeekOrigin.Begin);
            _fsLog.Write(ckpWriteRecord.AFIM, 0, 8);
            _fsLog.Flush(true);

            _fsLog.Seek(lastLogPos, SeekOrigin.Begin); // return to last position
            prev_lsn = LogEnd(prev_lsn);
            FlushBuffer();

            _checkpointAddress = _fsLog.Length;

            // reset LSN
            _fsLog.Seek(0, SeekOrigin.End);
            _LSN = _fsLog.Position;
        }
コード例 #3
0
        private long LogWrite(long prevLSN, WriteLogRecord record)
        {
            long lsn = _LSN;

            byte[] fileNameInBytes = System.Text.Encoding.UTF8.GetBytes(record.filename);
            int filenameLen = fileNameInBytes.Length;

            byte[] recordBytes = new byte[48 + filenameLen + record.count];

            byte[] inBytes = BitConverter.GetBytes(lsn); // LSN: 8 bytes
            Array.Copy(inBytes, 0, recordBytes, 0, 8);

            inBytes = BitConverter.GetBytes(recordBytes.Length); // record Length: 4 bytes
            Array.Copy(inBytes, 0, recordBytes, 8, 4);

            inBytes = BitConverter.GetBytes(prevLSN);  // prevLSN: 8 bytes (equal to lsn)
            Array.Copy(inBytes, 0, recordBytes, 12, 8);

            inBytes = BitConverter.GetBytes(_transactionID); // TransactionID: 4 bytes
            Array.Copy(inBytes, 0, recordBytes, 20, 4);

            inBytes = BitConverter.GetBytes(WRITE_OPERATION); // Operation: 4 bytes
            Array.Copy(inBytes, 0, recordBytes, 24, 4);

            inBytes = BitConverter.GetBytes(filenameLen); // filename length in bytes: 4 bytes
            Array.Copy(inBytes, 0, recordBytes, 28, 4);

            Array.Copy(fileNameInBytes, 0, recordBytes, 32, filenameLen); // filename: inBytes.Length bytes

            int idx = 32 + filenameLen;

            inBytes = BitConverter.GetBytes(record.blockNo); // blockNo: 8 bytes
            Array.Copy(inBytes, 0, recordBytes, idx, 8);
            idx += 8;

            inBytes = BitConverter.GetBytes(record.count); // count: 4 bytes
            Array.Copy(inBytes, 0, recordBytes, idx, 4);
            idx += 4;

            Array.Copy(record.AFIM, 0, recordBytes, idx, record.count); // AFIM: <record.count> bytes
            idx += record.count;

            inBytes = BitConverter.GetBytes(CRC32.Compute(recordBytes, 0, idx)); // CRC32: 4 bytes
            Array.Copy(inBytes, 0, recordBytes, idx, 4);
            idx += 4;

            WriteToBuffer(recordBytes, idx);

            return lsn;
        }
コード例 #4
0
        private LogRecord ParseLogRecord(string expectedFilename)
        {
            long rowPosition = _fsLog.Position;

            if (_fsLog.Read(_recoveryBuffer, 0, 32) != 32) // read first 32 bytes
                return null;

            long lsn = BitConverter.ToInt64(_recoveryBuffer, 0);
            if (lsn != rowPosition)
                return null;

            int recordLength = BitConverter.ToInt32(_recoveryBuffer, 8);
            if (recordLength < 32 || recordLength > 8496)
                return null;

            long prev_lsn = BitConverter.ToInt64(_recoveryBuffer, 12);
            if (prev_lsn > lsn)
                return null;

            int transactionID = BitConverter.ToInt32(_recoveryBuffer, 20);

            int operation = BitConverter.ToInt32(_recoveryBuffer, 24);
            if (operation < 1 || operation > 4)
                return null;

            if (operation == WRITE_OPERATION)
            {
                int filenameLength = BitConverter.ToInt32(_recoveryBuffer, 28);

                if ((filenameLength > 255) || (32 + filenameLength > recordLength))
                    return null;

                if (_fsLog.Read(_recoveryBuffer, 32, recordLength - 32) != recordLength - 32)
                    return null;

                string filename = System.Text.Encoding.UTF8.GetString(_recoveryBuffer, 32, filenameLength);
                int idx = 32 + filenameLength;
                if (filename != expectedFilename)
                    return null;

                if (idx + 12 > recordLength)
                    return null;

                long blockNo = BitConverter.ToInt64(_recoveryBuffer, idx);
                int count = BitConverter.ToInt32(_recoveryBuffer, idx + 8);
                idx += 12;

                if (idx + count + 4 > recordLength)
                    return null;

                byte[] AFIM = new byte[count];
                Array.Copy(_recoveryBuffer, idx, AFIM, 0, count);
                idx += count;

                UInt32 read_crc32 = BitConverter.ToUInt32(_recoveryBuffer, idx);
                UInt32 computed_crc32 = CRC32.Compute(_recoveryBuffer, 0, idx);
                if (read_crc32 != computed_crc32)
                {
                    return null;
                }

                WriteLogRecord writeLogRecord = new WriteLogRecord();
                writeLogRecord.lsn = lsn;
                writeLogRecord.prev_lsn = prev_lsn;
                writeLogRecord.transactionID = transactionID;
                writeLogRecord.operation = operation;
                writeLogRecord.filename = filename;
                writeLogRecord.blockNo = blockNo;
                writeLogRecord.count = count;
                writeLogRecord.AFIM = AFIM;
                return writeLogRecord;
            }
            else
            {
                UInt32 read_crc32 = BitConverter.ToUInt32(_recoveryBuffer, 28);
                UInt32 computed_crc32 = CRC32.Compute(_recoveryBuffer, 0, 28);
                if (read_crc32 != computed_crc32)
                {
                    return null;
                }

                LogRecord logRecord = new LogRecord();
                logRecord.lsn = lsn;
                logRecord.prev_lsn = prev_lsn;
                logRecord.transactionID = transactionID;
                logRecord.operation = operation;
                return logRecord;
            }
        }
コード例 #5
0
 public void LogWrite(string path, long blockNo, int count, byte[] AFIM)
 {
     WriteLogRecord writeLogRecord;
     if (_writeLogRecordDict.TryGetValue(blockNo, out writeLogRecord))
     {
         writeLogRecord.AFIM = AFIM;
         if (count > writeLogRecord.count)
             writeLogRecord.count = count;
     }
     else
     {
         writeLogRecord = new WriteLogRecord();
         writeLogRecord.filename = path;
         writeLogRecord.blockNo = blockNo;
         writeLogRecord.count = count;
         writeLogRecord.AFIM = AFIM;
         _writeLogRecordDict.Add(blockNo, writeLogRecord);
     }
 }