public void Execute() { try { log.Info("Starting backup of '{0}' to '{1}'", backupSourceDirectory, backupDestinationDirectory); UpdateBackupStatus( string.Format("Started backup process. Backing up data to directory = '{0}'", backupDestinationDirectory), null, BackupStatus.BackupMessageSeverity.Informational); EnsureBackupDestinationExists(); if (incrementalBackup) { var incrementalBackupState = Path.Combine(backupDestinationDirectory, Constants.IncrementalBackupState); if (File.Exists(incrementalBackupState)) { var state = RavenJObject.Parse(File.ReadAllText(incrementalBackupState)).JsonDeserialization <IncrementalBackupState>(); if (state.ResourceId != filesystem.Storage.Id) { throw new InvalidOperationException(string.Format("Can't perform an incremental backup to a given folder because it already contains incremental backup data of different file system. Existing incremental data origins from '{0}' file system.", state.ResourceName)); } } else { var state = new IncrementalBackupState() { ResourceId = filesystem.Storage.Id, ResourceName = filesystem.Name }; File.WriteAllText(incrementalBackupState, RavenJObject.FromObject(state).ToString()); } token.ThrowIfCancellationRequested(); if (CanPerformIncrementalBackup()) { backupDestinationDirectory = DirectoryForIncrementalBackup(); } else { incrementalBackup = false; // destination wasn't detected as a backup folder, automatically revert to a full backup if incremental was specified } } else if (BackupAlreadyExists) { throw new InvalidOperationException("Denying request to perform a full backup to an existing backup folder. Try doing an incremental backup instead."); } token.ThrowIfCancellationRequested(); UpdateBackupStatus(string.Format("Backing up indexes.."), null, BackupStatus.BackupMessageSeverity.Informational); // Make sure we have an Indexes folder in the backup location if (!Directory.Exists(Path.Combine(backupDestinationDirectory, "Indexes"))) { Directory.CreateDirectory(Path.Combine(backupDestinationDirectory, "Indexes")); } token.ThrowIfCancellationRequested(); filesystem.Search.Backup(backupDestinationDirectory, token); UpdateBackupStatus(string.Format("Finished indexes backup. Executing data backup.."), null, BackupStatus.BackupMessageSeverity.Informational); ExecuteBackup(backupDestinationDirectory, incrementalBackup, token); if (filesystemDocument != null) { File.WriteAllText(Path.Combine(backupDestinationDirectory, Constants.FilesystemDocumentFilename), RavenJObject.FromObject(filesystemDocument).ToString()); } token.ThrowIfCancellationRequested(); OperationFinishedSuccessfully(); } catch (OperationCanceledException e) { File.WriteAllText(Path.Combine(backupDestinationDirectory, Constants.BackupFailureMarker), e.Message); UpdateBackupStatus("Backup was canceled", null, BackupStatus.BackupMessageSeverity.Error); state.MarkCanceled(); } catch (AggregateException e) { var ne = e.ExtractSingleInnerException(); UpdateBackupStatus("Failed to complete backup because: " + ne.Message, ne, BackupStatus.BackupMessageSeverity.Error); state.MarkFaulted("Failed to complete backup because: " + ne.Message, ne); File.WriteAllText(Path.Combine(backupDestinationDirectory, Constants.BackupFailureMarker), ne.Message); } catch (Exception e) { UpdateBackupStatus("Failed to complete backup because: " + e.Message, e, BackupStatus.BackupMessageSeverity.Error); state.MarkFaulted("Failed to complete backup because: " + e.Message, e); File.WriteAllText(Path.Combine(backupDestinationDirectory, Constants.BackupFailureMarker), e.Message); } finally { CompleteBackup(); } }
public void Execute() { try { log.Info("Starting backup of '{0}' to '{1}'", backupSourceDirectory, backupDestinationDirectory); UpdateBackupStatus( string.Format("Started backup process. Backing up data to directory = '{0}'", backupDestinationDirectory), null, BackupStatus.BackupMessageSeverity.Informational); EnsureBackupDestinationExists(); if (incrementalBackup) { var incrementalBackupState = Path.Combine(backupDestinationDirectory, Constants.IncrementalBackupState); if (File.Exists(incrementalBackupState)) { var state = RavenJObject.Parse(File.ReadAllText(incrementalBackupState)).JsonDeserialization <IncrementalBackupState>(); if (state.ResourceId != database.TransactionalStorage.Id) { throw new InvalidOperationException(string.Format("Can't perform an incremental backup to a given folder because it already contains incremental backup data of different database. Existing incremental data origins from '{0}' database.", state.ResourceName)); } } else { var state = new IncrementalBackupState { ResourceId = database.TransactionalStorage.Id, ResourceName = database.Name ?? Constants.SystemDatabase }; File.WriteAllText(incrementalBackupState, RavenJObject.FromObject(state).ToString()); } cancellationToken.ThrowIfCancellationRequested(); if (CanPerformIncrementalBackup()) { backupDestinationDirectory = DirectoryForIncrementalBackup(); EnsureBackupDestinationExists(); } else { incrementalBackup = false; // destination wasn't detected as a backup folder, automatically revert to a full backup if incremental was specified } } else if (BackupAlreadyExists) { throw new InvalidOperationException("Denying request to perform a full backup to an existing backup folder. Try doing an incremental backup instead."); } cancellationToken.ThrowIfCancellationRequested(); UpdateBackupStatus("Backing up indexes..", null, BackupStatus.BackupMessageSeverity.Informational); // Make sure we have an Indexes folder in the backup location if (!Directory.Exists(Path.Combine(backupDestinationDirectory, "Indexes"))) { Directory.CreateDirectory(Path.Combine(backupDestinationDirectory, "Indexes")); } cancellationToken.ThrowIfCancellationRequested(); var directoryBackups = new List <DirectoryBackup> { new DirectoryBackup(Path.Combine(backupSourceDirectory, "IndexDefinitions"), Path.Combine(backupDestinationDirectory, "IndexDefinitions"), Path.Combine(backupSourceDirectory, "Temp" + Guid.NewGuid().ToString("N")), incrementalBackup) }; database.IndexStorage.Backup(backupDestinationDirectory, null, UpdateBackupStatus, cancellationToken); var progressNotifier = new ProgressNotifier(); foreach (var directoryBackup in directoryBackups) { directoryBackup.Notify += UpdateBackupStatus; var backupSize = directoryBackup.Prepare(); progressNotifier.TotalBytes += backupSize; } cancellationToken.ThrowIfCancellationRequested(); foreach (var directoryBackup in directoryBackups) { directoryBackup.Execute(progressNotifier, cancellationToken); } UpdateBackupStatus("Finished indexes backup. Executing data backup..", null, BackupStatus.BackupMessageSeverity.Informational); ExecuteBackup(backupDestinationDirectory, incrementalBackup, cancellationToken); if (databaseDocument != null) { File.WriteAllText(Path.Combine(backupDestinationDirectory, Constants.DatabaseDocumentFilename), RavenJObject.FromObject(databaseDocument).ToString()); } cancellationToken.ThrowIfCancellationRequested(); OperationFinishedSuccessfully(); } catch (OperationCanceledException e) { File.WriteAllText(Path.Combine(backupDestinationDirectory, Constants.BackupFailureMarker), e.Message); UpdateBackupStatus("Backup was canceled", null, BackupStatus.BackupMessageSeverity.Error); state.MarkCanceled(); } catch (AggregateException e) { var ne = e.ExtractSingleInnerException(); // OperationCancledException can be inside AggreateException, because we perform some writes in parallel if (ne is OperationCanceledException) { state.MarkCanceled(); UpdateBackupStatus("Backup was canceled", null, BackupStatus.BackupMessageSeverity.Error); } else { state.MarkFaulted("Failed to complete backup because:" + ne.Message, ne); UpdateBackupStatus("Failed to complete backup because: " + ne.Message, ne, BackupStatus.BackupMessageSeverity.Error); } File.WriteAllText(Path.Combine(backupDestinationDirectory, Constants.BackupFailureMarker), ne.Message); } catch (Exception e) { UpdateBackupStatus("Failed to complete backup because: " + e.Message, e, BackupStatus.BackupMessageSeverity.Error); state.MarkFaulted("Failed to complete backup because: " + e.Message); File.WriteAllText(Path.Combine(backupDestinationDirectory, Constants.BackupFailureMarker), e.Message); } finally { CompleteBackup(); } }