예제 #1
0
        /// <summary>
        /// Gets a log reader capable of reading records between the specified positions
        /// </summary>
        internal PhysicalLogReader GetPhysicalLogReader(
            ulong startingRecordPosition,
            ulong endingRecordPosition,
            long startingLsn,
            string readerName,
            LogReaderType readerType)
        {
            PhysicalLogReader logReader;

            do
            {
                logReader = new PhysicalLogReader(
                    this,
                    startingRecordPosition,
                    endingRecordPosition,
                    startingLsn,
                    readerName,
                    readerType);
                if (logReader.IsValid)
                {
                    break;
                }

                logReader.Dispose();
            } while (true);

            return(logReader);
        }
예제 #2
0
 public void DisposeRecoveryReadStreamIfNeeded()
 {
     if (this.RecoveryLogsReader != null)
     {
         this.RecoveryLogsReader.Dispose();
         this.RecoveryLogsReader = null;
     }
 }
예제 #3
0
        public TruncateTailManager(
            ReplicatedLogManager replicatedLogManager,
            TransactionMap transactionsMap,
            IStateManager stateManager,
            IBackupManager backupManager,
            LogicalSequenceNumber tailLsn,
            ApplyContext falseProgressApplyContext,
            PhysicalLogReader recoveryLogsReader,
            ITracer tracer)
        {
            Utility.Assert(tracer != null, "{0} TruncateTailManager: Input tracer cannot be null");
            Utility.Assert(backupManager != null, "{0} TruncateTailManager: Input backupManager cannot be null", tracer.Type);

            this.replicatedLogManager = replicatedLogManager;
            this.recoveryLogsReader   = recoveryLogsReader;
            this.transactionsMap      = transactionsMap;
            this.stateManager         = stateManager;
            this.backupManager        = backupManager;
            this.tracer  = tracer;
            this.tailLsn = tailLsn;
            this.falseProgressApplyContext = falseProgressApplyContext;
        }
예제 #4
0
        public async Task <RecoveryInformation> OpenAsync(
            ReplicaOpenMode openMode,
            TransactionalReplicatorSettings replicatorSettings,
            ITracer tracer,
            LogManager logManager,
            bool shouldLocalStateBeRemoved,
            PhysicalLogReader recoveryReader,
            bool isRestoring)
        {
            this.RecoveryLogsReader = recoveryReader;
            this.tracer             = tracer;

            PhysicalLogRecord           recoveredLinkedPhysicalRecord;
            TruncateHeadLogRecord       recoveredLastTruncateHeadLogRecord = null;
            CompleteCheckpointLogRecord recoveredCompleteCheckpointRecord  = null;

            this.logCompleteCheckpointAfterRecovery = true;

            this.tailRecordAtStart = await this.RecoveryLogsReader.SeekToLastRecord().ConfigureAwait(false);

            var logUsage = logManager.Length;
            var trace    = "OpenAsync: Log Usage: " + logUsage + " Recovered Replica Tail Record Type: "
                           + tailRecordAtStart.RecordType + " LSN: " + tailRecordAtStart.Lsn.LSN + " PSN: "
                           + tailRecordAtStart.Psn.PSN + " Position: " + tailRecordAtStart.RecordPosition;

            FabricEvents.Events.Api(tracer.Type, trace);

            var lastPhysicalRecord = tailRecordAtStart as PhysicalLogRecord;

            if (lastPhysicalRecord == null)
            {
                lastPhysicalRecord = await this.RecoveryLogsReader.GetPreviousPhysicalRecord(tailRecordAtStart).ConfigureAwait(false);
            }

            trace = "OpenAsync: Recovered last physical record Type: " + lastPhysicalRecord.RecordType + " LSN: "
                    + lastPhysicalRecord.Lsn.LSN + " PSN: " + lastPhysicalRecord.Psn.PSN + " Position: "
                    + lastPhysicalRecord.RecordPosition;

            FabricEvents.Events.Api(tracer.Type, trace);

            if (lastPhysicalRecord.RecordType == LogRecordType.Information)
            {
                var removingStateRecord = lastPhysicalRecord as InformationLogRecord;
                if (removingStateRecord.InformationEvent == InformationEvent.RemovingState)
                {
                    Utility.Assert(
                        lastPhysicalRecord == tailRecordAtStart,
                        "Last Physical Record {0} should be same as tail record at start {1}",
                        lastPhysicalRecord, tailRecordAtStart);

                    FabricEvents.Events.Api(tracer.Type, "OpenAsync: Skipping Recovery due to pending RemovingState");

                    this.IsRemovingStateAfterOpen = true;

                    return(new RecoveryInformation(shouldLocalStateBeRemoved));
                }
            }

            if (lastPhysicalRecord.RecordType == LogRecordType.TruncateHead)
            {
                recoveredLastTruncateHeadLogRecord = lastPhysicalRecord as TruncateHeadLogRecord;
            }
            else if (lastPhysicalRecord.RecordType == LogRecordType.EndCheckpoint)
            {
                this.RecoveredLastEndCheckpointRecord = lastPhysicalRecord as EndCheckpointLogRecord;
            }
            else if (lastPhysicalRecord.RecordType == LogRecordType.CompleteCheckpoint)
            {
                recoveredCompleteCheckpointRecord = lastPhysicalRecord as CompleteCheckpointLogRecord;
            }
            else
            {
                recoveredLinkedPhysicalRecord = await this.RecoveryLogsReader.GetLinkedPhysicalRecord(lastPhysicalRecord).ConfigureAwait(false);

                Utility.Assert(
                    (recoveredLinkedPhysicalRecord != null) &&
                    ((recoveredLinkedPhysicalRecord.RecordType == LogRecordType.TruncateHead) ||
                     (recoveredLinkedPhysicalRecord.RecordType == LogRecordType.EndCheckpoint) ||
                     (recoveredLinkedPhysicalRecord.RecordType == LogRecordType.CompleteCheckpoint)),
                    "Record type should be truncate head or end checkpoint or complete checkpoint. Record type is : {0}",
                    recoveredLinkedPhysicalRecord.RecordType);

                trace = "OpenAsync: RecoveredLinkedPhysicalRecord: " + recoveredLinkedPhysicalRecord.RecordType
                        + " LSN: " + recoveredLinkedPhysicalRecord.Lsn.LSN + " PSN: "
                        + recoveredLinkedPhysicalRecord.Psn.PSN + " Position: "
                        + recoveredLinkedPhysicalRecord.RecordPosition;

                FabricEvents.Events.Api(tracer.Type, trace);

                if (recoveredLinkedPhysicalRecord.RecordType == LogRecordType.TruncateHead)
                {
                    recoveredLastTruncateHeadLogRecord = recoveredLinkedPhysicalRecord as TruncateHeadLogRecord;
                }
                else if (recoveredLinkedPhysicalRecord.RecordType == LogRecordType.EndCheckpoint)
                {
                    this.RecoveredLastEndCheckpointRecord = recoveredLinkedPhysicalRecord as EndCheckpointLogRecord;
                }
                else
                {
                    recoveredCompleteCheckpointRecord = recoveredLinkedPhysicalRecord as CompleteCheckpointLogRecord;
                }
            }

            ulong logHeadPosition = 0;
            long  logHeadLsn      = 0;

            if (recoveredLastTruncateHeadLogRecord != null)
            {
                logHeadPosition = recoveredLastTruncateHeadLogRecord.LogHeadRecordPosition;
                logHeadLsn      = recoveredLastTruncateHeadLogRecord.LogHeadLsn.LSN;
                trace           = "OpenAsync: Recovered last truncate head record Type: "
                                  + recoveredLastTruncateHeadLogRecord.RecordType + " LSN: "
                                  + recoveredLastTruncateHeadLogRecord.Lsn.LSN + " PSN: "
                                  + recoveredLastTruncateHeadLogRecord.Psn.PSN + " Position: "
                                  + recoveredLastTruncateHeadLogRecord.RecordPosition + " LogHeadLSN: "
                                  + recoveredLastTruncateHeadLogRecord.LogHeadLsn.LSN + " LogHeadPosition: "
                                  + recoveredLastTruncateHeadLogRecord.LogHeadRecordPosition;

                FabricEvents.Events.Api(tracer.Type, trace);

                recoveredLinkedPhysicalRecord = recoveredLastTruncateHeadLogRecord;
                do
                {
                    recoveredLinkedPhysicalRecord = await this.RecoveryLogsReader.GetLinkedPhysicalRecord(recoveredLinkedPhysicalRecord).ConfigureAwait(false);

                    Utility.Assert(
                        (recoveredLinkedPhysicalRecord != null) &&
                        ((recoveredLinkedPhysicalRecord.RecordType == LogRecordType.TruncateHead) ||
                         (recoveredLinkedPhysicalRecord.RecordType == LogRecordType.EndCheckpoint) ||
                         (recoveredLinkedPhysicalRecord.RecordType == LogRecordType.CompleteCheckpoint)),
                        "Record type should be truncate head or end checkpoint or complete checkpoint. Record type is : {0}",
                        recoveredLinkedPhysicalRecord.RecordType);

                    this.RecoveredLastEndCheckpointRecord = recoveredLinkedPhysicalRecord as EndCheckpointLogRecord;

                    if (recoveredLinkedPhysicalRecord.RecordType == LogRecordType.CompleteCheckpoint)
                    {
                        recoveredCompleteCheckpointRecord = recoveredLinkedPhysicalRecord as CompleteCheckpointLogRecord;
                    }
                } while (this.RecoveredLastEndCheckpointRecord == null);
            }
            else if (recoveredCompleteCheckpointRecord != null)
            {
                logHeadPosition = recoveredCompleteCheckpointRecord.LogHeadRecordPosition;
                logHeadLsn      = recoveredCompleteCheckpointRecord.LogHeadLsn.LSN;

                trace = "OpenAsync: Recovered last complete checkpoint record Type: "
                        + recoveredCompleteCheckpointRecord.RecordType + " LSN: "
                        + recoveredCompleteCheckpointRecord.Lsn.LSN + " PSN: "
                        + recoveredCompleteCheckpointRecord.Psn.PSN + " Position: "
                        + recoveredCompleteCheckpointRecord.RecordPosition + " LogHeadLsn: "
                        + recoveredCompleteCheckpointRecord.LogHeadLsn.LSN + " LogHeadPosition: "
                        + recoveredCompleteCheckpointRecord.LogHeadRecordPosition;

                FabricEvents.Events.Api(tracer.Type, trace);
                recoveredLinkedPhysicalRecord = recoveredCompleteCheckpointRecord;

                do
                {
                    recoveredLinkedPhysicalRecord = await this.RecoveryLogsReader.GetLinkedPhysicalRecord(recoveredLinkedPhysicalRecord).ConfigureAwait(false);

                    Utility.Assert(
                        (recoveredLinkedPhysicalRecord != null) &&
                        ((recoveredLinkedPhysicalRecord.RecordType == LogRecordType.TruncateHead) ||
                         (recoveredLinkedPhysicalRecord.RecordType == LogRecordType.EndCheckpoint) ||
                         (recoveredLinkedPhysicalRecord.RecordType == LogRecordType.CompleteCheckpoint)),
                        "Record type should be truncate head or end checkpoint or complete checkpoint. Record type is : {0}",
                        recoveredLinkedPhysicalRecord.RecordType);

                    this.RecoveredLastEndCheckpointRecord = recoveredLinkedPhysicalRecord as EndCheckpointLogRecord;
                } while (this.RecoveredLastEndCheckpointRecord == null);
            }
            else
            {
                logHeadPosition = this.RecoveredLastEndCheckpointRecord.LogHeadRecordPosition;
                logHeadLsn      = this.RecoveredLastEndCheckpointRecord.LogHeadLsn.LSN;
            }

            trace = "OpenAsync: Recovered last end checkpoint record Type: "
                    + this.RecoveredLastEndCheckpointRecord.RecordType + " LSN: " + this.RecoveredLastEndCheckpointRecord.Lsn.LSN
                    + " PSN: " + this.RecoveredLastEndCheckpointRecord.Psn.PSN + " Position: "
                    + this.RecoveredLastEndCheckpointRecord.RecordPosition + " LogHeadLSN: "
                    + this.RecoveredLastEndCheckpointRecord.LogHeadLsn.LSN + " LogHeadPosition: "
                    + this.RecoveredLastEndCheckpointRecord.LogHeadRecordPosition;

            FabricEvents.Events.Api(tracer.Type, trace);
            if (recoveredCompleteCheckpointRecord != null)
            {
                this.logCompleteCheckpointAfterRecovery = false;

                // This is fine since both the begin and end records guarantee all the SP's have been renamed
                trace = "OpenAsync: " + " LogHeadPosition: " + this.RecoveredLastEndCheckpointRecord.LogHeadRecordPosition
                        + Environment.NewLine + " LogHeadLSN: " + this.RecoveredLastEndCheckpointRecord.LogHeadLsn.LSN
                        + Environment.NewLine + "           CompleteCheckpoint record found with LSN: "
                        + recoveredCompleteCheckpointRecord.Lsn.LSN + " PSN: "
                        + recoveredCompleteCheckpointRecord.Psn.PSN + " Position: "
                        + recoveredCompleteCheckpointRecord.RecordPosition;

                FabricEvents.Events.Api(tracer.Type, trace);
            }
            else
            {
                this.logCompleteCheckpointAfterRecovery = true;

                trace = "OpenAsync: " + " LogHeadPosition: " + this.RecoveredLastEndCheckpointRecord.LogHeadRecordPosition
                        + Environment.NewLine + " LogHeadLSN: " + this.RecoveredLastEndCheckpointRecord.LogHeadLsn.LSN
                        + Environment.NewLine + "           CompleteCheckpoint record missing";

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

            // For restore cases, logHeadPosition must be 0.
            if (isRestoring == true)
            {
                Utility.Assert(
                    logHeadPosition == 0,
                    "Full backup: LogHead Position ({0}) must be 0",
                    logHeadPosition);
            }

            this.RecoveryLogsReader.MoveStartingRecordPosition(
                logHeadLsn,
                logHeadPosition,
                "recovery",
                LogManager.LogReaderType.Recovery);

            logManager.SetLogHeadRecordPosition(logHeadPosition);

            return(new RecoveryInformation(
                       this.logCompleteCheckpointAfterRecovery,
                       shouldLocalStateBeRemoved));
        }