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