private IEnumerable <BackupItemReference> GetReverseBackupSequence( DateTime?minBackupEndTime, DateTime?restoreTargetTime, SupportedBackupType backupType) { var reverseFileSequence = BackupFileCatalog.GetReverseBackupSequence(restoreTargetTime, backupType); return(GetReverseBackupSequence(minBackupEndTime, restoreTargetTime, reverseFileSequence)); }
/// <summary> /// Constructor of immutable instance. /// </summary> /// <param name="backupType"> /// Type of backups contained in this file. /// </param> /// <param name="startTime"> /// Explicitly defined start of the period in which backups were written into the file. If null, the start time will be taken from creation time. /// </param> /// <param name="endTime"> /// Explicitly defined end of the period in which backups were written into the file. /// </param> /// <param name="fileInfo"> /// </param> /// <remarks> /// Note that <see cref="StartTime"/> will always have a value while <see cref="EndTime"/> may be null. This is because start time is more important and /// must be figured out in any case while EndTime is not essential and only beneficial for optimization. /// If simultaneous log and database backups are allowed, without end time we only need to start from first log prior to last database backup. /// However, if there is no simultaneous backup, things are much easier and we can work without end time. /// What happens if diff backup is marked with the hour when it is made and single daily log backup is marked with start of day timestamp? /// Then we need end time or have to start from first log backup file prior to the database backup. /// </remarks> public BackupFileInfo(SupportedBackupType backupType, DateTime?startTime, DateTime?endTime, FileInfo fileInfo) { Check.DoRequireArgumentNotNull(fileInfo, "fileInfo"); Check.DoCheckArgument(backupType != SupportedBackupType.None, "Invalid file type"); BackupType = backupType; FileInfo = fileInfo; PeriodStartDeclaredExplicitly = startTime.HasValue; StartTime = startTime ?? fileInfo.CreationTime; PeriodEndDeclaredExplicitly = endTime.HasValue; EndTime = endTime ?? fileInfo.LastWriteTime; }
/// <summary> /// Add new backup type mapping. /// </summary> /// <param name="nameSuffix"> /// Suffix of backup files, including extension, case insensitive /// </param> /// <param name="backupType"> /// Backup type /// </param> /// <param name="timePeriodExtractor"> /// Object implementing extraction of relevant information from file name, such as time period. /// </param> public void AddType(string nameSuffix, SupportedBackupType backupType, ITimePeriodFromFilesystemNameExtractor timePeriodExtractor) { Check.DoRequireArgumentNotNull(nameSuffix, "nameSuffix"); Check.DoRequireArgumentNotNull(timePeriodExtractor, "timePeriodExtractor"); Check.DoCheckArgument(null == GetTypeInfo(backupType), string.Format("Parser for {0} already mapped", backupType)); Check.DoCheckArgument(backupType != SupportedBackupType.None, "Invalid backup type (None)"); var intersectedType = _backupTypes.Values.Where( i => i.FileNameSuffix.EndsWith(nameSuffix, StringComparison.InvariantCultureIgnoreCase) || nameSuffix.EndsWith(i.FileNameSuffix, StringComparison.InvariantCultureIgnoreCase)) .FirstOrDefault(); Check.DoCheckArgument( intersectedType == null , () => string.Format("Suffix {0} for {1} conflicts with suffix {2} for type {3}" , nameSuffix, backupType, intersectedType.FileNameSuffix, intersectedType.BackupType)); var newTypeInfo = new BackupTypeInfo() { FileNameSuffix = nameSuffix, BackupType = backupType, TimePeriodExtractor = timePeriodExtractor }; _backupTypes.Add(backupType, newTypeInfo); }
/// <summary> /// Get reverse sequence of backup files which started before <paramref name="pointInTime"/>. /// </summary> /// <param name="pointInTime"> /// Point in time before which the database backup to be found must have started; null for latest. /// </param> /// <param name="backupType"> /// Type of backup files to find. /// </param> /// <returns> /// Sequence ordered by file start time <see cref="BackupFileInfo.StartTime"/> descending. /// </returns> /// <remarks> /// Note that database backup (diff or full) restores database to a point at which reading from data files while performing backup finished, /// which is in general some time after the backup start time. Thus in order to restore precisely to a point in time within the time period when /// database backup Bn was being performed, one must go back and restore previous database backup followed by log backups up to and including /// the one taken after the Bn backup. This is the reason to expose this method rather than provide just a method to retrieve the sequence /// of files to use for restoration. One must analyze the contents of the database backup (diff or full) in order to understand whether /// one can restore to a point in time within that file's time period. If not suitable, one must go back and check previous backup. /// Passing <see cref="BackupFileInfo.StartTime"/> the caller shall never get the same file back; thus it is possible to iterate backwards. /// </remarks> public IEnumerable <BackupFileInfo> GetReverseBackupSequence(DateTime?pointInTime, SupportedBackupType backupType) { Check.DoCheckArgument(backupType != SupportedBackupType.None); foreach (var folder in GetPriorFolderSequence(pointInTime)) { var files = folder.AllFiles .Where(f => f.BackupType == backupType) .Where(f => !pointInTime.HasValue || f.StartTime < pointInTime.Value) .OrderByDescending(f => f.StartTime); foreach (var file in files) { yield return(file); } } }
private BackupTypeInfo GetTypeInfo(SupportedBackupType backupType) { _backupTypes.TryGetValue(backupType, out var result); return(result); }