Beispiel #1
0
        private PathScanResults <string> DoWork(Models.Backup backup, CancellationToken cancellationToken)
        {
            PathScanResults <string> results = new PathScanResults <string>();

            BackupedFileRepository daoBackupedFile = new BackupedFileRepository();

            // Load pending `BackupedFiles` from `Backup`.
            IList <Models.BackupedFile> pendingFiles = daoBackupedFile.GetByBackupAndStatus(backup,
                                                                                                                    // 1. We don't want to resume a file that FAILED.
                                                                                                                    // 2. We don't want to resume a file that was CANCELED.
                                                                                                                    // Theoretically, a CANCELED file should never be present in a backup that is still RUNNING,
                                                                                                                    // unless the backup was being CANCELED, and the PlanExecutor was terminated by some reason
                                                                                                                    // after it updated the files as CANCELED but before it got the chance to update the backup
                                                                                                                    // itself as CANCELED.
                                                                                            TransferStatus.STOPPED, // The transfer didn't begin.
                                                                                            TransferStatus.RUNNING  // The transfer did begin but did not complete.
                                                                                            );

            cancellationToken.ThrowIfCancellationRequested();

            // Convert them to a list of paths.
            results.Files = pendingFiles.ToLinkedList <string, Models.BackupedFile>(p => p.File.Path);

            return(results);
        }
Beispiel #2
0
        //
        // Summary:
        // ...
        //
        private IEnumerable <CustomVersionedFile> GetFilesToTransfer(Models.Backup backup, LinkedList <Models.BackupPlanFile> files)
        {
            // Update files version.
            foreach (Models.BackupPlanFile entry in files)
            {
                // Throw if the operation was canceled.
                CancellationToken.ThrowIfCancellationRequested();

                switch (entry.LastStatus)
                {
                // Skip REMOVED, DELETED, and UNCHANGED files.
                default:
                    break;

                case Models.BackupFileStatus.ADDED:
                case Models.BackupFileStatus.MODIFIED:
                {
                    IFileVersion version = new FileVersion {
                        Version = entry.LastWrittenAt.ToString(Models.BackupedFile.VersionFormat)
                    };
                    yield return(new CustomVersionedFile
                        {
                            Path = entry.Path,
                            Size = entry.LastSize,
                            Checksum = null,
                            //Checksum = entry.LastChecksum,
                            Version = version,
                            LastWriteTimeUtc = entry.LastWrittenAt,
                        });

                    break;                                     // YES, it's required!
                }
                }
            }
        }
Beispiel #3
0
 protected override Task <PathScanResults <string> > GetFilesToProcess(Models.Backup backup)
 {
     return(ExecuteOnBackround(() =>
     {
         return DoWork(backup, CancellationTokenSource.Token);
     }, CancellationTokenSource.Token));
 }
Beispiel #4
0
        /// <exception cref="System.InvalidOperationException">
        ///   Thrown when the previous backup operation has not finished yet.
        /// </exception>
        private BackupOperation CreateBackupOperation(Models.BackupPlan plan)
        {
            var dao = new BackupRepository();

            Models.Backup latest = dao.GetLatestByPlan(plan);
            MustResumeLastOperation = latest != null && latest.NeedsResume();

            if (MustResumeLastOperation && !Options.Resume)
            {
                string message = string.Format("The backup (#{0}) has not finished yet."
                                               + " If it's still running, please, wait until it finishes,"
                                               + " otherwise you should resume it manually.",
                                               latest.Id);
                throw new InvalidOperationException(message);
            }

            // Create new backup or resume the last unfinished one.
            BackupOperation obj = MustResumeLastOperation
                                ? new ResumeBackupOperation(latest) as BackupOperation
                                : new NewBackupOperation(plan) as BackupOperation;

            obj.Updated += (sender2, e2) => BackupUpdateStatsInfo(e2.Status, e2.TransferStatus);
            //obj.EventLog = ...
            //obj.TransferListControl = ...

            BackupUpdateStatsInfo(BackupOperationStatus.Unknown, TransferStatus.STOPPED);

            return(obj);
        }
Beispiel #5
0
        public ResumeBackupOperation(Models.Backup backup, BackupOperationOptions options)
            : base(options)
        {
            Assert.IsNotNull(backup);
            Assert.AreEqual(TransferStatus.RUNNING, backup.Status);

            Backup = backup;
        }
Beispiel #6
0
        public async Task <FileVersionerResults> DoVersion(Models.Backup backup, LinkedList <string> filePaths, bool newVersion)
        {
            Assert.IsNotNull(backup);
            Assert.AreEqual(TransferStatus.RUNNING, backup.Status);
            Assert.IsNotNull(filePaths);

            Results.Reset();

            await ExecuteOnBackround(() =>
            {
                ISession session = NHibernateHelper.GetSession();
                try
                {
                    BackupRepository daoBackup = new BackupRepository(session);
                    BackupPlanFileRepository daoBackupPlanFile = new BackupPlanFileRepository(session);

                    Backup = daoBackup.Get(backup.Id);

                    IList <Models.BackupPlanFile> list = newVersion
                                                ? daoBackupPlanFile.GetAllByBackupPlan(Backup.BackupPlan)
                                                : daoBackupPlanFile.GetAllPendingByBackup(Backup);

                    AllFilesFromPlan = list.ToDictionary <Models.BackupPlanFile, string>(p => p.Path);

                    Execute(Backup, filePaths, newVersion);

                    Save(session);
                }
                catch (Exception ex)
                {
                    string message = string.Format("File versioning FAILED with an exception: {0}", ex.Message);

                    Results.OnError(this, message);
                    logger.Log(LogLevel.Error, ex, message);

                    throw ex;
                }
                finally
                {
                    //session.Close();
                    if (session.IsConnected)
                    {
                        session.Disconnect();
                    }
                }
            }, CancellationToken);

            return(Results);
        }
Beispiel #7
0
        public override void OnStart(CustomBackupAgent agent, Models.Backup backup)
        {
            base.OnStart(agent, backup);

            _daoBackup.Update(backup);

            var message = string.Format("Backup resumed at {0}", StartedAt);

            Info(message);
            //StatusInfo.Update(BackupStatusLevel.OK, message);

            OnUpdate(new BackupOperationEvent {
                Status = BackupOperationStatus.Resumed, Message = message
            });
        }
Beispiel #8
0
        public void OnCancelation(CustomBackupAgent agent, Models.Backup backup, Exception exception)
        {
            IsRunning = false;

            var message = string.Format("Backup canceled: {0}", exception != null ? exception.Message : "Exception not informed");

            Report.AddErrorMessage(message);
            Error(message);
            //StatusInfo.Update(BackupStatusLevel.ERROR, message);

            backup.WasCanceled();
            _daoBackup.Update(backup);

            OnUpdate(new BackupOperationEvent {
                Status = BackupOperationStatus.Canceled, Message = message
            });
        }
Beispiel #9
0
        public void OnFailure(CustomBackupAgent agent, Models.Backup backup, Exception exception)
        {
            IsRunning = false;

            logger.Log(LogLevel.Error, exception, "Caught exception: {0}", exception.Message);

            var message = string.Format("Backup failed: {0}", exception != null ? exception.Message : "Exception not informed");

            Report.AddErrorMessage(message);
            Error(message);
            //StatusInfo.Update(BackupStatusLevel.ERROR, message);

            backup.DidFail();
            _daoBackup.Update(backup);

            OnUpdate(new BackupOperationEvent {
                Status = BackupOperationStatus.Failed, Message = message
            });
        }
Beispiel #10
0
        private PathScanResults <string> DoWork(Models.Backup backup, CancellationToken cancellationToken)
        {
            // Scan files.
            DefaultPathScanner scanner = new DefaultPathScanner(backup.BackupPlan, cancellationToken);

#if DEBUG
            scanner.FileAdded += (object sender, string file) =>
            {
                logger.Debug("ADDED: File {0}", file);
            };
            scanner.EntryScanFailed += (object sender, string path, string message, Exception ex) =>
            {
                logger.Debug("FAILED: {0} - Reason: {1}", path, message);
            };
#endif

            scanner.Scan();

            return(scanner.Results);
        }
Beispiel #11
0
        private void Execute(Models.Backup backup, LinkedList <string> filePaths, bool isNewVersion)
        {
            // The `filePaths` argument contains the filesystem paths informed by the user for this backup.

            //
            // NOTE: The methods call ORDER is important!
            //

            SuppliedFiles = DoLoadOrCreateBackupPlanFiles(backup.BackupPlan, filePaths);
            DoUpdateBackupPlanFilesStatus(SuppliedFiles, isNewVersion);

            ChangeSet.AddedFiles = GetAddedFiles(SuppliedFiles);
#if false
            foreach (var item in ChangeSet.AddedFiles)
            {
                Console.WriteLine("BackupPlanAddedFiles: {0}", item.Path);
            }
#endif
            ChangeSet.ModifiedFiles = GetModifiedFiles(SuppliedFiles);
#if false
            foreach (var item in changeset.modifiedfiles)
            {
                console.writeline("backupplanmodifiedfiles: {0}", item.path);
            }
#endif
            // DO NOT update files removal and deletion status for `ResumeBackupOperation`,
            // only for `NewBackupOperation`.
            if (isNewVersion)
            {
                ChangeSet.RemovedFiles = GetRemovedFiles(AllFilesFromPlan.Values);
#if false
                foreach (var item in ChangeSet.RemovedFiles)
                {
                    Console.WriteLine("BackupPlanRemovedFiles: {0}", item.Path);
                }
#endif
                ChangeSet.DeletedFiles = GetDeletedFilesAndUpdateTheirStatus(SuppliedFiles);
            }

            //throw new Exception("Simulating failure.");
        }
Beispiel #12
0
        // Update specific `BackupPlanFile`s that exist and are NOT yet associated to a `BackupPlan`.
        protected void DoUpdateSyncedFiles(Models.Backup backup, LinkedList <string> filesToProcess)
        {
            BackupPlanFileRepository dao = new BackupPlanFileRepository();

            long totalUpdates = 0;

            foreach (var path in filesToProcess)
            {
                // There's NO NEED to SELECT and UPDATE if we can UPDATE directly using a WHERE clause.
                totalUpdates += dao.AssociateSyncedFileToBackupPlan(backup.BackupPlan, path);
            }

            if (totalUpdates > 0)
            {
                logger.Info("Associated {0} synced files to Backup Plan {1}", totalUpdates, backup.BackupPlan.Name);
            }
            else
            {
                logger.Info("There are no synced files to associate to Backup Plan {0}", backup.BackupPlan.Name);
            }
        }
Beispiel #13
0
 public async Task <FileVersionerResults> ResumeVersion(Models.Backup backup, LinkedList <string> files)
 {
     return(await DoVersion(backup, files, false));
 }
Beispiel #14
0
 protected override Task <FileVersionerResults> DoVersionFiles(Models.Backup backup, LinkedList <string> filesToProcess)
 {
     return(Versioner.ResumeVersion(backup, filesToProcess));
 }
Beispiel #15
0
        private void OnControlPlanQuery(object sender, ServerCommandEventArgs e)
        {
            string planType = e.Command.GetArgumentValue <string>("planType");
            Int32  planId   = e.Command.GetArgumentValue <Int32>("planId");

            ValidatePlanType(planType);

            bool isRunning   = IsPlanRunning(planType, planId);
            bool needsResume = false;
            bool isFinished  = false;

            bool isBackup  = planType.Equals(PlanTypeEnum.BACKUP.ToString().ToLowerInvariant());
            bool isRestore = planType.Equals(PlanTypeEnum.RESTORE.ToString().ToLowerInvariant());

            // Report to GUI.
            Commands.GuiReportPlanStatus report = new Commands.GuiReportPlanStatus();

            if (isBackup)
            {
                BackupRepository daoBackup = new BackupRepository();
                Models.Backup    latest    = daoBackup.GetLatestByPlan(new Models.BackupPlan {
                    Id = planId
                });

                needsResume = latest != null && latest.NeedsResume();
                isFinished  = latest != null && latest.IsFinished();

                if (isRunning)
                {
                    report.StartedAt = latest.StartedAt;
                }
                else if (isFinished)
                {
                    report.FinishedAt = latest.FinishedAt;
                }
            }
            else if (isRestore)
            {
                RestoreRepository daoRestore = new RestoreRepository();
                Models.Restore    latest     = daoRestore.GetLatestByPlan(new Models.RestorePlan {
                    Id = planId
                });

                needsResume = latest != null && latest.NeedsResume();
                isFinished  = latest != null && latest.IsFinished();

                if (isRunning)
                {
                    report.StartedAt = latest.StartedAt;
                }
                else if (isFinished)
                {
                    report.FinishedAt = latest.FinishedAt;
                }
            }

            bool isInterrupted = !isRunning && needsResume;

            Commands.OperationStatus status;
            // The condition order below is important because more than one flag might be true.
            if (isInterrupted)
            {
                status = Commands.OperationStatus.INTERRUPTED;
            }
            else if (needsResume)
            {
                status = Commands.OperationStatus.RESUMED;
            }
            else if (isRunning)
            {
                status = Commands.OperationStatus.STARTED;
            }
            else
            {
                status = Commands.OperationStatus.NOT_RUNNING;
            }

            report.Status = status;

            Handler.Send(e.Context, Commands.GuiReportOperationStatus(planType, planId, report));
        }
Beispiel #16
0
        protected void RegisterResultsEventHandlers(Models.Backup backup, TransferResults results)
        {
            BackupedFileRepository daoBackupedFile = new BackupedFileRepository();

            results.DeleteCompleted += (object sender, DeletionArgs e) =>
            {
                Int64?backupedFileId = (Int64?)e.UserData;
                // TODO(jweyrich): We could get rid of the SELECT and perform just the UPDATE.
                Models.BackupedFile backupedFile = daoBackupedFile.Get(backupedFileId.Value);
                backupedFile.TransferStatus = TransferStatus.PURGED;
                backupedFile.UpdatedAt      = DateTime.UtcNow;
                daoBackupedFile.Update(backupedFile);

                //var message = string.Format("Purged {0}", e.FilePath);
                //Info(message);
                //OnUpdate(new BackupOperationEvent { Status = BackupOperationStatus.Updated, Message = message });
            };
            results.Failed += (object sender, TransferFileProgressArgs args) =>
            {
                Models.BackupedFile backupedFile = daoBackupedFile.GetByBackupAndPath(backup, args.FilePath);
                backupedFile.TransferStatus = TransferStatus.FAILED;
                backupedFile.UpdatedAt      = DateTime.UtcNow;
                daoBackupedFile.Update(backupedFile);

                var message = string.Format("Failed {0} - {1}", args.FilePath, args.Exception != null ? args.Exception.Message : "Unknown reason");
                Warn(message);
                //StatusInfo.Update(BackupStatusLevel.ERROR, message);
                OnUpdate(new BackupOperationEvent {
                    Status = BackupOperationStatus.Updated, Message = message, TransferStatus = TransferStatus.FAILED
                });
            };
            results.Canceled += (object sender, TransferFileProgressArgs args) =>
            {
                Models.BackupedFile backupedFile = daoBackupedFile.GetByBackupAndPath(backup, args.FilePath);
                backupedFile.TransferStatus = TransferStatus.CANCELED;
                backupedFile.UpdatedAt      = DateTime.UtcNow;
                daoBackupedFile.Update(backupedFile);

                var message = string.Format("Canceled {0} - {1}", args.FilePath, args.Exception != null ? args.Exception.Message : "Unknown reason");
                Warn(message);
                //StatusInfo.Update(BackupStatusLevel.ERROR, message);
                OnUpdate(new BackupOperationEvent {
                    Status = BackupOperationStatus.Updated, Message = message, TransferStatus = TransferStatus.CANCELED
                });
            };
            results.Completed += (object sender, TransferFileProgressArgs args) =>
            {
                Models.BackupedFile backupedFile = daoBackupedFile.GetByBackupAndPath(backup, args.FilePath);
                backupedFile.TransferStatus = TransferStatus.COMPLETED;
                backupedFile.UpdatedAt      = DateTime.UtcNow;
                daoBackupedFile.Update(backupedFile);

                var message = string.Format("Completed {0}", args.FilePath);
                Info(message);
                OnUpdate(new BackupOperationEvent {
                    Status = BackupOperationStatus.Updated, Message = message, TransferStatus = TransferStatus.COMPLETED
                });

                Models.BackupPlan plan = Backup.BackupPlan;                 //backupedFile.Backup.BackupPlan;

                if (plan.PurgeOptions != null && plan.PurgeOptions.IsTypeCustom && plan.PurgeOptions.EnabledKeepNumberOfVersions)
                {
                    // Purge the oldest versioned files if the count of versions exceeds the maximum specified for the Backup Plan.
                    IList <Models.BackupedFile> previousVersions = daoBackupedFile.GetCompleteByPlanAndPath(plan, args.FilePath);
                    int found = previousVersions.Count;
                    int keep  = plan.PurgeOptions.NumberOfVersionsToKeep;
                    int diff  = found - keep;
                    if (diff > 0)
                    {
                        // Delete the oldest Count-N versions.
                        List <Models.BackupedFile> versionsToPurge = previousVersions.Skip(keep).ToList();
                        foreach (var vp in versionsToPurge)
                        {
                            DeleteVersionedFile(vp.File.Path, new FileVersion {
                                Version = vp.Version
                            }, vp.Id);
                        }
                    }
                }
            };
            results.Started += (object sender, TransferFileProgressArgs args) =>
            {
                Models.BackupedFile backupedFile = daoBackupedFile.GetByBackupAndPath(backup, args.FilePath);
                backupedFile.TransferStatus = TransferStatus.RUNNING;
                backupedFile.UpdatedAt      = DateTime.UtcNow;
                daoBackupedFile.Update(backupedFile);

                var message = string.Format("Started {0}", args.FilePath);
                Info(message);
                OnUpdate(new BackupOperationEvent {
                    Status = BackupOperationStatus.Updated, Message = message
                });
            };
            results.Progress += (object sender, TransferFileProgressArgs args) =>
            {
#if DEBUG
                var message = string.Format("Progress {0}% {1} ({2}/{3} bytes)",
                                            args.PercentDone, args.FilePath, args.TransferredBytes, args.TotalBytes);
                //Info(message);
#endif
                OnUpdate(new BackupOperationEvent {
                    Status = BackupOperationStatus.Updated, Message = null
                });
            };
        }
Beispiel #17
0
 protected abstract Task <PathScanResults <string> > GetFilesToProcess(Models.Backup backup);
Beispiel #18
0
 public ResumeBackupOperation(Models.Backup backup)
     : this(backup, new BackupOperationOptions())
 {
 }
Beispiel #19
0
 protected abstract Task <FileVersionerResults> DoVersionFiles(Models.Backup backup, LinkedList <string> filesToProcess);
Beispiel #20
0
        public virtual void OnStart(CustomBackupAgent agent, Models.Backup backup)
        {
            IsRunning = true;

            backup.DidStart();
        }
Beispiel #21
0
        protected async void DoBackup(CustomBackupAgent agent, Models.Backup backup, BackupOperationOptions options)
        {
            try
            {
                CurrentState = BackupOperationState.STARTING;
                OnStart(agent, backup);

                // Mount all network mappings and abort if there is any network mapping failure.
                CurrentState = BackupOperationState.MAPPING_NETWORK_DRIVES;
                Helper.MountAllNetworkDrives();

                // Execute pre-actions
                CurrentState = BackupOperationState.EXECUTING_PRE_ACTIONS;
                Helper.ExecutePreActions();

                //
                // Scanning
                //

                CurrentState = BackupOperationState.SCANNING_FILES;
                LinkedList <string> filesToProcess = null;
                {
                    Task <PathScanResults <string> > filesToProcessTask = GetFilesToProcess(backup);

                    {
                        var message = string.Format("Scanning files started.");
                        Info(message);
                        //StatusInfo.Update(BackupStatusLevel.INFO, message);
                        OnUpdate(new BackupOperationEvent {
                            Status = BackupOperationStatus.ScanningFilesStarted, Message = message
                        });
                    }

                    try
                    {
                        await filesToProcessTask;
                    }
                    catch (Exception ex)
                    {
                        if (ex.IsCancellation())
                        {
                            string message = string.Format("Scanning files was canceled.");

                            Report.AddErrorMessage(message);
                            logger.Warn(message);
                        }
                        else
                        {
                            string message = string.Format("Caught exception during scanning files: {0}", ex.Message);

                            Report.AddErrorMessage(message);
                            logger.Log(LogLevel.Error, ex, message);
                        }

                        if (filesToProcessTask.IsFaulted || filesToProcessTask.IsCanceled)
                        {
                            if (filesToProcessTask.IsCanceled)
                            {
                                OnCancelation(agent, backup, ex);                                 // filesToProcessTask.Exception
                            }
                            else
                            {
                                OnFailure(agent, backup, ex);                                 // filesToProcessTask.Exception
                            }
                            return;
                        }
                    }

                    filesToProcess = filesToProcessTask.Result.Files;

                    {
                        foreach (var entry in filesToProcessTask.Result.FailedFiles)
                        {
                            Report.AddErrorMessage(entry.Value);
                        }

                        if (filesToProcessTask.Result.FailedFiles.Count > 0)
                        {
                            StringBuilder sb = new StringBuilder();
                            sb.AppendLine("Scanning failed for the following drives/files/directories:");
                            foreach (var entry in filesToProcessTask.Result.FailedFiles)
                            {
                                sb.AppendLine(string.Format("  Path: {0} - Reason: {1}", entry.Key, entry.Value));
                            }
                            Warn(sb.ToString());
                        }

                        var message = string.Format("Scanning files finished.");
                        Info(message);
                        //StatusInfo.Update(BackupStatusLevel.INFO, message);
                        OnUpdate(new BackupOperationEvent {
                            Status = BackupOperationStatus.ScanningFilesFinished, Message = message
                        });
                    }
                }

                //
                // Update synced files
                //

                CurrentState = BackupOperationState.UPDATING_SYNCED_FILES;
                {
                    Task updateSyncedFilesTask = ExecuteOnBackround(() =>
                    {
                        DoUpdateSyncedFiles(backup, filesToProcess);
                    }, CancellationTokenSource.Token);

                    {
                        var message = string.Format("Update of synced files started.");
                        Info(message);
                    }

                    try
                    {
                        await updateSyncedFilesTask;
                    }
                    catch (Exception ex)
                    {
                        if (ex.IsCancellation())
                        {
                            string message = string.Format("Update of synced files was canceled.");

                            Report.AddErrorMessage(message);
                            logger.Warn(message);
                        }
                        else
                        {
                            string message = string.Format("Caught exception during update of synced files: {0}", ex.Message);

                            Report.AddErrorMessage(message);
                            logger.Log(LogLevel.Error, ex, message);
                        }

                        if (updateSyncedFilesTask.IsFaulted || updateSyncedFilesTask.IsCanceled)
                        {
                            Versioner.Undo();
                            if (updateSyncedFilesTask.IsCanceled)
                            {
                                OnCancelation(agent, backup, ex);                                 // updateSyncedFilesTask.Exception
                            }
                            else
                            {
                                OnFailure(agent, backup, ex);                                 // updateSyncedFilesTask.Exception
                            }
                            return;
                        }
                    }

                    {
                        var message = string.Format("Update of synced files finished.");
                        Info(message);
                    }
                }

                //
                // Versioning
                //

                CurrentState = BackupOperationState.VERSIONING_FILES;
                {
                    Task <FileVersionerResults> versionerTask = DoVersionFiles(backup, filesToProcess);
                    Report.VersionerResults = versionerTask.Result;

                    {
                        var message = string.Format("Processing files started.");
                        Info(message);
                        //StatusInfo.Update(BackupStatusLevel.INFO, message);
                        OnUpdate(new BackupOperationEvent {
                            Status = BackupOperationStatus.ProcessingFilesStarted, Message = message
                        });
                    }

                    try
                    {
                        await versionerTask;
                    }
                    catch (Exception ex)
                    {
                        if (ex.IsCancellation())
                        {
                            string message = string.Format("Processing files was canceled.");

                            Report.AddErrorMessage(message);
                            logger.Warn(message);
                        }
                        else
                        {
                            string message = string.Format("Caught exception during processing files: {0}", ex.Message);

                            Report.AddErrorMessage(message);
                            logger.Log(LogLevel.Error, ex, message);
                        }

                        if (versionerTask.IsFaulted || versionerTask.IsCanceled)
                        {
                            Versioner.Undo();
                            if (versionerTask.IsCanceled)
                            {
                                OnCancelation(agent, backup, ex);                                 // versionerTask.Exception
                            }
                            else
                            {
                                OnFailure(agent, backup, ex);                                 // versionerTask.Exception
                            }
                            return;
                        }
                    }

                    agent.Files = Versioner.FilesToTransfer;

                    {
                        var message = string.Format("Processing files finished.");
                        Info(message);
                        //StatusInfo.Update(BackupStatusLevel.INFO, message);
                        OnUpdate(new BackupOperationEvent {
                            Status = BackupOperationStatus.ProcessingFilesFinished, Message = message
                        });
                    }

                    {
                        agent.Results.Stats.BytesTotal = agent.EstimatedTransferSize;

                        var message = string.Format("Estimated backup size: {0} files, {1}",
                                                    agent.Files.Count(), FileSizeUtils.FileSizeToString(agent.EstimatedTransferSize));
                        Info(message);
                    }
                }

                //
                // Transfer files
                //

                CurrentState = BackupOperationState.TRANSFERRING_FILES;
                {
                    Task <TransferResults> transferTask = agent.Start();
                    Report.TransferResults = transferTask.Result;

                    {
                        var message = string.Format("Transfer files started.");
                        Info(message);
                    }

                    try
                    {
                        await transferTask;
                    }
                    catch (Exception ex)
                    {
                        if (ex.IsCancellation())
                        {
                            string message = string.Format("Transfer files was canceled.");

                            Report.TransferResults.ErrorMessages.Add(message);
                            logger.Warn(message);
                        }
                        else
                        {
                            string message = string.Format("Caught exception during transfer files: {0}", ex.Message);

                            Report.TransferResults.ErrorMessages.Add(message);
                            logger.Log(LogLevel.Error, ex, message);
                        }

                        if (transferTask.IsFaulted || transferTask.IsCanceled)
                        {
                            if (transferTask.IsCanceled)
                            {
                                OnCancelation(agent, backup, ex);                                 // transferTask.Exception
                            }
                            else
                            {
                                OnFailure(agent, backup, ex);                                 // transferTask.Exception
                            }
                            return;
                        }
                    }

                    {
                        var message = string.Format("Transfer files finished.");
                        Info(message);
                    }
                }

                CurrentState = BackupOperationState.EXECUTING_POST_ACTIONS;
                Helper.ExecutePostActions(Report.TransferResults);

                CurrentState = BackupOperationState.FINISHING;
                OnFinish(agent, backup);
            }
            catch (Exception ex)
            {
                OnFinish(agent, backup, ex);
            }
        }
Beispiel #22
0
        public void OnFinish(CustomBackupAgent agent, Models.Backup backup, Exception ex = null)
        {
            IsRunning = false;

            switch (CurrentState)
            {
            default:
            {
                var message = string.Format("Backup failed: {0}", ex.Message);
                Warn(message);
                //StatusInfo.Update(BackupStatusLevel.WARN, message);
                Report.AddErrorMessage(ex.Message);

                Report.OperationStatus = OperationStatus.FAILED;
                backup.DidFail();
                _daoBackup.Update(backup);
                OnUpdate(new BackupOperationEvent {
                        Status = BackupOperationStatus.Failed, Message = message
                    });

                break;
            }

            case BackupOperationState.FINISHING:
            {
                TransferResults.Statistics stats = agent.Results.Stats;

                var message = string.Format(
                    "Backup finished! Stats: {0} completed, {1} failed, {2} canceled, {3} pending, {4} running",
                    stats.Completed, stats.Failed, stats.Canceled, stats.Pending, stats.Running);
                Info(message);
                //StatusInfo.Update(BackupStatusLevel.OK, message);

                switch (agent.Results.OverallStatus)
                //switch (backup.Status)
                {
                default: throw new InvalidOperationException("Unexpected TransferStatus");

                case TransferStatus.CANCELED:
                    Report.OperationStatus = OperationStatus.CANCELED;
                    backup.WasCanceled();
                    _daoBackup.Update(backup);
                    OnUpdate(new BackupOperationEvent {
                            Status = BackupOperationStatus.Canceled, Message = message
                        });
                    break;

                case TransferStatus.FAILED:
                    Report.OperationStatus = OperationStatus.FAILED;
                    backup.DidFail();
                    _daoBackup.Update(backup);
                    OnUpdate(new BackupOperationEvent {
                            Status = BackupOperationStatus.Failed, Message = message
                        });
                    break;

                case TransferStatus.COMPLETED:
                    Report.OperationStatus = OperationStatus.COMPLETED;
                    backup.DidComplete();
                    _daoBackup.Update(backup);
                    OnUpdate(new BackupOperationEvent {
                            Status = BackupOperationStatus.Finished, Message = message
                        });
                    break;
                }

                break;
            }
            }

            Report.StartedAt  = Backup.StartedAt;
            Report.FinishedAt = Backup.FinishedAt.Value;
        }
Beispiel #23
0
 public NewBackupOperation(Models.BackupPlan plan, BackupOperationOptions options)
     : base(options)
 {
     Backup = new Models.Backup(plan);
 }