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