/// <summary> /// Verified sequence of backup items to restore to achieve configured outcome. /// Never returns null. /// </summary> /// <param name="lastDatabaseBackupItem"></param> /// <returns></returns> private List <BackupItem> GetLogBackupItems(BackupItem lastDatabaseBackupItem, DateTime?targetTime) { Check.DoRequireArgumentNotNull(lastDatabaseBackupItem, "lastDatabaseBackupItem"); var result = new List <BackupItem>(1000); var logFiles = BackupFileCatalog.GetLogBackupsSequence(lastDatabaseBackupItem.BackupStartTime); // need only first log backup after target time; flag indicates that file is already processed var targetReached = false; var fileIterator = logFiles.GetEnumerator(); var lastBackupItem = lastDatabaseBackupItem; while (!targetReached && fileIterator.MoveNext()) { var header = ParseBackupHeader(fileIterator.Current.FileInfo); if (header != null) { var itemIterator = header.ValidItems.GetEnumerator(); while (!targetReached && itemIterator.MoveNext()) { var item = itemIterator.Current; Check.DoAssertLambda(CheckSequence(lastBackupItem, item, false), () => $"Item #{item.Position} in file {item.FileInfo.Name} cannot be applied after item #{lastBackupItem.Position} in" + $" file {lastBackupItem.FileInfo.Name}"); lastBackupItem = item; result.Add(item); targetReached = (targetTime.HasValue && item.BackupStartTime > targetTime.Value); } } } return(result); }
private string PickNewFileName(string fullFilePath) { var name = Path.GetFileName(fullFilePath); var dir = Path.GetDirectoryName(fullFilePath); var nameWithoutExtension = Path.GetFileNameWithoutExtension(name); var extension = Path.GetExtension(name); var result = fullFilePath; // limiting number of tries to 100; there shouldn't be hundreds of files there for (var n = 1; File.Exists(result) && n < 100; ++n) { var newName = Regex.Replace(nameWithoutExtension, @"(?<=([\D]+|^))\d*$", n.ToString()); // not using Path.ChangeExtension because name can contain '.' and the extension would replace part of the file name result = Path.Combine(dir, string.Format("{0}{1}", newName, extension)); } Check.DoAssertLambda(!File.Exists(result), () => $"Failed to pick nonexistent file name for {fullFilePath}"); return(result); }
/// <summary> /// Set EndTime to start of the next folder where it has not yet been set explicitly. /// </summary> /// <param name="objectSequence"> /// Must be sorted chronologically /// </param> public static void InferEndTimeWhereNotDefinedExplicitly <T>(List <T> objectSequence) where T : IBackupFilesystemObjectInfo { for (var i = 0; i < objectSequence.Count; ++i) { var currentObject = objectSequence[i]; if (!currentObject.PeriodEndDeclaredExplicitly) { if (i + 1 < objectSequence.Count) { var nextObject = objectSequence[i + 1]; currentObject.EndTime = nextObject.StartTime; } else { // last folder: using last write time currentObject.EndTime = currentObject.FileSystemInfo.LastWriteTime; } } Check.DoAssertLambda(currentObject.StartTime < currentObject.EndTime , () => string.Format("End time of {0} equals its start time {1}", currentObject.FileSystemInfo.Name, currentObject.StartTime)); } }