/// <summary> /// Rolls back transaction by copying all backed up data bask to master stream and closes the transaction. /// </summary> public void RollbackTransaction() { if (logStreamHeader != null) { if (logStreamHeader.TransactionCompleted) { throw new InvalidOperationException("Can't rollback completed transaction"); } logStream.Position = TransactionLogStreamMetadata.StructureSize; // Copy segments from log stream back to stream for (int i = 0; i < logStreamHeader.SegmentCount; i++) { SegmentMetadata sh = SegmentMetadata.Load(logStream); if (!sh.TransactionId.Equals(logStreamHeader.TransactionId)) { throw new InvalidOperationException("Wrong segment found in transaction log"); } masterStream.Position = sh.Position; CopyData(logStream, sh.Size, masterStream); } // Set back original stream length if (logStreamHeader.StreamLength < masterStream.Length) { masterStream.SetLength(logStreamHeader.StreamLength); } masterStream.Flush(); logStream.SetLength(0); logStream.Flush(); logStreamHeader = null; rollbackNeeded = false; } }
public static SegmentMetadata Load(Stream stream) { BinaryReader reader = new BinaryReader(stream); SegmentMetadata sh = new SegmentMetadata { TransactionId = new Guid(reader.ReadBytes(16)), Position = reader.ReadInt64(), Size = reader.ReadInt32() }; return sh; }
public static SegmentMetadata Load(Stream stream) { BinaryReader reader = new BinaryReader(stream); SegmentMetadata sh = new SegmentMetadata { TransactionId = new Guid(reader.ReadBytes(16)), Position = reader.ReadInt64(), Size = reader.ReadInt32() }; return(sh); }
// Copies a section of data from master stream to the log stream private void BackupData(long location, int size) { logStream.Seek(0, SeekOrigin.End); // Write segment header SegmentMetadata sh = new SegmentMetadata { TransactionId = logStreamHeader.TransactionId, Position = location, Size = size }; long metadataPos = logStream.Position; sh.Save(logStream); // Copy data masterStream.Position = location; int bytesCopied = CopyData(masterStream, size, logStream); // If bytes copied differ from size in header, update the header if (bytesCopied != size) { logStream.Position = metadataPos; sh.Size = bytesCopied; sh.Save(logStream); } logStream.Flush(); // Update log stream header logStreamHeader.SegmentCount++; logStreamHeader.Save(logStream); logStream.Flush(); }