private void MirrorGroup(FileGroup group) { using (_engine = new MirrorMaker(_progress)) { try { _engine.StartingDirectory += OnStartingDirectory; _engine.StartingFile += OnStartingFile; _engine.ItemHandlingError += OnItemHandlingError; string destinationSubFolder = group.GetDestinationSubFolder(DestinationRootForThisUser); _progress.WriteVerbose("[{0}] Source={1}", group.Name, group.RootFolder); _progress.WriteVerbose("[{0}] Destination={1}", group.Name, destinationSubFolder); //_engine.PreviewMode = false; _engine.Run(group.RootFolder, destinationSubFolder); if (_engine.WasCancelled) { _currentGroup.Disposition = FileGroup.DispositionChoice.Cancelled; } else { group.Disposition = FileGroup.DispositionChoice.WasBackedUp; } } catch (IOException error) { _gotIOExceptionProbablyDiskFull = true; //enhance: we could clarify that it was partially backed up _currentGroup.Disposition = FileGroup.DispositionChoice.NotEnoughRoom; _progress.WriteWarning(error.Message); } if (GroupProgress != null) { GroupProgress.Invoke(); } } }
public void GatherPreview() { /* enhance: we could try to deal with the situation where a lower-priority group * is hogging space from a newly enlarged higher-priority group. We'd have to * scan ahead, perhaps first collecting the current on-backup sizes of each. * * Then, as we go through the groups, we could keep going so long as deleting * some lower-priority group would allow us to keep going. */ _alreadyAccountedFor = new HashSet <string>(); _cancelRequested = false; _files = 0; ApprovedChangeInKB = 0; //PredictedChangeInKiloBytes = 0; _totalFilesThatWillBeBackedUp = 0; var limitHasBeenReached = false; foreach (var group in _groups) { if (_cancelRequested) { break; } _currentGroup = group; //used by callbacks group.ClearStatistics(); if (group.Disposition == FileGroup.DispositionChoice.Hide) { _progress.WriteMessage("Skipping preview of group {0}", group.Name); continue; } _progress.WriteMessage("Beginning preview of group {0}", group.Name); Debug.Assert(!string.IsNullOrEmpty(group.RootFolder), "should have been weeded out already"); Debug.Assert(SafeIO.Directory.Exists(group.RootFolder), "should have been weeded out already"); if (limitHasBeenReached) { //don't even investigate. //NB: there might actually be enough room, if this group is smaller //than the first one which was too big. Or algorithm doesn't try //to fit it in. group.Disposition = FileGroup.DispositionChoice.NotEnoughRoom; InvokeGroupProgress(); continue; } group.Disposition = FileGroup.DispositionChoice.Calculating; InvokeGroupProgress(); string destinationSubFolder = group.GetDestinationSubFolder(DestinationRootForThisUser); using (_engine = new MirrorMaker(_progress)) { _engine.StartingDirectory += OnStartingDirectory; _engine.StartingFile += OnStartingFile; _engine.Run(group.RootFolder, destinationSubFolder); var groupsChangeInKB = (long)Math.Ceiling(group.NetChangeInBytes / 1024.0); //is there room to fit in this whole group? if (ApprovedChangeInKB + groupsChangeInKB < _totalAvailableOnDeviceInKilobytes) { ApprovedChangeInKB = groupsChangeInKB; _totalFilesThatWillBeBackedUp += group.UpdateFileCount + group.NewFileCount; group.Disposition = FileGroup.DispositionChoice.WillBeBackedUp; } else { limitHasBeenReached = true; //nb: remove if/when we go to the system below of deleting group.Disposition = FileGroup.DispositionChoice.NotEnoughRoom; } InvokeGroupProgress(); _files = 0; } _engine = null; } }
public void Run() { _cancelRequested = false; _alreadyAccountedFor = new HashSet <string>(); try { foreach (var group in _groups) { if (_cancelRequested) { break; } _currentGroup = group; //used by callbacks try { if (group.Disposition == FileGroup.DispositionChoice.Hide) { _progress.WriteMessage("Skipping group {0}", group.Name); continue; } if (_gotIOExceptionProbablyDiskFull) { group.Disposition = FileGroup.DispositionChoice.NotEnoughRoom; continue; } _progress.WriteMessage("Beginning group {0}", group.Name); if (group.Disposition == FileGroup.DispositionChoice.NotEnoughRoom) { continue; } group.ClearStatistics(); group.Disposition = FileGroup.DispositionChoice.Synchronizing; InvokeGroupProgress(); MirrorGroup(group); InvokeGroupProgress(); } catch (Exception error) { var message = "Exception processing group: " + group.Name; _progress.WriteError(message); _progress.WriteException(error); UsageReporter.ReportException(false, "backup", error, message); } _engine = null; _progress.WriteMessage("Controller finished normally."); //we don't want to send, say, 100 errors just because the drive is full. Let's just send one. if (_firstErrorMessage != null) { UsageReporter.SendEvent("Backup", "file error(just the 1st one)", "file error(just the 1st one)", _firstErrorMessage, 0); } } // Program.ReportToGoogleAnalytics("FinishedBackup", "filesBackedUp", _totalFilesThatWillBeBackedUp); /* Program.ReportToGoogleAnalytics("finishedUpdated","updated", _engine.UpdatedCount); * Program.ReportToGoogleAnalytics("finishedCreated", "created", _engine.CreatedCount); * Program.ReportToGoogleAnalytics("finishedDeleted", "deleted", _engine.DeletedCount); */ } finally { CleanupTempFiles(); } }