예제 #1
0
        private InternalBackupResult CreateBackup(
            DatabaseSmugglerOptionsServerSide options, string backupFilePath, long?startDocumentEtag, long?startRaftIndex)
        {
            // the last etag is already included in the last backup
            var currentBackupResults = new InternalBackupResult();

            startDocumentEtag = startDocumentEtag == null ? 0 : ++startDocumentEtag;
            startRaftIndex    = startRaftIndex == null ? 0 : ++startRaftIndex;

            using (Stream fileStream = File.Open(backupFilePath, FileMode.CreateNew))
                using (var outputStream = GetOutputStream(fileStream))
                    using (_database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                    {
                        var smugglerSource      = new DatabaseSource(_database, startDocumentEtag.Value, startRaftIndex.Value, _logger);
                        var smugglerDestination = new StreamDestination(outputStream, context, smugglerSource);
                        var smuggler            = new DatabaseSmuggler(_database,
                                                                       smugglerSource,
                                                                       smugglerDestination,
                                                                       _database.Time,
                                                                       options: options,
                                                                       result: _backupResult,
                                                                       onProgress: _onProgress,
                                                                       token: TaskCancelToken.Token);

                        smuggler.ExecuteAsync().Wait();

                        switch (outputStream)
                        {
                        case EncryptingXChaCha20Poly1305Stream encryptedStream:
                            encryptedStream.Flush(flushToDisk: true);
                            break;

                        case FileStream file:
                            file.Flush(flushToDisk: true);
                            break;

                        default:
                            throw new InvalidOperationException($" {outputStream.GetType()} not supported");
                        }

                        currentBackupResults.LastDocumentEtag         = smugglerSource.LastEtag;
                        currentBackupResults.LastDatabaseChangeVector = smugglerSource.LastDatabaseChangeVector;
                        currentBackupResults.LastRaftIndex            = smugglerSource.LastRaftIndex;

                        return(currentBackupResults);
                    }
        }
예제 #2
0
        private InternalBackupResult CreateLocalBackupOrSnapshot(PeriodicBackupStatus status, string backupFilePath, long?startDocumentEtag, long?startRaftIndex)
        {
            var internalBackupResult = new InternalBackupResult();

            using (status.LocalBackup.UpdateStats(_isFullBackup))
            {
                // will rename the file after the backup is finished
                var tempBackupFilePath = backupFilePath + InProgressExtension;

                try
                {
                    BackupTypeValidation();

                    AddInfo($"Started {GetBackupDescription(_configuration.BackupType, _isFullBackup)}");
                    if (_configuration.BackupType == BackupType.Backup ||
                        _configuration.BackupType == BackupType.Snapshot && _isFullBackup == false)
                    {
                        // smuggler backup
                        var options = new DatabaseSmugglerOptionsServerSide
                        {
                            AuthorizationStatus = AuthorizationStatus.DatabaseAdmin,
                            IncludeArtificial   = true // we want to include artificial in backup
                        };

                        options.OperateOnTypes |= DatabaseItemType.Tombstones;
                        options.OperateOnTypes |= DatabaseItemType.CompareExchangeTombstones;

                        var currentBackupResult = CreateBackup(options, tempBackupFilePath, startDocumentEtag, startRaftIndex);

                        if (_isFullBackup)
                        {
                            internalBackupResult = currentBackupResult;
                        }
                        else
                        {
                            if (_backupResult.GetLastEtag() == _previousBackupStatus.LastEtag &&
                                _backupResult.GetLastRaftIndex() == _previousBackupStatus.LastRaftIndex.LastEtag)
                            {
                                internalBackupResult.LastDocumentEtag         = startDocumentEtag ?? 0;
                                internalBackupResult.LastDatabaseChangeVector = _previousBackupStatus.LastDatabaseChangeVector;
                                internalBackupResult.LastRaftIndex            = startRaftIndex ?? 0;
                            }
                            else
                            {
                                internalBackupResult = currentBackupResult;
                            }
                        }
                    }
                    else
                    {
                        // snapshot backup
                        ValidateFreeSpaceForSnapshot(tempBackupFilePath);

                        (internalBackupResult.LastDocumentEtag, internalBackupResult.LastDatabaseChangeVector) = _database.ReadLastEtagAndChangeVector();
                        internalBackupResult.LastRaftIndex = GetDatabaseEtagForBackup();
                        var databaseSummary = _database.GetDatabaseSummary();
                        var indexesCount    = _database.IndexStore.Count;

                        var totalSw          = Stopwatch.StartNew();
                        var sw               = Stopwatch.StartNew();
                        var compressionLevel = _configuration.SnapshotSettings?.CompressionLevel ?? CompressionLevel.Optimal;
                        var smugglerResult   = _database.FullBackupTo(tempBackupFilePath, compressionLevel,
                                                                      info =>
                        {
                            AddInfo(info.Message);

                            _backupResult.SnapshotBackup.ReadCount += info.FilesCount;
                            if (sw.ElapsedMilliseconds > 0 && info.FilesCount > 0)
                            {
                                AddInfo($"Backed up {_backupResult.SnapshotBackup.ReadCount} " +
                                        $"file{(_backupResult.SnapshotBackup.ReadCount > 1 ? "s" : string.Empty)}");
                                sw.Restart();
                            }
                        }, TaskCancelToken.Token);

                        EnsureSnapshotProcessed(databaseSummary, smugglerResult, indexesCount);

                        AddInfo($"Backed up {_backupResult.SnapshotBackup.ReadCount} files, " +
                                $"took: {totalSw.ElapsedMilliseconds:#,#;;0}ms");
                    }

                    IOExtensions.RenameFile(tempBackupFilePath, backupFilePath);

                    status.LocalBackup.Exception = null;
                }
                catch (Exception e)
                {
                    status.LocalBackup.Exception = e.ToString();

                    // deleting the temp backup file if the backup failed
                    DeleteFile(tempBackupFilePath);
                    throw;
                }
            }

            if (_backupToLocalFolder)
            {
                var sp = Stopwatch.StartNew();
                var localRetentionPolicy = new LocalRetentionPolicyRunner(_retentionPolicyParameters, _configuration.LocalSettings.FolderPath);
                localRetentionPolicy.Execute();
                sp.Stop();
                status.LocalRetentionDurationInMs = sp.ElapsedMilliseconds;
            }

            return(internalBackupResult);
        }
예제 #3
0
        private InternalBackupResult CreateLocalBackupOrSnapshot(
            PeriodicBackupStatus status, string backupFilePath, long?startDocumentEtag, long?startRaftIndex)
        {
            var internalBackupResult = new InternalBackupResult();

            using (status.LocalBackup.UpdateStats(_isFullBackup))
            {
                try
                {
                    // will rename the file after the backup is finished
                    var tempBackupFilePath = backupFilePath + InProgressExtension;

                    BackupTypeValidation();

                    if (_configuration.BackupType == BackupType.Backup ||
                        _configuration.BackupType == BackupType.Snapshot && _isFullBackup == false)
                    {
                        var backupType     = _configuration.BackupType == BackupType.Snapshot ? "snapshot " : string.Empty;
                        var backupSizeType = _isFullBackup ? "a full" : "an incremental";
                        AddInfo($"Started {backupSizeType} {backupType}backup");

                        // smuggler backup
                        var options = new DatabaseSmugglerOptionsServerSide
                        {
                            AuthorizationStatus = AuthorizationStatus.DatabaseAdmin,
                        };
                        if (_isFullBackup == false)
                        {
                            options.OperateOnTypes |= DatabaseItemType.Tombstones;
                            options.OperateOnTypes |= DatabaseItemType.CompareExchangeTombstones;
                        }

                        var currentBackupResult = CreateBackup(options, tempBackupFilePath, startDocumentEtag, startRaftIndex);

                        if (_isFullBackup)
                        {
                            internalBackupResult = currentBackupResult;
                        }
                        else
                        {
                            if (_backupResult.GetLastEtag() == _previousBackupStatus.LastEtag && _backupResult.GetLastRaftIndex() == _previousBackupStatus.LastRaftIndex.LastEtag)
                            {
                                internalBackupResult.LastDocumentEtag = startDocumentEtag ?? 0;
                                internalBackupResult.LastRaftIndex    = startRaftIndex ?? 0;
                            }
                            else
                            {
                                internalBackupResult = currentBackupResult;
                            }
                        }
                    }
                    else
                    {
                        // snapshot backup
                        AddInfo("Started a snapshot backup");

                        internalBackupResult.LastDocumentEtag = _database.ReadLastEtag();
                        internalBackupResult.LastRaftIndex    = GetDatabaseEtagForBackup();
                        var databaseSummary = _database.GetDatabaseSummary();
                        var indexesCount    = _database.IndexStore.Count;

                        var totalSw        = Stopwatch.StartNew();
                        var sw             = Stopwatch.StartNew();
                        var smugglerResult = _database.FullBackupTo(tempBackupFilePath,
                                                                    info =>
                        {
                            AddInfo(info.Message);

                            _backupResult.SnapshotBackup.ReadCount += info.FilesCount;
                            if (sw.ElapsedMilliseconds > 0 && info.FilesCount > 0)
                            {
                                AddInfo($"Backed up {_backupResult.SnapshotBackup.ReadCount} " +
                                        $"file{(_backupResult.SnapshotBackup.ReadCount > 1 ? "s" : string.Empty)}");
                                sw.Restart();
                            }
                        }, TaskCancelToken.Token);

                        EnsureSnapshotProcessed(databaseSummary, smugglerResult, indexesCount);

                        AddInfo($"Backed up {_backupResult.SnapshotBackup.ReadCount} files, " +
                                $"took: {totalSw.ElapsedMilliseconds:#,#;;0}ms");
                    }

                    IOExtensions.RenameFile(tempBackupFilePath, backupFilePath);
                }
                catch (Exception e)
                {
                    status.LocalBackup.Exception = e.ToString();
                    throw;
                }
            }

            if (_backupToLocalFolder)
            {
                var localRetentionPolicy = new LocalRetentionPolicyRunner(_retentionPolicyParameters, _configuration.LocalSettings.FolderPath);
                localRetentionPolicy.Execute();
            }

            return(internalBackupResult);
        }