// Copies a section of data from master stream to the log stream 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(); }
/// <summary> /// Start transaction /// </summary> /// <param name="initialSegments">Areas in master stream which don't require backing up. Can be null.</param> public Guid BeginTransaction(IEnumerable <Segment> initialSegments = null) { CheckState(); if (logStream == null) { throw new InvalidOperationException("Log stream not specified"); } if (logStreamHeader != null) { throw new InvalidOperationException("Unable to start new transaction while existing transaction is in progress"); } // Add custom segments that will not be backed up segments.Clear(); if (initialSegments != null) { // <源码修改> //IOrderedEnumerable<Segment> orderedList = initialSegments.OrderBy(x => x.Location); var orderedList = new List <Segment>(initialSegments); orderedList.Sort(SegmentComparer.Instance); // </源码修改> foreach (var segment in orderedList) { segments.AddLast(segment); } } // Add unallocated space after the end of stream segments.AddLast(new Segment(masterStream.Length, long.MaxValue - masterStream.Length)); CheckSegments(); // Truncate transaction log logStream.SetLength(0); logStream.Flush(); // Initialize transaction log logStreamHeader = new TransactionLogStreamMetadata { TransactionId = Guid.NewGuid(), StreamLength = masterStream.Length, SegmentCount = 0, TransactionCompleted = false }; logStreamHeader.Save(logStream); logStream.Flush(); return(logStreamHeader.TransactionId); }