/// <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); }
public void DisposeRecoveryReadStreamIfNeeded() { if (this.RecoveryLogsReader != null) { this.RecoveryLogsReader.Dispose(); this.RecoveryLogsReader = null; } }
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; }
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)); }