Exemple #1
0
        protected override void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            base.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);

            if (this.replicatedData.Array == null)
            {
                var startingPos = bw.BaseStream.Position;

                // Leave room for size
                bw.BaseStream.Position += sizeof(int);

                // Note that if you change this part, begin checkpoint log record also must be changed.
                bw.Write(this.backupId.ToByteArray());
                bw.Write(this.highestBackedUpEpoch.DataLossNumber);
                bw.Write(this.highestBackedUpEpoch.ConfigurationNumber);
                bw.Write(this.highestBackedUpLsn.LSN);

                bw.Write(this.backupLogRecordCount);
                bw.Write(this.BackupLogSizeInKB);

                var endPosition   = bw.BaseStream.Position;
                var sizeOfSection = checked ((int)(endPosition - startingPos));
                bw.BaseStream.Position = startingPos;
                bw.Write(sizeOfSection);
                bw.BaseStream.Position = endPosition;

                this.replicatedData = CreateArraySegment(startingPos, bw);
            }

            operationData.Add(this.replicatedData);
        }
Exemple #2
0
        protected override void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            base.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);

            if (this.replicatedData.Array == null)
            {
                var startingPos = bw.BaseStream.Position;

                // Leave room for size
                bw.BaseStream.Position += sizeof(int);

                bw.Write(this.lastStableLsn.LSN);

                // Write size at the beginning.
                var endPosition   = bw.BaseStream.Position;
                var sizeOfSection = checked ((int)(endPosition - startingPos));
                bw.BaseStream.Position = startingPos;
                bw.Write(sizeOfSection);
                bw.BaseStream.Position = endPosition;

                this.replicatedData = CreateArraySegment(startingPos, bw);
            }

            operationData.Add(this.replicatedData);
        }
        protected override void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            base.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);

            if (this.replicatedData == null)
            {
                this.replicatedData = new List <ArraySegment <byte> >();

                // Metadata section.
                var startingPos = bw.BaseStream.Position;
                bw.BaseStream.Position += sizeof(int);

                // Metadata fields.
                bw.Write(this.isSingleOperationTransaction);

                // End Metadata section
                var endPosition   = bw.BaseStream.Position;
                var sizeOfSection = checked ((int)(endPosition - startingPos));
                bw.BaseStream.Position = startingPos;
                bw.Write(sizeOfSection);
                bw.BaseStream.Position = endPosition;

                this.replicatedData.Add(CreateArraySegment(startingPos, bw));

                OperationLogRecord.WriteOperationData(this.metaData, bw, ref this.replicatedData);
                OperationLogRecord.WriteOperationData(this.redo, bw, ref this.replicatedData);
                OperationLogRecord.WriteOperationData(this.undo, bw, ref this.replicatedData);
            }

            foreach (var segment in this.replicatedData)
            {
                operationData.Add(segment);
            }
        }
        protected override void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            base.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);
            var startingPos = bw.BaseStream.Position;

            bw.BaseStream.Position += sizeof(int);

            bw.Write(this.lastStableLsn.LSN);
            if (isPhysicalWrite == true)
            {
                if (this.lastCompletedBeginCheckpointRecordOffset == InvalidPhysicalRecordOffset || forceRecomputeOffsets == true)
                {
                    Utility.Assert(
                        this.lastCompletedBeginCheckpointRecord != null || forceRecomputeOffsets,
                        "(this.lastCompletedBeginCheckpointRecord != null)={0} || forceRecomputeOffsets={1}",
                        this.lastCompletedBeginCheckpointRecord != null,
                        forceRecomputeOffsets);

                    if (this.lastCompletedBeginCheckpointRecord != null)
                    {
                        if (this.lastCompletedBeginCheckpointRecord.RecordPosition != InvalidRecordPosition)
                        {
                            Utility.Assert(
                                this.RecordPosition != InvalidPhysicalRecordOffset,
                                "this.RecordPosition != LogRecord.INVALID_RECORD_POSITION");
                            this.lastCompletedBeginCheckpointRecordOffset = this.RecordPosition
                                                                            - this.lastCompletedBeginCheckpointRecord
                                                                            .RecordPosition;
                        }
                        else
                        {
                            this.lastCompletedBeginCheckpointRecordOffset = InvalidPhysicalRecordOffset;
                        }
                    }
                }

                bw.Write(this.lastCompletedBeginCheckpointRecordOffset);
            }

            var endPosition   = bw.BaseStream.Position;
            var sizeOfSection = checked ((int)(endPosition - startingPos));

            bw.BaseStream.Position = startingPos;
            bw.Write(sizeOfSection);
            bw.BaseStream.Position = endPosition;

            operationData.Add(CreateArraySegment(startingPos, bw));
        }
Exemple #5
0
        /// <summary>
        /// Returns the metadata for the copied state.
        /// </summary>
        /// <returns></returns>
        /// <remarks>
        /// Contains
        /// - Version of the copy metadata state.
        /// - Progress ProgressVectorEntry of the copied checkpoint.
        /// - Copied Checkpoints Epoch
        /// - Sequence number of the first operation in the log to be copied.
        /// - Sequence number of the copied checkpoints sequence number.
        /// - UptoSequence number for the copy provided by the volatile replicator.
        /// - Highest possible the state providers could have copied.
        /// </remarks>
        private OperationData GetCopyStateMetadata()
        {
            var expectedSize = this.beginCheckpointRecord.ProgressVector.ByteCount;

            expectedSize += CopyStateMetadataByteSizeNotIncludingProgressVector;

            OperationData result;

            using (var stream = new MemoryStream(expectedSize))
            {
                using (var bw = new BinaryWriter(stream))
                {
                    // First 4 bytes are reserved for the version of the metadata.
                    bw.Write(CopyStateMetadataVersion);

                    // TODO: Ask for the size to avoid expanding the memoryStream.
                    this.beginCheckpointRecord.ProgressVector.Write(bw);

                    var startingEpoch = this.beginCheckpointRecord.Epoch;
                    bw.Write(startingEpoch.DataLossNumber);
                    bw.Write(startingEpoch.ConfigurationNumber);

                    bw.Write(this.sourceStartingLsn.LSN);
                    bw.Write(this.beginCheckpointRecord.Lsn.LSN);
                    bw.Write(this.uptoLsn.LSN);
                    bw.Write(this.replicatedLogManager.CurrentLogTailLsn.LSN);

                    Utility.Assert(
                        expectedSize == stream.Position,
                        "Position mismatch. Expected {0} Position {1}",
                        expectedSize, stream.Position);

                    result = new OperationData(new ArraySegment <byte>(stream.GetBuffer(), 0, (int)stream.Position));
                    result.Add(CopyProgressVectorOperation);
                }
            }

            var trace = "Copying Log Preamble. SourceStartingLSN: " + this.sourceStartingLsn.LSN
                        + " BeginCheckpointLSN: " + this.beginCheckpointRecord.Lsn.LSN + " StateRecordsCoipied: "
                        + this.copiedRecordNumber + " CurrentTailSequenceNumber: "
                        + this.replicatedLogManager.CurrentLogTailLsn.LSN;

            FabricEvents.Events.CopyStreamGetNext(tracer.Type, trace);
            return(result);
        }
Exemple #6
0
        internal static OperationData WriteRecord(
            LogRecord record,
            BinaryWriter bw,
            bool isPhysicalWrite       = true,
            bool setRecordLength       = true,
            bool forceRecomputeOffsets = false)
        {
            // NOTE:- The binary writer is not where the real data is written
            // It is only passed in to avoid each log record from creating its own writer

            // The real data of the log record is returned in the operation data
            // As a result, reset the position of the writer before starting to write

            bw.BaseStream.Position = 0;

            var operationData = new OperationData();

            record.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);
            uint recordLength = 0;

            foreach (var data in operationData)
            {
                recordLength += (uint)data.Count;
            }

            if (setRecordLength)
            {
                record.RecordLength = recordLength;
            }

            var mm = bw.BaseStream as MemoryStream;
            var startingPosition = bw.BaseStream.Position;

            bw.Write(recordLength);
            var arraySegment = new ArraySegment <byte>(
                mm.GetBuffer(),
                (int)startingPosition,
                (int)mm.Position - (int)startingPosition);

            // Append and prepend record length in a fixed encoding of sizeof(int) bytes
            operationData.Add(arraySegment);
            operationData.Insert(0, arraySegment);

            return(operationData);
        }
        internal static OperationData ReadOperationData(BinaryReader br)
        {
            var count = br.ReadInt32();

            if (count == NullOperationDataCode)
            {
                return(null);
            }

            var operationData = new OperationData();

            for (var i = 0; i < count; i++)
            {
                operationData.Add(ReadBytes(br));
            }

            return(operationData);
        }
Exemple #8
0
        protected override void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            base.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);
            var startingPos = bw.BaseStream.Position;

            bw.BaseStream.Position += sizeof(int);

            bw.Write((int)this.informationEvent);

            var endPosition   = bw.BaseStream.Position;
            var sizeOfSection = checked ((int)(endPosition - startingPos));

            bw.BaseStream.Position = startingPos;
            bw.Write(sizeOfSection);
            bw.BaseStream.Position = endPosition;

            operationData.Add(CreateArraySegment(startingPos, bw));
        }
Exemple #9
0
        protected override void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            base.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);
            var startingPosition = bw.BaseStream.Position;

            bw.BaseStream.Position += sizeof(int);

            if (this.linkedPhysicalRecordOffset == InvalidPhysicalRecordOffset || forceRecomputeOffsets == true)
            {
                Utility.Assert(
                    this.linkedPhysicalRecord != null || forceRecomputeOffsets == true,
                    "(this.linkedPhysicalRecord != null)={0}, forceRecomputeOffsets={1}",
                    this.linkedPhysicalRecord != null,
                    forceRecomputeOffsets);

                if (this.linkedPhysicalRecord == null)
                {
                    this.linkedPhysicalRecordOffset = 0;
                }
                else
                {
                    Utility.Assert(
                        this.linkedPhysicalRecord.RecordPosition != InvalidRecordPosition,
                        "this.linkedPhysicalRecord.RecordPosition != LogRecord.INVALID_RECORD_POSITION");
                    Utility.Assert(
                        this.RecordPosition != InvalidRecordPosition,
                        "this.RecordPosition != LogRecord.INVALID_RECORD_POSITION");

                    this.linkedPhysicalRecordOffset = this.RecordPosition - this.linkedPhysicalRecord.RecordPosition;
                }
            }

            bw.Write(this.linkedPhysicalRecordOffset);

            var endPosition   = bw.BaseStream.Position;
            var sizeOfSection = checked ((int)(endPosition - startingPosition));

            bw.BaseStream.Position = startingPosition;
            bw.Write(sizeOfSection);
            bw.BaseStream.Position = endPosition;

            operationData.Add(CreateArraySegment(startingPosition, bw));
            return;
        }
Exemple #10
0
        protected override void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            base.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);
            var startingPosition = bw.BaseStream.Position;

            bw.BaseStream.Position += sizeof(int);

            bw.Write(this.isStable);
            bw.Write(this.periodicTruncationTimeTicks);

            var endPosition   = bw.BaseStream.Position;
            var sizeOfSection = checked ((int)(endPosition - startingPosition));

            bw.BaseStream.Position = startingPosition;
            bw.Write(sizeOfSection);
            bw.BaseStream.Position = endPosition;

            operationData.Add(CreateArraySegment(startingPosition, bw));
        }
        protected override void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            base.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);
            var startingPosition = bw.BaseStream.Position;

            // Metadata Size
            bw.BaseStream.Position += sizeof(int);

            // Future fields

            // End of metadata.
            var endPosition   = bw.BaseStream.Position;
            var sizeOfSection = checked ((int)(endPosition - startingPosition));

            bw.BaseStream.Position = startingPosition;
            bw.Write(sizeOfSection);
            bw.BaseStream.Position = endPosition;

            operationData.Add(CreateArraySegment(startingPosition, bw));
        }
Exemple #12
0
        protected override void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            base.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);
            var startingPos = bw.BaseStream.Position;

            bw.BaseStream.Position += sizeof(int);

            bw.Write(this.logHeadEpoch.DataLossNumber);
            bw.Write(this.logHeadEpoch.ConfigurationNumber);
            bw.Write(this.logHeadLsn.LSN);
            bw.Write(this.logHeadPsn.PSN);

            if (isPhysicalWrite == true)
            {
                if (this.logHeadRecordOffset == InvalidPhysicalRecordOffset || forceRecomputeOffsets == true)
                {
                    Utility.Assert(
                        this.logHeadRecord != null,
                        "this.logHeadRecord != null");
                    Utility.Assert(
                        this.logHeadRecord.RecordPosition != InvalidRecordPosition,
                        "this.logHeadRecord.RecordPosition != LogRecord.INVALID_RECORD_POSITION");
                    Utility.Assert(
                        this.RecordPosition != InvalidRecordPosition,
                        "this.RecordPosition != LogRecord.INVALID_RECORD_POSITION");
                    this.logHeadRecordOffset = this.RecordPosition - this.logHeadRecord.RecordPosition;
                }

                bw.Write(this.logHeadRecordOffset);
            }

            var endPosition   = bw.BaseStream.Position;
            var sizeOfSection = checked ((int)(endPosition - startingPos));

            bw.BaseStream.Position = startingPos;
            bw.Write(sizeOfSection);
            bw.BaseStream.Position = endPosition;

            operationData.Add(CreateArraySegment(startingPos, bw));
            return;
        }
        internal static OperationData ReadOperationData(OperationData operationData, ref int index)
        {
            int count;

            using (var br = new BinaryReader(IncrementIndexAndGetMemoryStreamAt(operationData, ref index)))
            {
                count = br.ReadInt32();
            }

            if (count == NullOperationDataCode)
            {
                return(null);
            }

            var operationData2 = new OperationData();

            for (var i = 0; i < count; i++)
            {
                operationData2.Add(ReadBytes(operationData, ref index));
            }

            return(operationData2);
        }
Exemple #14
0
        protected override void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            base.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);

            var startingPosition = bw.BaseStream.Position;

            bw.BaseStream.Position += sizeof(int);

            bw.Write(this.epoch.DataLossNumber);
            bw.Write(this.epoch.ConfigurationNumber);
            bw.Write(this.primaryReplicaId);
            bw.Write(this.timestamp.ToBinary());

            var endPosition   = bw.BaseStream.Position;
            var sizeOfSection = checked ((int)(endPosition - startingPosition));

            bw.BaseStream.Position = startingPosition;
            bw.Write(sizeOfSection);
            bw.BaseStream.Position = endPosition;

            operationData.Add(CreateArraySegment(startingPosition, bw));

            return;
        }
Exemple #15
0
        private async Task <OperationData> GetNextAsyncSafe(CancellationToken cancellationToken)
        {
            OperationData data;

            if (this.copyStage == CopyStage.CopyMetadata)
            {
                data = await this.copyContext.GetNextAsync(CancellationToken.None).ConfigureAwait(false);

                Utility.Assert(data.Count == 1, "data.Count == 1");

                var bytes = data[0].Array;

                using (var br = new BinaryReader(new MemoryStream(bytes, data[0].Offset, data[0].Count)))
                {
                    this.targetReplicaId      = br.ReadInt64();
                    this.targetProgressVector = new ProgressVector();
                    this.targetProgressVector.Read(br, false);
                    var targetLogHeadDatalossNumber      = br.ReadInt64();
                    var targetLogHeadConfigurationNumber = br.ReadInt64();
                    this.targetLogHeadEpoch = new Epoch(targetLogHeadDatalossNumber, targetLogHeadConfigurationNumber);
                    this.targetLogHeadLsn   = new LogicalSequenceNumber(br.ReadInt64());
                    this.currentTargetLsn   = new LogicalSequenceNumber(br.ReadInt64());
                    this.latestRecoveredAtomicRedoOperationLsn = br.ReadInt64();
                }

                var message =
                    string.Format(
                        CultureInfo.InvariantCulture,
                        "Target Replica Copy Context: {0}" + Environment.NewLine
                        + "     TargetLogHeadEpoch: {1},{2} TargetLogHeadLsn: {3} TargetLogTailEpoch: {4},{5} TargetLogTailLSN: {6}"
                        + Environment.NewLine
                        + "     SourceLogHeadEpoch: {7},{8} SourceLogHeadLsn: {9} SourceLogTailEpoch: {10},{11} SourceLogTailLSN: {12}"
                        + Environment.NewLine + "     Target ProgressVector: {13}" + Environment.NewLine
                        + "     Source ProgressVector: {14}" + Environment.NewLine
                        + "     LastRecoveredAtomicRedoOperationLsn: {15}",
                        this.targetReplicaId,
                        this.targetLogHeadEpoch.DataLossNumber,
                        this.targetLogHeadEpoch.ConfigurationNumber,
                        this.targetLogHeadLsn.LSN,
                        this.targetProgressVector.LastProgressVectorEntry.Epoch.DataLossNumber,
                        this.targetProgressVector.LastProgressVectorEntry.Epoch.ConfigurationNumber,
                        this.currentTargetLsn.LSN,
                        this.replicatedLogManager.CurrentLogHeadRecord.CurrentEpoch.DataLossNumber,
                        this.replicatedLogManager.CurrentLogHeadRecord.CurrentEpoch.ConfigurationNumber,
                        this.replicatedLogManager.CurrentLogHeadRecord.Lsn.LSN,
                        this.replicatedLogManager.CurrentLogTailEpoch.DataLossNumber,
                        this.replicatedLogManager.CurrentLogTailEpoch.ConfigurationNumber,
                        this.replicatedLogManager.CurrentLogTailLsn.LSN,
                        this.targetProgressVector.ToString(Constants.ProgressVectorMaxStringSizeInKb / 2),
                        this.replicatedLogManager.ProgressVector.ToString(Constants.ProgressVectorMaxStringSizeInKb / 2),
                        this.latestRecoveredAtomicRedoOperationLsn);

                FabricEvents.Events.CopyStreamMetadata(tracer.Type, message);

                await this.waitForLogFlushUptoLsn(this.uptoLsn).ConfigureAwait(false);

                CopyMode copyMode;
                await this.checkpointManager.AcquireBackupAndCopyConsistencyLockAsync("Copy").ConfigureAwait(false);

                try
                {
                    copyMode = this.checkpointManager.GetLogRecordsToCopy(
                        this.targetProgressVector,
                        this.targetLogHeadEpoch,
                        this.targetLogHeadLsn,
                        this.currentTargetLsn,
                        this.latestRecoveredAtomicRedoOperationLsn,
                        this.targetReplicaId,
                        out this.sourceStartingLsn,
                        out this.targetStartingLsn,
                        out this.logRecordsToCopy,
                        out this.beginCheckpointRecord);
                }
                finally
                {
                    this.checkpointManager.ReleaseBackupAndCopyConsistencyLock("Copy");
                }

                CopyStage copyStageToWrite;
                if (copyMode == CopyMode.None)
                {
                    this.copyStage   = CopyStage.CopyNone;
                    copyStageToWrite = CopyStage.CopyNone;
                }
                else if (copyMode == CopyMode.Full)
                {
                    this.copyStage       = CopyStage.CopyState;
                    copyStageToWrite     = CopyStage.CopyState;
                    this.copyStateStream = this.stateManager.GetCurrentState();
                }
                else if ((copyMode & CopyMode.FalseProgress) != 0)
                {
                    Utility.Assert(
                        this.sourceStartingLsn <= this.targetStartingLsn,
                        "this.sourceStartingLsn ({0}) <= this.targetStartingLsn ({1})",
                        this.sourceStartingLsn, this.targetStartingLsn);

                    this.copyStage   = CopyStage.CopyFalseProgress;
                    copyStageToWrite = CopyStage.CopyFalseProgress;
                }
                else
                {
                    this.copyStage   = CopyStage.CopyScanToStartingLsn;
                    copyStageToWrite = CopyStage.CopyLog;
                }

                return(this.GetCopyMetadata(copyStageToWrite));
            }

            if (this.copyStage == CopyStage.CopyState)
            {
                data = await this.copyStateStream.GetNextAsync(cancellationToken).ConfigureAwait(false);

                if (data != null)
                {
                    data.Add(CopyStateOperation);

                    FabricEvents.Events.CopyStreamGetNextNoise(
                        tracer.Type,
                        "Copying State Operation: " + this.copiedRecordNumber);

                    ++this.copiedRecordNumber;
                    return(data);
                }

                var disposableCopyStateStream = this.copyStateStream as IDisposable;
                if (disposableCopyStateStream != null)
                {
                    disposableCopyStateStream.Dispose();
                }

                if (this.uptoLsn < beginCheckpointRecord.LastStableLsn)
                {
                    // Ensure we copy records up to the stable LSN of the begin checkpoint record as part of the copy stream
                    // so that the idle can initiate a checkpoint and apply it as part of the copy pump itself

                    // Not doing the above will mean that the idle can get promoted to active even before the checkpoint is completed
                    // uptolsn is inclusive LSN
                    // BUG: RDBug #9269022:Replicator must rename copy log before changing role to active secondary during full builds
                    this.uptoLsn = beginCheckpointRecord.LastStableLsn;

                    var trace = "FullCopy: Copying Logs from " + this.sourceStartingLsn.LSN
                                + " to BC.LastStableLsn: " + beginCheckpointRecord.LastStableLsn.LSN + " as the upto lsn: " + this.uptoLsn + " was smaller than the checkpoint stable lsn";

                    FabricEvents.Events.CopyStreamGetNext(tracer.Type, trace);
                }

                data = this.GetCopyStateMetadata();

                this.copyStage          = CopyStage.CopyLog;
                this.copiedRecordNumber = 0;

                return(data);
            }

            if (this.copyStage == CopyStage.CopyFalseProgress)
            {
                this.copyStage = CopyStage.CopyScanToStartingLsn;

                this.bw.BaseStream.Position = 0;
                this.bw.Write(this.sourceStartingLsn.LSN);
                var stream = this.bw.BaseStream as MemoryStream;
                data = new OperationData(new ArraySegment <byte>(stream.GetBuffer(), 0, (int)stream.Position));
                data.Add(CopyFalseProgressOperation);

                var trace = "Copying False Progress. SourceStartingLSN: " + this.sourceStartingLsn.LSN
                            + " TargetStartingLSN: " + this.targetStartingLsn.LSN;

                FabricEvents.Events.CopyStreamGetNext(tracer.Type, trace);
                return(data);
            }

            LogRecord record;

            if (this.copyStage == CopyStage.CopyScanToStartingLsn)
            {
                var startingLsn = (this.sourceStartingLsn < this.targetStartingLsn)
                    ? this.sourceStartingLsn
                    : this.targetStartingLsn;

                do
                {
                    var hasMoved = await this.logRecordsToCopy.MoveNextAsync(cancellationToken).ConfigureAwait(false);

                    if (hasMoved == false)
                    {
                        goto Finish;
                    }

                    record = this.logRecordsToCopy.Current;
                    Utility.Assert(record.Lsn <= startingLsn, "record.Lsn <= startingLsn");
                } while (record.Lsn < startingLsn);

                // The log stream is positioned at the end of startingLsn at this point. The enumerator Current is pointing to the "startingLsn"
                this.copyStage = CopyStage.CopyLog;
            }

            if (this.copyStage == CopyStage.CopyLog)
            {
                do
                {
                    // This will start copying after the startingLsn record as expected
                    var hasMoved = await this.logRecordsToCopy.MoveNextAsync(cancellationToken).ConfigureAwait(false);

                    if (hasMoved == false)
                    {
                        goto Finish;
                    }

                    record = this.logRecordsToCopy.Current;
                } while (record is PhysicalLogRecord);

                if (record.Lsn > this.uptoLsn)
                {
                    goto Finish;
                }

                var logicalLogRecord = record as LogicalLogRecord;

                Utility.Assert(logicalLogRecord != null, "Must be a logical log record");

                data = logicalLogRecord.ToOperationData(this.bw);
                data.Add(CopyLogOperation);

                var trace = "Copying log record. LogRecordNumber: " + this.copiedRecordNumber + "Record Type: "
                            + record.RecordType + " LSN: " + record.Lsn.LSN;

                FabricEvents.Events.CopyStreamGetNextNoise(tracer.Type, trace);
                ++this.copiedRecordNumber;
                return(data);
            }

Finish:
            if (this.logRecordsToCopy != null)
            {
                this.logRecordsToCopy.Dispose();
            }

            FabricEvents.Events.CopyStreamFinished(tracer.Type, this.copiedRecordNumber);

            return(null);
        }
        protected override void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            base.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);

            var startingPos = bw.BaseStream.Position;

            // Leave room for size
            bw.BaseStream.Position += sizeof(int);

            // By now, all the log records before this begin checkpoint must have been serialized
            if (this.earliestPendingTransactionOffset == LogicalLogRecord.InvalidLogicalRecordOffset || forceRecomputeOffsets == true)
            {
                Utility.Assert(
                    this.earliestPendingTransaction
                    != BeginTransactionOperationLogRecord.InvalidBeginTransactionLogRecord,
                    "Earliest pending transaction is not expected to be invalid");

                if (this.earliestPendingTransaction == null)
                {
                    this.earliestPendingTransactionOffset = 0;
                }
                else
                {
                    this.earliestPendingTransactionOffset = this.RecordPosition
                                                            - this.earliestPendingTransaction.RecordPosition;
                }
            }

            Utility.Assert(this.progressVector != null, "this.progressVector != null");
            this.progressVector.Write(bw);
            bw.Write(this.earliestPendingTransactionOffset);
            Utility.Assert(
                this.epoch != LogicalSequenceNumber.InvalidEpoch,
                "this.copyEpoch != LogicalSequenceNumber.InvalidEpoch");
            bw.Write(this.epoch.DataLossNumber);
            bw.Write(this.epoch.ConfigurationNumber);

            // Write the backup information.
            // Note that if you change this part, backup log record also must be changed.
            Utility.Assert(
                this.highestBackedUpEpoch.DataLossNumber != LogicalSequenceNumber.InvalidLsn.LSN,
                "this.backupLogSize != uint.MaxValue");
            Utility.Assert(
                this.highestBackedUpEpoch.ConfigurationNumber != LogicalSequenceNumber.InvalidLsn.LSN,
                "this.backupLogSize != uint.MaxValue");
            Utility.Assert(
                this.highestBackedUpLsn != LogicalSequenceNumber.InvalidLsn,
                "this.backupLogSize != uint.MaxValue");
            Utility.Assert(this.backupLogRecordCount != uint.MaxValue, "this.backupLogSize != uint.MaxValue");
            Utility.Assert(this.backupLogSize != uint.MaxValue, "this.backupLogSize != uint.MaxValue");

            bw.Write(this.backupId.ToByteArray());
            bw.Write(this.highestBackedUpEpoch.DataLossNumber);
            bw.Write(this.highestBackedUpEpoch.ConfigurationNumber);
            bw.Write(this.highestBackedUpLsn.LSN);

            bw.Write(this.backupLogRecordCount);
            bw.Write(this.backupLogSize);

            bw.Write(this.lastPeriodicCheckpointTimeTicks);
            bw.Write(this.lastPeriodicTruncationTimeTicks);

            var endPosition   = bw.BaseStream.Position;
            var sizeOfSection = checked ((int)(endPosition - startingPos));

            bw.BaseStream.Position = startingPos;
            bw.Write(sizeOfSection);
            bw.BaseStream.Position = endPosition;

            operationData.Add(CreateArraySegment(startingPos, bw));
        }
Exemple #17
0
        protected virtual void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            // NOTE - LogicalData optimization is NOT done here unlike other log records because the lsn is not yet assigned at this point.
            // Logical Metadata section.
            var logicalStartingPosition = bw.BaseStream.Position;

            bw.BaseStream.Position += sizeof(int);

            // Logical Metadata fields
            bw.Write((uint)this.recordType);
            bw.Write(this.lsn.LSN);

            // End Logical Metadata section
            var logicalEndPosition = bw.BaseStream.Position;

            var logicalSizeOfSection = checked ((int)(logicalEndPosition - logicalStartingPosition));

            bw.BaseStream.Position = logicalStartingPosition;
            bw.Write(logicalSizeOfSection);
            bw.BaseStream.Position = logicalEndPosition;

            operationData.Add(CreateArraySegment(logicalStartingPosition, bw));

            if (isPhysicalWrite)
            {
                // Physical Metadata section.
                var physicalStartPosition = bw.BaseStream.Position;
                bw.BaseStream.Position += sizeof(int);

                bw.Write(this.psn.PSN);

                Utility.Assert(
                    this.recordPosition != InvalidRecordPosition,
                    "this.recordPosition != LogRecord.INVALID_RECORD_POSITION");

                if (this.previousPhysicalRecordOffset == InvalidPhysicalRecordOffset)
                {
                    Utility.Assert(
                        this.previousPhysicalRecord != PhysicalLogRecord.InvalidPhysicalLogRecord,
                        "this.previousPhysicalRecord != PhysicalLogRecord.InvalidPhysicalLogRecord");

                    if (this.previousPhysicalRecord == null)
                    {
                        this.previousPhysicalRecordOffset = 0;
                    }
                    else
                    {
                        Utility.Assert(
                            this.previousPhysicalRecord.recordPosition != InvalidRecordPosition,
                            "this.previousPhysicalRecord.recordPosition != LogRecord.INVALID_RECORD_POSITION");

                        Utility.Assert(
                            this.recordPosition != InvalidRecordPosition,
                            "this.recordPosition != LogRecord.INVALID_RECORD_POSITION");

                        this.previousPhysicalRecordOffset = this.recordPosition
                                                            - this.previousPhysicalRecord.recordPosition;
                    }
                }
                else
                {
                    Utility.CodingError(
                        "Record written twice. Record Type:{0} RecordPosition={1}",
                        this.recordType,
                        this.recordPosition);
                }

                bw.Write(this.previousPhysicalRecordOffset);

                // End Logical Metadata section
                var physicalEndPosition   = bw.BaseStream.Position;
                var physicalSizeOfSection = checked ((int)(physicalEndPosition - physicalStartPosition));
                bw.BaseStream.Position = physicalStartPosition;
                bw.Write(physicalSizeOfSection);
                bw.BaseStream.Position = physicalEndPosition;

                operationData.Add(CreateArraySegment(physicalStartPosition, bw));
            }

            return;
        }
        protected override void Write(BinaryWriter bw, OperationData operationData, bool isPhysicalWrite, bool forceRecomputeOffsets)
        {
            base.Write(bw, operationData, isPhysicalWrite, forceRecomputeOffsets);
            var startingPosition = bw.BaseStream.Position;

            if (this.replicatedData.Array == null)
            {
                bw.BaseStream.Position += sizeof(int);

                bw.Write(this.transaction.Id);

                var endPosition   = bw.BaseStream.Position;
                var sizeOfSection = checked ((int)(endPosition - startingPosition));
                bw.BaseStream.Position = startingPosition;
                bw.Write(sizeOfSection);
                bw.BaseStream.Position = endPosition;

                this.replicatedData = CreateArraySegment(startingPosition, bw);
            }

            operationData.Add(this.replicatedData);

            if (isPhysicalWrite)
            {
                // Physical Metadata section.
                var physicalStartPosition = bw.BaseStream.Position;
                bw.BaseStream.Position += sizeof(int);

                startingPosition = bw.BaseStream.Position;

                if (this.parentTransactionRecordOffset == InvalidLogicalRecordOffset || forceRecomputeOffsets == true)
                {
                    Utility.Assert(
                        this.parentTransactionRecord != InvalidLogicalLogRecord || forceRecomputeOffsets == true,
                        "(this.parentTransactionRecord != LogicalLogRecord.InvalidLogicalLogRecord)={0}, forceRecomputeOffsets={1}",
                        this.parentTransactionRecord != InvalidLogicalLogRecord,
                        forceRecomputeOffsets);

                    if (this.parentTransactionRecord == null)
                    {
                        this.parentTransactionRecordOffset = 0;
                    }
                    else
                    {
                        Utility.Assert(
                            this.parentTransactionRecord.RecordPosition != InvalidRecordPosition,
                            "his.parentTransactionRecord.RecordPosition != LogRecord.INVALID_RECORD_POSITION");
                        Utility.Assert(
                            this.RecordPosition != InvalidRecordPosition,
                            "this.RecordPosition != LogRecord.INVALID_RECORD_POSITION");
                        this.parentTransactionRecordOffset = this.RecordPosition
                                                             - this.parentTransactionRecord.RecordPosition;
                    }
                }
                bw.Write(this.parentTransactionRecordOffset);

                // End Physical Metadata section
                var physicalEndPosition   = bw.BaseStream.Position;
                var physicalSizeOfSection = checked ((int)(physicalEndPosition - physicalStartPosition));
                bw.BaseStream.Position = physicalStartPosition;
                bw.Write(physicalSizeOfSection);
                bw.BaseStream.Position = physicalEndPosition;

                operationData.Add(CreateArraySegment(physicalStartPosition, bw));
            }

            return;
        }