Beispiel #1
0
        public async Task incremental_and_full_backup_encrypted_db_and_restore_to_encrypted_DB_with_provided_key()
        {
            var defaultS3Settings = GetS3Settings();
            var key = EncryptedServer(out var certificates, out string dbName);

            using (var store = GetDocumentStore(new Options
            {
                AdminCertificate = certificates.ServerCertificate.Value,
                ClientCertificate = certificates.ServerCertificate.Value,
                ModifyDatabaseName = s => dbName,
                ModifyDatabaseRecord = record => record.Encrypted = true,
                Path = NewDataPath()
            }))
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User
                    {
                        Name = "oren"
                    }, "users/1");
                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType = BackupType.Backup,
                    S3Settings = defaultS3Settings,
                    IncrementalBackupFrequency = "0 */6 * * *",
                    BackupEncryptionSettings = new BackupEncryptionSettings
                    {
                        Key = "OI7Vll7DroXdUORtc6Uo64wdAk1W0Db9ExXXgcg5IUs=",
                        EncryptionMode = EncryptionMode.UseProvidedKey
                    }
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));
                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);

                var value = WaitForValue(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(operation);
                    return getPeriodicBackupResult.Status?.LastEtag;
                }, 1);
                Assert.Equal(1, value);

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");
                    await session.StoreAsync(new User { Name = "ayende" }, "users/3");

                    session.CountersFor("users/2").Increment("downloads", 200);

                    await session.SaveChangesAsync();
                }

                var lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));
                value = WaitForValue(() => store.Maintenance.Send(operation).Status.LastEtag, lastEtag);
                Assert.Equal(lastEtag, value);

                var backupStatus = store.Maintenance.Send(operation);
                var databaseName = $"restored_database-{Guid.NewGuid()}";

                var subfolderS3Settings = GetS3Settings(backupStatus.Status.FolderName);

                using (RestoreDatabaseFromCloud(store, new RestoreFromS3Configuration
                {
                    Settings = subfolderS3Settings,
                    DatabaseName = databaseName,
                    EncryptionKey = "OI7Vll7DroXdUORtc6Uo64wdAk1W0Db9ExXXgcg5IUs=",
                    BackupEncryptionSettings = new BackupEncryptionSettings
                    {
                        Key = "OI7Vll7DroXdUORtc6Uo64wdAk1W0Db9ExXXgcg5IUs=",
                        EncryptionMode = EncryptionMode.UseProvidedKey
                    }
                }))
                {
                    using (var session = store.OpenSession(databaseName))
                    {
                        var users = session.Load<User>("users/1");
                        Assert.NotNull(users);
                        users = session.Load<User>("users/2");
                        Assert.NotNull(users);
                    }
                }
            }
        }
Beispiel #2
0
        public async Task can_backup_to_directory_multiple_backups_with_long_interval()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                var periodicBackupRunner = (await GetDocumentDatabaseInstanceFor(store)).PeriodicBackupRunner;

                // get by reflection the maxTimerTimeoutInMilliseconds field
                // this field is the maximum interval acceptable in .Net's threading timer
                // if the requested backup interval is bigger than this maximum interval,
                // a timer with maximum interval will be used several times until the interval cumulatively
                // will be equal to requested interval
                typeof(PeriodicBackupRunner)
                .GetField(nameof(PeriodicBackupRunner.MaxTimerTimeout), BindingFlags.Instance | BindingFlags.Public)
                .SetValue(periodicBackupRunner, TimeSpan.FromMilliseconds(100));

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                SpinWait.SpinUntil(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(operation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, TimeSpan.FromSeconds(15));

                var etagForBackups = store.Maintenance.Send(operation).Status.LastEtag;
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    await session.SaveChangesAsync();
                }

                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                SpinWait.SpinUntil(() =>
                {
                    var newLastEtag = store.Maintenance.Send(operation).Status.LastEtag;
                    return(newLastEtag != etagForBackups);
                }, TimeSpan.FromSeconds(15));
            }

            using (var store = GetDocumentStore(new Options
            {
                ModifyDatabaseName = s => $"{s}_2"
            }))
            {
                await store.Smuggler.ImportIncrementalAsync(new DatabaseSmugglerImportOptions(),
                                                            Directory.GetDirectories(backupPath).First());

                using (var session = store.OpenAsyncSession())
                {
                    var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                    Assert.True(users.Any(x => x.Value.Name == "oren"));
                    Assert.True(users.Any(x => x.Value.Name == "ayende"));
                }
            }
        }
Beispiel #3
0
        protected async Task incremental_and_full_backup_encrypted_db_and_restore_to_encrypted_DB_with_database_key_internal()
        {
            var defaultS3Settings = GetS3Settings();

            var key = EncryptedServer(out var certificates, out string dbName);

            using (var store = GetDocumentStore(new Options
            {
                AdminCertificate = certificates.ServerCertificate.Value,
                ClientCertificate = certificates.ServerCertificate.Value,
                ModifyDatabaseName = s => dbName,
                ModifyDatabaseRecord = record => record.Encrypted = true,
                Path = NewDataPath()
            }))
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User
                    {
                        Name = "oren"
                    }, "users/1");

                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType = BackupType.Backup,
                    S3Settings = defaultS3Settings,
                    IncrementalBackupFrequency = "0 */6 * * *",
                    BackupEncryptionSettings   = new BackupEncryptionSettings
                    {
                        EncryptionMode = EncryptionMode.UseDatabaseKey
                    }
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);

                PeriodicBackupStatus backupStatus = null;
                var value = WaitForValue(() =>
                {
                    backupStatus = store.Maintenance.Send(operation).Status;
                    return(backupStatus?.LastEtag);
                }, expectedVal: 1, timeout: 30_000);
                Assert.True(1 == value, $"gotStatus? {backupStatus != null}, Status Error: {backupStatus?.Error?.Exception}," +
                            $" S3 Error: {backupStatus?.UploadToS3?.Exception}, LocalBackup Exception: {backupStatus?.LocalBackup?.Exception}");

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    await session.StoreAsync(new User { Name = "ayende" }, "users/3");

                    session.CountersFor("users/2").Increment("downloads", 200);

                    await session.SaveChangesAsync();
                }

                var lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                value = WaitForValue(() =>
                {
                    backupStatus = store.Maintenance.Send(operation).Status;
                    return(backupStatus?.LastEtag);
                }, expectedVal: lastEtag, timeout: 30_000);
                Assert.True(lastEtag == value, $"gotStatus? {backupStatus != null}, Status Error: {backupStatus?.Error?.Exception}," +
                            $" S3 Error: {backupStatus?.UploadToS3?.Exception}, LocalBackup Exception: {backupStatus?.LocalBackup?.Exception}");

                var databaseName = $"restored_database-{Guid.NewGuid()}";

                var subfolderS3Settings = GetS3Settings(backupStatus.FolderName);

                using (RestoreDatabaseFromCloud(store, new RestoreFromS3Configuration
                {
                    Settings = subfolderS3Settings,
                    DatabaseName = databaseName,
                    BackupEncryptionSettings = new BackupEncryptionSettings
                    {
                        Key = key,
                        EncryptionMode = EncryptionMode.UseProvidedKey
                    }
                }))
                {
                    using (var session = store.OpenSession(databaseName))
                    {
                        var users = session.Load <User>("users/1");
                        Assert.NotNull(users);
                        users = session.Load <User>("users/2");
                        Assert.NotNull(users);
                    }
                }
            }
        }
Beispiel #4
0
        public async Task CanImportTombstonesFromIncrementalBackup()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "fitzchak" }, "users/1");

                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                Assert.True(SpinWait.SpinUntil(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(operation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, TimeSpan.FromSeconds(15)));

                var etagForBackups = store.Maintenance.Send(operation).Status.LastEtag;
                using (var session = store.OpenAsyncSession())
                {
                    session.Delete("users/1");
                    await session.SaveChangesAsync();
                }

                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                Assert.True(SpinWait.SpinUntil(() =>
                {
                    var newLastEtag = store.Maintenance.Send(operation).Status.LastEtag;
                    return(newLastEtag != etagForBackups);
                }, TimeSpan.FromSeconds(15)));
            }

            using (var store = GetDocumentStore(new Options
            {
                ModifyDatabaseName = s => $"{s}_2"
            }))
            {
                await store.Smuggler.ImportIncrementalAsync(new DatabaseSmugglerImportOptions(),
                                                            Directory.GetDirectories(backupPath).First());

                using (var session = store.OpenAsyncSession())
                {
                    var user = await session.LoadAsync <User>("users/1");

                    Assert.Null(user);
                }
            }
        }
Beispiel #5
0
        public async Task can_backup_and_restore_snapshot()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    await session.SaveChangesAsync();
                }

                using (var session = store.OpenAsyncSession())
                {
                    await session
                    .Query <User>()
                    .Where(x => x.Name == "oren")
                    .ToListAsync();     // create an index to backup

                    await session
                    .Query <User>()
                    .Where(x => x.Age > 20)
                    .ToListAsync();     // create an index to backup
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType    = BackupType.Snapshot,
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                SpinWait.SpinUntil(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(operation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, TimeSpan.FromSeconds(15));

                var etagForBackups = store.Maintenance.Send(operation).Status.LastEtag;
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    await session.StoreAsync(new User { Name = "ayende" }, "users/3");

                    await session.SaveChangesAsync();
                }

                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                SpinWait.SpinUntil(() =>
                {
                    var newLastEtag = store.Maintenance.Send(operation).Status.LastEtag;
                    return(newLastEtag != etagForBackups);
                }, TimeSpan.FromSeconds(15));

                // restore the database with a different name
                string restoredDatabaseName = $"restored_database_snapshot-{Guid.NewGuid()}";
                using (RestoreDatabase(store, new RestoreBackupConfiguration
                {
                    BackupLocation = Directory.GetDirectories(backupPath).First(),
                    DatabaseName = restoredDatabaseName
                }))
                {
                    using (var session = store.OpenAsyncSession(restoredDatabaseName))
                    {
                        var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                        Assert.NotNull(users["users/1"]);
                        Assert.NotNull(users["users/2"]);
                        Assert.True(users.Any(x => x.Value.Name == "oren"));
                        Assert.True(users.Any(x => x.Value.Name == "ayende"));
                    }

                    var stats = await store.Maintenance.SendAsync(new GetStatisticsOperation());

                    Assert.Equal(2, stats.CountOfIndexes);
                }
            }
        }
Beispiel #6
0
        public async Task periodic_backup_should_export_starting_from_last_etag()
        {
            //http://issues.hibernatingrhinos.com/issue/RavenDB-11395

            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    await session.StoreAsync(new User { Name = "aviv" }, "users/2");

                    session.CountersFor("users/1").Increment("likes", 100);
                    session.CountersFor("users/2").Increment("downloads", 200);
                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                SpinWait.SpinUntil(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(operation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, TimeSpan.FromSeconds(15));


                var exportPath = GetBackupPath(store, backupTaskId, incremental: false);

                using (var store2 = GetDocumentStore())
                {
                    await store2.Smuggler.ImportAsync(new DatabaseSmugglerImportOptions(), exportPath);

                    var stats = await store2.Maintenance.SendAsync(new GetStatisticsOperation());

                    Assert.Equal(2, stats.CountOfDocuments);
                    Assert.Equal(2, stats.CountOfCounters);

                    using (var session = store2.OpenAsyncSession())
                    {
                        var user1 = await session.LoadAsync <User>("users/1");

                        var user2 = await session.LoadAsync <User>("users/2");

                        Assert.Equal("oren", user1.Name);
                        Assert.Equal("aviv", user2.Name);

                        var dic = await session.CountersFor(user1).GetAllAsync();

                        Assert.Equal(1, dic.Count);
                        Assert.Equal(100, dic["likes"]);

                        dic = await session.CountersFor(user2).GetAllAsync();

                        Assert.Equal(1, dic.Count);
                        Assert.Equal(200, dic["downloads"]);
                    }
                }

                var etagForBackups = store.Maintenance.Send(operation).Status.LastEtag;
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/3");

                    session.CountersFor("users/3").Increment("votes", 300);
                    await session.SaveChangesAsync();
                }

                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                SpinWait.SpinUntil(() =>
                {
                    var newLastEtag = store.Maintenance.Send(operation).Status.LastEtag;
                    return(newLastEtag != etagForBackups);
                }, TimeSpan.FromSeconds(15));

                exportPath = GetBackupPath(store, backupTaskId);

                using (var store3 = GetDocumentStore())
                {
                    // importing to a new database, in order to verify that
                    // periodic backup imports only the changed documents (and counters)

                    await store3.Smuggler.ImportAsync(new DatabaseSmugglerImportOptions(), exportPath);

                    var stats = await store3.Maintenance.SendAsync(new GetStatisticsOperation());

                    Assert.Equal(1, stats.CountOfDocuments);
                    Assert.Equal(1, stats.CountOfCounters);

                    using (var session = store3.OpenAsyncSession())
                    {
                        var user3 = await session.LoadAsync <User>("users/3");

                        Assert.Equal("ayende", user3.Name);

                        var dic = await session.CountersFor(user3).GetAllAsync();

                        Assert.Equal(1, dic.Count);
                        Assert.Equal(300, dic["votes"]);
                    }
                }
            }
        }
        public async Task ExportFullThanDeleteAttachmentAndCreateAnotherOneThanExportIncrementalThanImport()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore(new Options
            {
                ModifyDatabaseName = s => $"{s}_store1"
            }))
            {
                using (var session = store.OpenSession())
                {
                    session.Store(new User
                    {
                        Name = "Fitzchak"
                    }, "users/1");
                    session.SaveChanges();
                }

                using (var stream = new MemoryStream(new byte[] { 1, 2, 3 }))
                    store.Operations.Send(new PutAttachmentOperation("users/1", "file1", stream, "image/png"));

                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };
                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                SpinWait.SpinUntil(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(operation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, TimeSpan.FromSeconds(15));

                var etagForBackups = store.Maintenance.Send(operation).Status.LastEtag;
                store.Operations.Send(new DeleteAttachmentOperation("users/1", "file1"));
                using (var stream = new MemoryStream(new byte[] { 4, 5, 6 }))
                    store.Operations.Send(new PutAttachmentOperation("users/1", "file2", stream, "image/png"));

                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                var stats = await store.Maintenance.SendAsync(new GetStatisticsOperation());

                Assert.Equal(1, stats.CountOfDocuments);
                Assert.Equal(1, stats.CountOfAttachments);
                Assert.Equal(1, stats.CountOfUniqueAttachments);

                SpinWait.SpinUntil(() =>
                {
                    var newLastEtag = store.Maintenance.Send(operation).Status.LastEtag;
                    return(newLastEtag != etagForBackups);
                }, TimeSpan.FromMinutes(2));
            }

            using (var store = GetDocumentStore(new Options
            {
                ModifyDatabaseName = s => $"{s}_store2"
            }))
            {
                await store.Smuggler.ImportIncrementalAsync(new DatabaseSmugglerImportOptions(), Directory.GetDirectories(backupPath).First());

                var stats = await store.Maintenance.SendAsync(new GetStatisticsOperation());

                Assert.Equal(1, stats.CountOfDocuments);
                Assert.Equal(1, stats.CountOfAttachments);
                Assert.Equal(1, stats.CountOfUniqueAttachments);

                using (var session = store.OpenSession())
                {
                    var user = session.Load <User>("users/1");

                    var metadata = session.Advanced.GetMetadataFor(user);
                    Assert.Equal(DocumentFlags.HasAttachments.ToString(), metadata[Constants.Documents.Metadata.Flags]);
                    var attachment = metadata.GetObjects(Constants.Documents.Metadata.Attachments).Single();
                    Assert.Equal("file2", attachment.GetString(nameof(AttachmentName.Name)));
                }
            }
        }
Beispiel #8
0
        static async Task MainInternal()
        {
            using (var docStore = new DocumentStore
            {
                Urls = new[] { "http://127.0.0.1:8080" },
                Database = "Products"
            }.Initialize())
            {
                #region logical_full_backup_every_3_hours
                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        //Backup files local path
                        FolderPath = @"E:\RavenBackups"
                    },

                    //Full Backup period (Cron expression for a 3-hours period)
                    FullBackupFrequency = "0 */3 * * *",

                    //Type can be Backup or Snapshot
                    BackupType = BackupType.Backup,

                    //Task Name
                    Name = "fullBackupTask",
                };
                var operation = new UpdatePeriodicBackupOperation(config);
                var result    = await docStore.Maintenance.SendAsync(operation);

                #endregion
            }


            using (var docStore = new DocumentStore
            {
                Urls = new[] { "http://127.0.0.1:8080" },
                Database = "Products"
            }.Initialize())
            {
                #region encrypted_logical_full_backup
                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        //Backup files local path
                        FolderPath = @"E:\RavenBackups"
                    },

                    //Full Backup period (Cron expression for a 3-hours period)
                    FullBackupFrequency = "0 */3 * * *",

                    //Type can be Backup or Snapshot
                    BackupType = BackupType.Backup,

                    //Task Name
                    Name = "fullBackupTask"
                };
                var operation = new UpdatePeriodicBackupOperation(config);
                var result    = await docStore.Maintenance.SendAsync(operation);

                #endregion
            }

            using (var docStore = new DocumentStore
            {
                Urls = new[] { "http://127.0.0.1:8080" },
                Database = "Products"
            }.Initialize())
            {
                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = @"E:\RavenBackups"
                    },

                    #region backup_type_snapshot
                    //Type can be Backup or Snapshot
                    BackupType = BackupType.Snapshot,
                    #endregion

                    #region backup_full_backup
                    //Full Backup period (Cron expression for a 6-hours period)
                    FullBackupFrequency = "0 */6 * * *",
                    #endregion

                    #region backup_incremental_backup
                    //Cron expression: set incremental backup period ("*/20 * * * *" is a 20-minutes period)
                    IncrementalBackupFrequency = "*/20 * * * *",
                    #endregion
                };
            }
            using (var docStore = new DocumentStore
            {
                Urls = new[] { "http://127.0.0.1:8080" },
                Database = "Products"
            }.Initialize())
            {
                #region backup_remote_destinations
                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = @"E:\RavenBackups"
                    },

                    //FTP Backup settings
                    FtpSettings = new FtpSettings
                    {
                        Url      = "192.168.10.4",
                        Port     = 8080,
                        UserName = "******",
                        Password = "******"
                    },

                    //Azure Backup settings
                    AzureSettings = new AzureSettings
                    {
                        StorageContainer = "storageContainer",
                        RemoteFolderName = "remoteFolder",
                        AccountName      = "JohnAccount",
                        AccountKey       = "key"
                    }
                };
                var operation = new UpdatePeriodicBackupOperation(config);
                var result    = await docStore.Maintenance.SendAsync(operation);

                #endregion
            }

            using (var docStore = new DocumentStore
            {
                Urls = new[] { "http://127.0.0.1:8080" },
                Database = "Products"
            }.Initialize())
            {
                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = @"E:\RavenBackups"
                    },

                    //FTP Backup settings
                    FtpSettings = new FtpSettings
                    {
                        Url      = "192.168.10.4",
                        Port     = 8080,
                        UserName = "******",
                        Password = "******"
                    },

                    //Azure Backup settings
                    AzureSettings = new AzureSettings
                    {
                        StorageContainer = "storageContainer",
                        RemoteFolderName = "remoteFolder",
                        AccountName      = "JohnAccount",
                        AccountKey       = "key"
                    }
                };
                #region initiate_immediate_backup_execution
                var operation = new UpdatePeriodicBackupOperation(config);
                var result    = await docStore.Maintenance.SendAsync(operation);

                //run a backup task immediately
                await docStore.Maintenance.SendAsync(new StartBackupOperation(true, result.TaskId));

                #endregion

                #region get_backup_execution_results
                //Provide GetPeriodicBackupStatusOperation with the task ID returned by RavenDB
                var backupStatus = new GetPeriodicBackupStatusOperation(result.TaskId);
                #endregion
            }


            using (var docStore = new DocumentStore
            {
                Urls = new[] { "http://127.0.0.1:8080" },
                Database = "Products"
            }.Initialize())
            {
                #region restore_to_single_node
                var restoreConfiguration = new RestoreBackupConfiguration();

                //New database name
                restoreConfiguration.DatabaseName = "newProductsDatabase";

                //Local path with a backup file
                var backupPath = @"C:\Users\RavenDB\backups\2018-12-26-16-17.ravendb-Products-A-backup";
                restoreConfiguration.BackupLocation = backupPath;

                var restoreBackupTask = new RestoreBackupOperation(restoreConfiguration);
                docStore.Maintenance.Server.Send(restoreBackupTask);
                #endregion

                #region restore_disable_ongoing_tasks_false
                //Disable or Enable ongoing tasks after restoration.
                //Default setting is FALSE, so tasks DO run when backup is restored.
                restoreConfiguration.DisableOngoingTasks = false;
                #endregion

                #region restore_last_file_name_to_restore
                //Last incremental backup file to restore from
                restoreConfiguration.LastFileNameToRestore = @"2018-12-26-12-00.ravendb-incremental-backup";
                #endregion

                #region restore_to_specific__data_directory
                //Restore to a pre-chosen folder
                var dataPath = @"C:\Users\RavenDB\backups\2018-12-26-16-17.ravendb-Products-A-backup\restoredDatabaseLocation";
                restoreConfiguration.DataDirectory = dataPath;
                #endregion

                #region restore_disable_ongoing_tasks_true
                //Do or do not run ongoing tasks after restoration.
                //Default setting is FALSE, to allow tasks' execution when backup is restored.
                restoreConfiguration.DisableOngoingTasks = true;
                #endregion
            }

            #region encrypted_database
            // path to the certificate you received during the server setup
            var cert = new X509Certificate2(@"C:\Users\RavenDB\authentication_key\admin.client.certificate.RavenDBdom.pfx");
            using (var docStore = new DocumentStore
            {
                Urls = new[] { "https://a.RavenDBdom.development.run" },
                Database = "encryptedDatabase",
                Certificate = cert
            }.Initialize())
            {
                // Backup & Restore here
            }
            #endregion

            // path to the authentication key you received during the server setup
            cert = new X509Certificate2(@"C:\Users\RavenDB\authentication_key\admin.client.certificate.RavenDBdom.pfx");
            using (var docStore = new DocumentStore
            {
                Urls = new[] { "https://a.RavenDBdom.development.run" },
                Database = "encryptedDatabase",
                Certificate = cert
            }.Initialize())
            {
                #region restore_encrypted_database
                // restore encrypted database

                // restore configuration
                var restoreConfiguration = new RestoreBackupConfiguration();

                //New database name
                restoreConfiguration.DatabaseName = "newEncryptedDatabase";

                //Backup-file location
                var backupPath = @"C:\Users\RavenDB\2019-01-06-11-11.ravendb-encryptedDatabase-A-snapshot";
                restoreConfiguration.BackupLocation = backupPath;

                restoreConfiguration.EncryptionKey = "1F0K2R/KkcwbkK7n4kYlv5eqisy/pMnSuJvZ2sJ/EKo=";

                var restoreBackupTask = new RestoreBackupOperation(restoreConfiguration);
                docStore.Maintenance.Server.Send(restoreBackupTask);
                #endregion
            }
        }
Beispiel #9
0
        public async Task can_backup_and_restore()
        {
            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    session.CountersFor("users/1").Increment("likes", 100);
                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType                 = BackupType.Backup,
                    GoogleCloudSettings        = GoogleCloudFact.GoogleCloudSettings,
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                var value     = WaitForValue(() =>
                {
                    var status = store.Maintenance.Send(operation).Status;
                    return(status?.LastEtag);
                }, 4);
                Assert.Equal(4, value);

                var backupStatus      = store.Maintenance.Send(operation);
                var backupOperationId = backupStatus.Status.LastOperationId;

                var backupOperation = store.Maintenance.Send(new GetOperationStateOperation(backupOperationId.Value));

                var backupResult = backupOperation.Result as BackupResult;
                Assert.True(backupResult.Counters.Processed);
                Assert.Equal(1, backupResult.Counters.ReadCount);

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    session.CountersFor("users/2").Increment("downloads", 200);

                    await session.SaveChangesAsync();
                }

                var lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                value = WaitForValue(() => store.Maintenance.Send(operation).Status.LastEtag, lastEtag);
                Assert.Equal(lastEtag, value);

                // restore the database with a different name
                var databaseName = $"restored_database-{Guid.NewGuid()}";

                GoogleCloudFact.GoogleCloudSettings.RemoteFolderName = $"{backupStatus.Status.FolderName}";
                var restoreFromGoogleCloudConfiguration = new RestoreFromGoogleCloudConfiguration()
                {
                    DatabaseName = databaseName,
                    Settings     = GoogleCloudFact.GoogleCloudSettings
                };
                var googleCloudOperation = new RestoreBackupOperation(restoreFromGoogleCloudConfiguration);
                var restoreOperation     = store.Maintenance.Server.Send(googleCloudOperation);

                restoreOperation.WaitForCompletion(TimeSpan.FromSeconds(30));
                {
                    using (var session = store.OpenAsyncSession(databaseName))
                    {
                        var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                        Assert.True(users.Any(x => x.Value.Name == "oren"));
                        Assert.True(users.Any(x => x.Value.Name == "ayende"));

                        var val = await session.CountersFor("users/1").GetAsync("likes");

                        Assert.Equal(100, val);
                        val = await session.CountersFor("users/2").GetAsync("downloads");

                        Assert.Equal(200, val);
                    }

                    var originalDatabase = await Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                    var restoredDatabase = await Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(databaseName);

                    using (restoredDatabase.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx))
                        using (ctx.OpenReadTransaction())
                        {
                            var databaseChangeVector = DocumentsStorage.GetDatabaseChangeVector(ctx);
                            Assert.Equal($"A:7-{originalDatabase.DbBase64Id}, A:8-{restoredDatabase.DbBase64Id}", databaseChangeVector);
                        }
                }
            }
        }
Beispiel #10
0
        public async Task can_backup_to_directory_multiple_backups()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var result = await store.Admin.Server.SendAsync(new UpdatePeriodicBackupOperation(config, store.Database));

                var periodicBackupTaskId = result.TaskId;

                var operation = new GetPeriodicBackupStatusOperation(store.Database, periodicBackupTaskId);
                SpinWait.SpinUntil(() =>
                {
                    var getPeriodicBackupResult = store.Admin.Server.Send(operation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, TimeSpan.FromMinutes(2));

                var etagForBackups = store.Admin.Server.Send(operation).Status.LastEtag;
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    await session.SaveChangesAsync();
                }

                SpinWait.SpinUntil(() =>
                {
                    var newLastEtag = store.Admin.Server.Send(operation).Status.LastEtag;
                    return(newLastEtag != etagForBackups);
                }, TimeSpan.FromMinutes(2));
            }

            using (var store = GetDocumentStore(new Options
            {
                ModifyDatabaseName = s => $"{s}_2"
            }))
            {
                await store.Smuggler.ImportIncrementalAsync(new DatabaseSmugglerImportOptions(),
                                                            Directory.GetDirectories(backupPath).First());

                using (var session = store.OpenAsyncSession())
                {
                    var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                    Assert.True(users.Any(x => x.Value.Name == "oren"));
                    Assert.True(users.Any(x => x.Value.Name == "ayende"));
                }
            }
        }
Beispiel #11
0
        public async Task can_backup_and_restore_snapshot()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType    = BackupType.Snapshot,
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var result = await store.Admin.Server.SendAsync(new UpdatePeriodicBackupOperation(config, store.Database));

                var periodicBackupTaskId = result.TaskId;

                var operation = new GetPeriodicBackupStatusOperation(store.Database, periodicBackupTaskId);
                SpinWait.SpinUntil(() =>
                {
                    var getPeriodicBackupResult = store.Admin.Server.Send(operation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, TimeSpan.FromMinutes(2));

                var etagForBackups = store.Admin.Server.Send(operation).Status.LastEtag;
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    await session.StoreAsync(new User { Name = "ayende" }, "users/3");

                    await session.SaveChangesAsync();
                }

                SpinWait.SpinUntil(() =>
                {
                    var newLastEtag = store.Admin.Server.Send(operation).Status.LastEtag;
                    return(newLastEtag != etagForBackups);
                }, TimeSpan.FromMinutes(2));

                // restore the database with a different name
                const string restoredDatabaseName = "restored_database_snapshot";
                var          restoreConfiguration = new RestoreBackupConfiguration
                {
                    BackupLocation = Directory.GetDirectories(backupPath).First(),
                    DatabaseName   = restoredDatabaseName
                };
                var restoreBackupTask = new RestoreBackupOperation(restoreConfiguration);
                var restoreResult     = store.Admin.Server.Send(restoreBackupTask);
                var stateRequest      = new GetOperationStateOperation(restoreResult.OperationId, true);
                store.Admin.Server.Send(stateRequest);

                SpinWait.SpinUntil(() =>
                {
                    var state = store.Admin.Server.Send(stateRequest);
                    return(state.Status == OperationStatus.Completed);
                }, TimeSpan.FromMinutes(2));

                using (var session = store.OpenAsyncSession(restoredDatabaseName))
                {
                    var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                    Assert.True(users.Any(x => x.Value.Name == "oren"));
                    Assert.True(users.Any(x => x.Value.Name == "ayende"));
                }
            }
        }
Beispiel #12
0
        public async Task CanCreateBackupUsingConfigurationFromBackupScript()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                var scriptPath   = Path.Combine(Path.GetTempPath(), Path.ChangeExtension(Guid.NewGuid().ToString(), ".ps1"));
                var localSetting = new LocalSettings
                {
                    Disabled   = false,
                    FolderPath = backupPath,
                };

                var localSettingsString = JsonConvert.SerializeObject(localSetting);

                string command;
                string script;

                if (PlatformDetails.RunningOnPosix)
                {
                    command = "bash";
                    script  = $"#!/bin/bash\r\necho '{localSettingsString}'";
                    File.WriteAllText(scriptPath, script);
                    Process.Start("chmod", $"700 {scriptPath}");
                }
                else
                {
                    command = "powershell";
                    script  = $"echo '{localSettingsString}'";
                    File.WriteAllText(scriptPath, script);
                }

                var putConfiguration = new ServerWideBackupConfiguration
                {
                    Disabled                   = false,
                    FullBackupFrequency        = "0 2 * * 0",
                    IncrementalBackupFrequency = "0 2 * * 1",
                    LocalSettings              = new LocalSettings
                    {
                        GetBackupConfigurationScript = new GetBackupConfigurationScript
                        {
                            Exec      = command,
                            Arguments = scriptPath
                        }
                    }
                };

                await store.Maintenance.Server.SendAsync(new PutServerWideBackupConfigurationOperation(putConfiguration));

                var record = await store.Maintenance.Server.SendAsync(new GetDatabaseRecordOperation(store.Database));

                var backupTask = record.PeriodicBackups.First();
                Assert.Null(backupTask.LocalSettings.FolderPath);
                Assert.NotNull(backupTask.LocalSettings.GetBackupConfigurationScript);
                Assert.NotNull(backupTask.LocalSettings.GetBackupConfigurationScript.Exec);
                Assert.NotNull(backupTask.LocalSettings.GetBackupConfigurationScript.Arguments);

                var backupTaskId = backupTask.TaskId;
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new Company { Name = "Hibernating Rhinos" }, "companies/1");

                    await session.SaveChangesAsync();
                }

                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                var value     = WaitForValue(() =>
                {
                    var status = store.Maintenance.Send(operation).Status;
                    return(status?.LastEtag);
                }, 1);
                Assert.Equal(1, value);
            }
        }
Beispiel #13
0
        public async Task ServerWideBackupShouldBackupIdleDatabase(int rounds)
        {
            const string fullBackupFrequency = "*/2 * * * *";
            var          backupParser        = CrontabSchedule.Parse(fullBackupFrequency);
            const int    maxIdleTimeInSec    = 10;

            using var server = GetNewServer(new ServerCreationOptions
            {
                CustomSettings = new Dictionary <string, string>
                {
                    [RavenConfiguration.GetKey(x => x.Databases.MaxIdleTime)]             = $"{maxIdleTimeInSec}",
                    [RavenConfiguration.GetKey(x => x.Databases.FrequencyToCheckForIdle)] = "3",
                    [RavenConfiguration.GetKey(x => x.Core.RunInMemory)] = "false"
                }
            });
            using var dispose = new DisposableAction(() => server.ServerStore.DatabasesLandlord.SkipShouldContinueDisposeCheck = false);
            server.ServerStore.DatabasesLandlord.SkipShouldContinueDisposeCheck = true;

            var dbName             = GetDatabaseName();
            var controlgroupDbName = GetDatabaseName() + "controlgroup";
            var baseBackupPath     = NewDataPath(suffix: "BackupFolder");

            using var store = new DocumentStore { Database = dbName, Urls = new[] { server.WebUrl } }.Initialize();
            store.Maintenance.Server.Send(new CreateDatabaseOperation(new DatabaseRecord(dbName)));
            store.Maintenance.Server.Send(new CreateDatabaseOperation(new DatabaseRecord(controlgroupDbName)));
            await using var keepControlGroupAlive = new RepeatableAsyncAction(async token =>
            {
                await store.Maintenance.ForDatabase(controlgroupDbName).SendAsync(new GetStatisticsOperation(), token);
                await Task.Delay(TimeSpan.FromSeconds(maxIdleTimeInSec), token);
            }).Run();

            using (var session = store.OpenAsyncSession())
            {
                await session.StoreAsync(new User { Name = "EGOR" }, "su");

                await session.SaveChangesAsync();
            }
            using (var session = store.OpenAsyncSession(controlgroupDbName))
            {
                await session.StoreAsync(new User { Name = "egor" }, "susu");

                await session.SaveChangesAsync();
            }

            var      first           = true;
            DateTime backupStartTime = default;
            GetPeriodicBackupStatusOperation periodicBackupStatusOperation = null;
            PeriodicBackupStatus             status             = null;
            PeriodicBackupStatus             controlGroupStatus = null;

            for (int i = 0; i < rounds; i++)
            {
                // let db get idle
                await WaitForValueAsync(() => Task.FromResult(server.ServerStore.IdleDatabases.Count > 0), true, 180 * 1000, 3000);

                Assert.True(1 == server.ServerStore.IdleDatabases.Count, $"IdleDatabasesCount({server.ServerStore.IdleDatabases.Count}), Round({i})");
                Assert.True(server.ServerStore.IdleDatabases.ContainsKey(store.Database), $"Round({i})");

                DateTime lastBackup;
                if (first)
                {
                    var putConfiguration = new ServerWideBackupConfiguration
                    {
                        FullBackupFrequency = fullBackupFrequency,
                        LocalSettings       = new LocalSettings {
                            FolderPath = baseBackupPath
                        },
                    };
                    var result = await store.Maintenance.Server.SendAsync(new PutServerWideBackupConfigurationOperation(putConfiguration));

                    backupStartTime = DateTime.UtcNow;

                    var serverWideConfiguration = await store.Maintenance.Server.SendAsync(new GetServerWideBackupConfigurationOperation(result.Name));

                    Assert.NotNull(serverWideConfiguration);
                    periodicBackupStatusOperation = new GetPeriodicBackupStatusOperation(serverWideConfiguration.TaskId);

                    // the configuration is applied to existing databases
                    var periodicBackupConfigurations = (await store.Maintenance.Server.SendAsync(new GetDatabaseRecordOperation(store.Database))).PeriodicBackups;
                    Assert.Equal(1, periodicBackupConfigurations.Count);
                    var backupConfigurations = (await store.Maintenance.Server.SendAsync(new GetDatabaseRecordOperation(controlgroupDbName))).PeriodicBackups;
                    Assert.Equal(1, backupConfigurations.Count);

                    first      = false;
                    lastBackup = backupStartTime;
                }
                else
                {
                    Assert.True(status.LastFullBackup.HasValue);
                    lastBackup = status.LastFullBackup.Value;
                }
                var nextBackup = backupParser.GetNextOccurrence(lastBackup);
                await Task.Delay(nextBackup - DateTime.UtcNow);

                status = await AssertWaitForNextBackup(store.Database, status);

                controlGroupStatus = await AssertWaitForNextBackup(controlgroupDbName, controlGroupStatus);

                async Task <PeriodicBackupStatus> AssertWaitForNextBackup(string db, PeriodicBackupStatus prevStatus)
                {
                    PeriodicBackupStatus nextStatus = null;

                    Assert.True(await WaitForValueAsync(async() =>
                    {
                        nextStatus = (await store.Maintenance.ForDatabase(db).SendAsync(periodicBackupStatusOperation)).Status;
                        if (nextStatus == null)
                        {
                            return(false);
                        }
                        Assert.True(nextStatus.Error?.Exception == null, nextStatus.Error?.Exception);
                        Assert.True(nextStatus.LocalBackup?.Exception == null, nextStatus.LocalBackup?.Exception);

                        return(prevStatus == null || nextStatus.LastOperationId.HasValue && nextStatus.LastOperationId > prevStatus.LastOperationId);
                    }, true), $"Round {i}");
                    return(nextStatus);
                }

                var backupsDir = Directory.GetDirectories(baseBackupPath);
                Assert.Equal(2, backupsDir.Length);

                AssertBackupDirCount(controlgroupDbName, controlGroupStatus);
                AssertBackupDirCount(store.Database, status);
                void AssertBackupDirCount(string db, PeriodicBackupStatus periodicBackupStatus)
                {
                    var backupPath = Path.Combine(baseBackupPath, db);
                    var backupDirs = Directory.GetDirectories(backupPath);

                    Assert.True(i + 1 == backupDirs.Length,
                                $"firstBackupStartTime: {backupStartTime}, checkTime: {DateTime.UtcNow}, i: {i}, " +
                                $"controlGroupBackupNum: {backupDirs.Length}, path: {backupPath}, {PrintBackups(periodicBackupStatus, backupDirs)}");
                }
            }
        }
Beispiel #14
0
        public async Task snapshot_encrypted_db_and_restore_to_encrypted_DB()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            var key = EncryptedServer(out var certificates, out string dbName);

            var defaultS3Settings = GetS3Settings();

            using (var store = GetDocumentStore(new Options
            {
                AdminCertificate = certificates.ServerCertificate.Value,
                ClientCertificate = certificates.ServerCertificate.Value,
                ModifyDatabaseName = s => dbName,
                ModifyDatabaseRecord = record => record.Encrypted = true,
                Path = NewDataPath()
            }))
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User
                    {
                        Name = "oren"
                    }, "users/1");
                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType = BackupType.Snapshot,
                    S3Settings = defaultS3Settings,
                    IncrementalBackupFrequency = "0 */6 * * *"
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));
                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);

                var value = WaitForValue(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(operation);
                    return getPeriodicBackupResult.Status?.LastEtag;
                }, 1);
                Assert.Equal(1, value);

                var backupStatus = store.Maintenance.Send(operation);
                var databaseName = $"restored_database-{Guid.NewGuid()}";

                var subfolderS3Settings = GetS3Settings(backupStatus.Status.FolderName);

                using (RestoreDatabaseFromCloud(store, new RestoreFromS3Configuration
                {
                    Settings = subfolderS3Settings,
                    DatabaseName = databaseName,
                    EncryptionKey = key,
                    BackupEncryptionSettings = new BackupEncryptionSettings
                    {
                        EncryptionMode = EncryptionMode.UseDatabaseKey
                    }
                }))
                {
                    using (var session = store.OpenSession(databaseName))
                    {
                        var users = session.Load<User>("users/1");
                        Assert.NotNull(users);
                    }
                }
            }
        }
Beispiel #15
0
        public async Task IncludeArtificialDocuments_Backup_ShouldWork()
        {
            using (var store = GetDocumentStore())
            {
                new MapReduce_WithOutput().Execute(store);

                using (var session = store.OpenSession())
                {
                    session.Store(new Company
                    {
                        Name = "HR"
                    });

                    session.SaveChanges();
                }

                WaitForIndexing(store);

                string artificialDocumentId = null;

                Assert.True(WaitForValue(() =>
                {
                    using (var session = store.OpenSession())
                    {
                        var result           = session.Query <MapReduce_WithOutput.Result>().SingleOrDefault();
                        artificialDocumentId = result.Id;
                        return(result != null);
                    }
                }, true));

                Assert.NotNull(artificialDocumentId);

                var toFolderWithArtificial = Path.Combine(NewDataPath(), "BackupFolder");

                var config = new PeriodicBackupConfiguration
                {
                    BackupType    = BackupType.Backup,
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = toFolderWithArtificial
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (store.Maintenance.Send(new UpdatePeriodicBackupOperation(config))).TaskId;
                store.Maintenance.Send(new StartBackupOperation(true, backupTaskId));
                var getPeriodicBackupStatusOperation = new GetPeriodicBackupStatusOperation(backupTaskId);

                Assert.True(WaitForValue(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(getPeriodicBackupStatusOperation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, true));

                toFolderWithArtificial = Directory.GetDirectories(toFolderWithArtificial).First();
                var toDatabaseName = store.Database + "_restored";

                using (RestoreDatabase(store, new RestoreBackupConfiguration
                {
                    BackupLocation = toFolderWithArtificial,
                    DatabaseName = toDatabaseName,
                    SkipIndexes = true
                }))
                {
                    using (var session = store.OpenSession(toDatabaseName))
                    {
                        Assert.Null(session.Load <MapReduce_WithOutput.Result>(artificialDocumentId));
                    }
                }

                var importOptionsWithoutArtificial = new DatabaseSmugglerImportOptions();
                var importOptionsWithArtificial    = new DatabaseSmugglerImportOptions {
                    IncludeArtificial = true
                };

                importOptionsWithoutArtificial.OperateOnTypes |= ~DatabaseItemType.Indexes;
                importOptionsWithArtificial.OperateOnTypes    |= ~DatabaseItemType.Indexes;

                var toFileWithArtificial = Directory.GetFiles(toFolderWithArtificial).First();

                // artificial in file
                // include artificial is false
                using (var innerStore = GetDocumentStore())
                {
                    var operation = await innerStore.Smuggler.ImportAsync(importOptionsWithoutArtificial, toFileWithArtificial);

                    await operation.WaitForCompletionAsync(TimeSpan.FromSeconds(30));

                    using (var session = innerStore.OpenSession())
                    {
                        Assert.Null(session.Load <MapReduce_WithOutput.Result>(artificialDocumentId));
                    }
                }

                // artificial in file
                // include artificial is true
                using (var innerStore = GetDocumentStore())
                {
                    var operation = await innerStore.Smuggler.ImportAsync(importOptionsWithArtificial, toFileWithArtificial);

                    await operation.WaitForCompletionAsync(TimeSpan.FromSeconds(30));

                    using (var session = innerStore.OpenSession())
                    {
                        Assert.NotNull(session.Load <MapReduce_WithOutput.Result>(artificialDocumentId));
                    }
                }
            }
        }
Beispiel #16
0
        protected async Task incremental_and_full_check_last_file_for_backup_internal()
        {
            var defaultS3Settings = GetS3Settings();

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "user-1" }, "users/1");

                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType = BackupType.Backup,
                    S3Settings = defaultS3Settings,
                    IncrementalBackupFrequency = "0 */6 * * *",
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);

                PeriodicBackupStatus backupStatus = null;
                var value = WaitForValue(() =>
                {
                    backupStatus = store.Maintenance.Send(operation).Status;
                    return(backupStatus?.LastEtag);
                }, expectedVal: 1, timeout: 30_000);
                Assert.True(1 == value, $"gotStatus? {backupStatus != null}, Status Error: {backupStatus?.Error?.Exception}," +
                            $" S3 Error: {backupStatus?.UploadToS3?.Exception}, LocalBackup Exception: {backupStatus?.LocalBackup?.Exception}");

                var operationStatus = WaitForValue(() =>
                {
                    var backupOperation = store.Maintenance.Send(new GetOperationStateOperation(backupStatus.LastOperationId.Value));
                    return(backupOperation.Status);
                }, OperationStatus.Completed);
                Assert.Equal(OperationStatus.Completed, operationStatus);

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "user-2" }, "users/2");

                    await session.SaveChangesAsync();
                }

                var lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                value = WaitForValue(() =>
                {
                    backupStatus = store.Maintenance.Send(operation).Status;
                    return(backupStatus?.LastEtag);
                }, expectedVal: lastEtag, timeout: 30_000);
                Assert.True(lastEtag == value, $"gotStatus? {backupStatus != null}, Status Error: {backupStatus?.Error?.Exception}," +
                            $" S3 Error: {backupStatus?.UploadToS3?.Exception}, LocalBackup Exception: {backupStatus?.LocalBackup?.Exception}");

                Assert.Equal(OperationStatus.Completed, WaitForValue(() =>
                {
                    var backupOperation = store.Maintenance.Send(new GetOperationStateOperation(backupStatus.LastOperationId.Value));
                    return(backupOperation.Status);
                }, OperationStatus.Completed));

                string lastFileToRestore;
                using (var client = new RavenAwsS3Client(defaultS3Settings))
                {
                    var fullBackupPath = $"{defaultS3Settings.RemoteFolderName}/{backupStatus.FolderName}";
                    lastFileToRestore = (await client.ListObjectsAsync(fullBackupPath, string.Empty, false)).FileInfoDetails.Last().FullPath;
                }

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "user-3" }, "users/3");

                    await session.SaveChangesAsync();
                }

                lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                value = WaitForValue(() =>
                {
                    backupStatus = store.Maintenance.Send(operation).Status;
                    return(backupStatus?.LastEtag);
                }, expectedVal: lastEtag, timeout: 30_000);
                Assert.True(lastEtag == value, $"gotStatus? {backupStatus != null}, Status Error: {backupStatus?.Error?.Exception}," +
                            $" S3 Error: {backupStatus?.UploadToS3?.Exception}, LocalBackup Exception: {backupStatus?.LocalBackup?.Exception}");

                var databaseName = $"restored_database-{Guid.NewGuid()}";

                var subfolderS3Settings = GetS3Settings(backupStatus.FolderName);

                using (RestoreDatabaseFromCloud(store,
                                                new RestoreFromS3Configuration
                {
                    Settings = subfolderS3Settings,
                    DatabaseName = databaseName,
                    LastFileNameToRestore = lastFileToRestore
                }))
                {
                    using (var session = store.OpenSession(databaseName))
                    {
                        var users = session.Load <User>("users/1");
                        Assert.NotNull(users);
                        users = session.Load <User>("users/2");
                        Assert.NotNull(users);
                        users = session.Load <User>("users/3");
                        Assert.Null(users);
                    }
                }
            }
        }
Beispiel #17
0
        public async Task can_backup_and_restore()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    session.CountersFor("users/1").Increment("likes", 100);
                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType    = BackupType.Backup,
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                SpinWait.SpinUntil(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(operation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, TimeSpan.FromSeconds(15));

                var backupStatus      = store.Maintenance.Send(operation);
                var backupOperationId = backupStatus.Status.LastOperationId;

                var backupOperation = store.Maintenance.Send(new GetOperationStateOperation(backupOperationId.Value));

                var backupResult = backupOperation.Result as BackupResult;
                Assert.True(backupResult.Counters.Processed);
                Assert.Equal(1, backupResult.Counters.ReadCount);

                var etagForBackups = backupStatus.Status.LastEtag;
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    session.CountersFor("users/2").Increment("downloads", 200);

                    await session.SaveChangesAsync();
                }

                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                SpinWait.SpinUntil(() =>
                {
                    var newLastEtag = store.Maintenance.Send(operation).Status.LastEtag;
                    return(newLastEtag != etagForBackups);
                }, TimeSpan.FromSeconds(15));

                // restore the database with a different name
                string databaseName = $"restored_database-{Guid.NewGuid()}";

                using (RestoreDatabase(store, new RestoreBackupConfiguration
                {
                    BackupLocation = Directory.GetDirectories(backupPath).First(),
                    DatabaseName = databaseName
                }))
                {
                    using (var session = store.OpenAsyncSession(databaseName))
                    {
                        var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                        Assert.True(users.Any(x => x.Value.Name == "oren"));
                        Assert.True(users.Any(x => x.Value.Name == "ayende"));

                        var val = await session.CountersFor("users/1").GetAsync("likes");

                        Assert.Equal(100, val);
                        val = await session.CountersFor("users/2").GetAsync("downloads");

                        Assert.Equal(200, val);
                    }
                }
            }
        }
Beispiel #18
0
        public async Task can_create_azure_snapshot_and_restore_using_restore_point()
        {
            using (var holder = new Azure.AzureClientHolder(AzureFactAttribute.AzureSettings))
            {
                using (var store = GetDocumentStore())
                {
                    using (var session = store.OpenSession())
                    {
                        session.Store(new User {
                            Name = "oren"
                        }, "users/1");
                        session.CountersFor("users/1").Increment("likes", 100);
                        session.SaveChanges();
                    }

                    var config = new PeriodicBackupConfiguration
                    {
                        BackupType    = BackupType.Snapshot,
                        AzureSettings = holder.Settings,
                        IncrementalBackupFrequency = "0 0 1 1 *"
                    };

                    var backupTaskId = (store.Maintenance.Send(new UpdatePeriodicBackupOperation(config))).TaskId;
                    store.Maintenance.Send(new StartBackupOperation(true, backupTaskId));
                    var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                    PeriodicBackupStatus status = null;
                    var value = WaitForValue(() =>
                    {
                        status = store.Maintenance.Send(operation).Status;
                        return(status?.LastEtag);
                    }, 4);
                    Assert.True(4 == value, $"4 == value, Got status: {status != null}, exception: {status?.Error?.Exception}");
                    Assert.True(status.LastOperationId != null, $"status.LastOperationId != null, Got status: {status != null}, exception: {status?.Error?.Exception}");

                    var client   = store.GetRequestExecutor().HttpClient;
                    var data     = new StringContent(JsonConvert.SerializeObject(holder.Settings), Encoding.UTF8, "application/json");
                    var response = await client.PostAsync(store.Urls.First() + "/admin/restore/points?type=Azure ", data);

                    string result        = response.Content.ReadAsStringAsync().Result;
                    var    restorePoints = JsonConvert.DeserializeObject <RestorePoints>(result);
                    Assert.Equal(1, restorePoints.List.Count);
                    var point = restorePoints.List.First();

                    var databaseName = $"restored_database-{Guid.NewGuid()}";
                    holder.Settings.RemoteFolderName = holder.Settings.RemoteFolderName + "/" + status.FolderName;
                    var restoreOperation = await store.Maintenance.Server.SendAsync(new RestoreBackupOperation(new RestoreFromAzureConfiguration()
                    {
                        DatabaseName = databaseName,
                        Settings = holder.Settings,
                        DisableOngoingTasks = true,
                        LastFileNameToRestore = point.FileName,
                    }));

                    await restoreOperation.WaitForCompletionAsync(TimeSpan.FromSeconds(60));

                    using (var store2 = GetDocumentStore(new Options()
                    {
                        CreateDatabase = false, ModifyDatabaseName = s => databaseName
                    }))
                    {
                        using (var session = store2.OpenSession(databaseName))
                        {
                            var users = session.Load <User>(new[] { "users/1", "users/2" });
                            Assert.True(users.Any(x => x.Value.Name == "oren"));

                            var val = session.CountersFor("users/1").Get("likes");
                            Assert.Equal(100, val);
                        }

                        var originalDatabase = Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database).Result;
                        var restoredDatabase = Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(databaseName).Result;
                        using (restoredDatabase.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx))
                            using (ctx.OpenReadTransaction())
                            {
                                var databaseChangeVector = DocumentsStorage.GetDatabaseChangeVector(ctx);
                                Assert.Equal($"A:4-{originalDatabase.DbBase64Id}", databaseChangeVector);
                            }
                    }
                }
            }
        }
Beispiel #19
0
        public void FullBackupShouldBackupDocumentTombstones()
        {
            using var store = GetDocumentStore();

            // create 3 docs
            using (var session = store.OpenSession())
            {
                for (int i = 1; i <= 3; i++)
                {
                    session.Store(new DummyDoc {
                        DummyString = $"{i}"
                    }, $"{nameof(DummyDoc)}/{i}");
                }

                session.SaveChanges();
            }

            // create 3 CompareExchanges
            var rhinoceros = store.Operations.Send(new PutCompareExchangeValueOperation <DummyDoc>("emojis/Rhinoceros", new DummyDoc {
                DummyString = "🦏"
            }, 0));

            Assert.True(rhinoceros.Successful);
            var shark = store.Operations.Send(new PutCompareExchangeValueOperation <DummyDoc>("emojis/Shark", new DummyDoc {
                DummyString = "🦈"
            }, 0));

            Assert.True(shark.Successful);
            var bird = store.Operations.Send(new PutCompareExchangeValueOperation <DummyDoc>("emojis/Bird", new DummyDoc {
                DummyString = "🐦"
            }, 0));

            Assert.True(bird.Successful);

            // create 1 tombstone
            using (var session = store.OpenSession())
            {
                session.Delete($"{nameof(DummyDoc)}/{new Random().Next(1, 3)}");
                session.SaveChanges();
            }

            // create 1 CompareExchange tombstone
            var res = store.Operations.Send(new DeleteCompareExchangeValueOperation <DummyDoc>($"emojis/Rhinoceros", rhinoceros.Index));

            Assert.True(res.Successful);

            // run full backup
            var config = new PeriodicBackupConfiguration
            {
                LocalSettings = new LocalSettings
                {
                    FolderPath = NewDataPath(forceCreateDir: true)
                },
                Name = "full backup with tombstones",
                FullBackupFrequency = "0 0 1 1 *",
                BackupType          = BackupType.Backup
            };

            var documentDb = Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

            (long etag, _) = documentDb.Result.ReadLastEtagAndChangeVector();

            var result = store.Maintenance.Send(new UpdatePeriodicBackupOperation(config));

            store.Maintenance.Send(new StartBackupOperation(true, result.TaskId));

            var operation = new GetPeriodicBackupStatusOperation(result.TaskId);
            PeriodicBackupStatus status = null;
            var value = WaitForValue(() =>
            {
                status = store.Maintenance.Send(operation).Status;
                return(status?.LastEtag);
            }, expectedVal: etag);

            Assert.True(etag == value, $"gotStatus? {status != null}, Status Error: {status?.Error?.Exception}, LocalBackup Exception: {status?.LocalBackup?.Exception}");
            Assert.NotNull(status.LocalBackup);

            var backupPath     = status.LocalBackup.BackupDirectory;
            var restoredDbName = GetDatabaseName();

            using (RestoreDatabase(store, new RestoreBackupConfiguration
            {
                BackupLocation = backupPath,
                DatabaseName = restoredDbName
            }))
            {
                var stats = store.Maintenance.ForDatabase(restoredDbName).Send(new GetDetailedStatisticsOperation());
                Assert.Equal(2, stats.CountOfDocuments);
                Assert.Equal(1, stats.CountOfTombstones);
                Assert.Equal(2, stats.CountOfCompareExchange);

                // we don't put the Compare Exchange tombstones into the schema, on backup restore.
                Assert.Equal(0, stats.CountOfCompareExchangeTombstones);
            }
        }
Beispiel #20
0
        private void can_backup_and_restore_internal(bool oneTimeBackup)
        {
            using (var holder = new Azure.AzureClientHolder(AzureFactAttribute.AzureSettings))
            {
                using (var store = GetDocumentStore())
                {
                    using (var session = store.OpenSession())
                    {
                        session.Store(new User {
                            Name = "oren"
                        }, "users/1");
                        session.CountersFor("users/1").Increment("likes", 100);
                        session.SaveChanges();
                    }

                    PeriodicBackupStatus status = null;
                    long backupTaskId           = 0;
                    GetPeriodicBackupStatusOperation operation = null;
                    BackupResult backupResult = null;
                    if (oneTimeBackup == false)
                    {
                        var config = new PeriodicBackupConfiguration {
                            BackupType = BackupType.Backup, AzureSettings = holder.Settings, IncrementalBackupFrequency = "0 0 1 1 *"
                        };
                        backupTaskId = (store.Maintenance.Send(new UpdatePeriodicBackupOperation(config))).TaskId;
                        operation    = new GetPeriodicBackupStatusOperation(backupTaskId);
                        store.Maintenance.Send(new StartBackupOperation(true, backupTaskId));

                        var value = WaitForValue(() =>
                        {
                            status = store.Maintenance.Send(operation).Status;
                            return(status?.LastEtag);
                        }, 4);
                        Assert.True(4 == value, $"4 == value, Got status: {status != null}, exception: {status?.Error?.Exception}");
                        Assert.True(status.LastOperationId != null, $"status.LastOperationId != null, Got status: {status != null}, exception: {status?.Error?.Exception}");

                        OperationState backupOperation = null;
                        var            operationStatus = WaitForValue(() =>
                        {
                            backupOperation = store.Maintenance.Send(new GetOperationStateOperation(status.LastOperationId.Value));
                            return(backupOperation.Status);
                        }, OperationStatus.Completed);
                        Assert.Equal(OperationStatus.Completed, operationStatus);

                        backupResult = backupOperation.Result as BackupResult;
                        Assert.NotNull(backupResult);
                        Assert.True(backupResult.Counters.Processed, "backupResult.Counters.Processed");
                        Assert.Equal(1, backupResult.Counters.ReadCount);
                    }

                    using (var session = store.OpenSession())
                    {
                        session.Store(new User {
                            Name = "ayende"
                        }, "users/2");
                        session.CountersFor("users/2").Increment("downloads", 200);

                        session.SaveChanges();
                    }

                    if (oneTimeBackup == false)
                    {
                        var lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                        store.Maintenance.Send(new StartBackupOperation(false, backupTaskId));
                        var value2 = WaitForValue(() => store.Maintenance.Send(operation).Status.LastEtag, lastEtag);
                        Assert.Equal(lastEtag, value2);
                    }

                    if (oneTimeBackup)
                    {
                        var backupConfiguration = new BackupConfiguration
                        {
                            BackupType    = BackupType.Backup,
                            AzureSettings = holder.Settings,
                        };

                        backupResult = (BackupResult)store.Maintenance.Send(new BackupOperation(backupConfiguration)).WaitForCompletion(TimeSpan.FromSeconds(15));
                        Assert.True(backupResult != null && backupResult.Counters.Processed, "backupResult != null && backupResult.Counters.Processed");
                        Assert.Equal(2, backupResult.Counters.ReadCount);
                    }

                    // restore the database with a different name
                    var databaseName = $"restored_database-{Guid.NewGuid()}";

                    holder.Settings.RemoteFolderName = oneTimeBackup ? $"{holder.Settings.RemoteFolderName}/{backupResult.LocalBackup.BackupDirectory}" : $"{holder.Settings.RemoteFolderName}/{status.FolderName}";
                    var restoreFromGoogleCloudConfiguration = new RestoreFromAzureConfiguration()
                    {
                        DatabaseName        = databaseName,
                        Settings            = holder.Settings,
                        DisableOngoingTasks = true
                    };
                    var googleCloudOperation = new RestoreBackupOperation(restoreFromGoogleCloudConfiguration);
                    var restoreOperation     = store.Maintenance.Server.Send(googleCloudOperation);

                    restoreOperation.WaitForCompletion(TimeSpan.FromSeconds(30));
                    using (var store2 = GetDocumentStore(new Options()
                    {
                        CreateDatabase = false, ModifyDatabaseName = s => databaseName
                    }))
                    {
                        using (var session = store2.OpenSession(databaseName))
                        {
                            var users = session.Load <User>(new[] { "users/1", "users/2" });
                            Assert.True(users.Any(x => x.Value.Name == "oren"));
                            Assert.True(users.Any(x => x.Value.Name == "ayende"));

                            var val = session.CountersFor("users/1").Get("likes");
                            Assert.Equal(100, val);
                            val = session.CountersFor("users/2").Get("downloads");
                            Assert.Equal(200, val);
                        }

                        var originalDatabase = Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database).Result;
                        var restoredDatabase = Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(databaseName).Result;
                        using (restoredDatabase.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx))
                            using (ctx.OpenReadTransaction())
                            {
                                var databaseChangeVector = DocumentsStorage.GetDatabaseChangeVector(ctx);
                                Assert.Contains($"A:7-{originalDatabase.DbBase64Id}", databaseChangeVector);
                                Assert.Contains($"A:8-{restoredDatabase.DbBase64Id}", databaseChangeVector);
                            }
                    }
                }
            }
        }
Beispiel #21
0
        public async Task ShouldWork()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore(new Options
            {
                ModifyDatabaseRecord = record => record.Settings[RavenConfiguration.GetKey(x => x.PerformanceHints.MaxNumberOfResults)] = "1"
            }))
            {
                await store.Maintenance.SendAsync(new CreateSampleDataOperation());

                WaitForIndexing(store);

                using (var session = store.OpenAsyncSession())
                {
                    await session.Query <Employee>().ToListAsync(); // this will generate performance hint
                }

                var database = await GetDatabase(store.Database);

                database.NotificationCenter.Paging.UpdatePaging(null);

                int beforeBackupAlertCount;
                using (database.NotificationCenter.GetStored(out var actions))
                    beforeBackupAlertCount = actions.Count();

                Assert.True(beforeBackupAlertCount > 0);

                var beforeBackupStats = store.Maintenance.Send(new GetStatisticsOperation());

                var config = new PeriodicBackupConfiguration
                {
                    BackupType    = BackupType.Snapshot,
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (store.Maintenance.Send(new UpdatePeriodicBackupOperation(config))).TaskId;
                store.Maintenance.Send(new StartBackupOperation(true, backupTaskId));
                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                await WaitForValueAsync(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(operation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, true);

                // restore the database with a different name
                var restoredDatabaseName = GetDatabaseName();

                string backupLocation      = Directory.GetDirectories(backupPath).First();
                var    filesInBackupFolder = Directory.GetFiles(backupLocation);
                Assert.True(filesInBackupFolder.Where(RestorePointsBase.IsBackupOrSnapshot).Any(),
                            $"The backup folder \"{backupLocation}\" contains no backup or snapshot files.\n{string.Join(", ","filesInBackupFolder")}");
                using (RestoreDatabase(store, new RestoreBackupConfiguration
                {
                    BackupLocation = backupLocation,
                    DatabaseName = restoredDatabaseName
                }))
                {
                    var afterRestoreStats = store.Maintenance.ForDatabase(restoredDatabaseName).Send(new GetStatisticsOperation());

                    var restoredDatabase = await GetDatabase(restoredDatabaseName);

                    int afterRestoreAlertCount;
                    using (restoredDatabase.NotificationCenter.GetStored(out var actions))
                        afterRestoreAlertCount = actions.Count();

                    Assert.True(afterRestoreAlertCount > 0);

                    var indexesPath      = restoredDatabase.Configuration.Indexing.StoragePath;
                    var indexesDirectory = new DirectoryInfo(indexesPath.FullPath);
                    Assert.True(indexesDirectory.Exists);
                    Assert.Equal(afterRestoreStats.CountOfIndexes, indexesDirectory.GetDirectories().Length);

                    Assert.NotEqual(beforeBackupStats.DatabaseId, afterRestoreStats.DatabaseId);
                    Assert.Equal(beforeBackupStats.CountOfAttachments, afterRestoreStats.CountOfAttachments);
                    Assert.Equal(beforeBackupStats.CountOfConflicts, afterRestoreStats.CountOfConflicts);
                    Assert.Equal(beforeBackupStats.CountOfDocuments, afterRestoreStats.CountOfDocuments);
                    Assert.Equal(beforeBackupStats.CountOfDocumentsConflicts, afterRestoreStats.CountOfDocumentsConflicts);
                    Assert.Equal(beforeBackupStats.CountOfIndexes, afterRestoreStats.CountOfIndexes);
                    Assert.Equal(beforeBackupStats.CountOfRevisionDocuments, afterRestoreStats.CountOfRevisionDocuments);
                    Assert.Equal(beforeBackupStats.CountOfTombstones, afterRestoreStats.CountOfTombstones);
                    Assert.Equal(beforeBackupStats.CountOfUniqueAttachments, afterRestoreStats.CountOfUniqueAttachments);
                }
            }
        }
        public async Task periodic_backup_should_work_with_long_intervals()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                var periodicBackupRunner = (await GetDocumentDatabaseInstanceFor(store)).PeriodicBackupRunner;

                // get by reflection the maxTimerTimeoutInMilliseconds field
                // this field is the maximum interval acceptable in .Net's threading timer
                // if the requested backup interval is bigger than this maximum interval,
                // a timer with maximum interval will be used several times until the interval cumulatively
                // will be equal to requested interval
                typeof(PeriodicBackupRunner)
                .GetField(nameof(PeriodicBackupRunner.MaxTimerTimeout), BindingFlags.Instance | BindingFlags.Public)
                .SetValue(periodicBackupRunner, TimeSpan.FromMilliseconds(100));

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren 1" }, "users/1");

                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType    = BackupType.Backup,
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                var value     = WaitForValue(() =>
                {
                    var status = store.Maintenance.Send(operation).Status;
                    return(status?.LastEtag);
                }, 1);
                Assert.Equal(1, value);

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren 2" }, "users/2");

                    await session.SaveChangesAsync();
                }

                var lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                value = WaitForValue(() => store.Maintenance.Send(operation).Status.LastEtag, lastEtag);
                Assert.Equal(lastEtag, value);
            }

            using (var store = GetDocumentStore(new Options
            {
                ModifyDatabaseName = s => $"{s}_2"
            }))
            {
                await store.Smuggler.ImportIncrementalAsync(new DatabaseSmugglerImportOptions(),
                                                            Directory.GetDirectories(backupPath).First());

                using (var session = store.OpenAsyncSession())
                {
                    var user = await session.LoadAsync <User>("users/1");

                    Assert.Equal("oren 1", user.Name);

                    user = await session.LoadAsync <User>("users/2");

                    Assert.Equal("oren 2", user.Name);
                }
            }
        }
Beispiel #23
0
        public async Task can_restore_smuggler_correctly()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                SpinWait.SpinUntil(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(operation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, TimeSpan.FromSeconds(15));

                var etagForBackups = store.Maintenance.Send(operation).Status.LastEtag;
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    await session.SaveChangesAsync();
                }

                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                SpinWait.SpinUntil(() =>
                {
                    var newLastEtag = store.Maintenance.Send(operation).Status.LastEtag;
                    return(newLastEtag != etagForBackups);
                }, TimeSpan.FromSeconds(15));
            }

            using (var store1 = GetDocumentStore(new Options
            {
                ModifyDatabaseName = s => $"{s}_2"
            }))
                using (var store2 = GetDocumentStore(new Options
                {
                    ModifyDatabaseName = s => $"{s}_2"
                }))
                {
                    var backupDirectory = Directory.GetDirectories(backupPath).First();

                    var backupToMovePath = $"{backupPath}{Path.DirectorySeparatorChar}IncrementalBackupTemp";
                    Directory.CreateDirectory(backupToMovePath);
                    var incrementalBackupFile = Directory.GetFiles(backupDirectory).OrderBackups().Last();
                    var fileName = Path.GetFileName(incrementalBackupFile);
                    File.Move(incrementalBackupFile, $"{backupToMovePath}{Path.DirectorySeparatorChar}{fileName}");

                    await store1.Smuggler.ImportIncrementalAsync(new DatabaseSmugglerImportOptions(), backupDirectory);

                    using (var session = store1.OpenAsyncSession())
                    {
                        var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                        var keyValuePair = users.First();
                        Assert.NotNull(keyValuePair.Value);
                        Assert.True(keyValuePair.Value.Name == "oren" && keyValuePair.Key == "users/1");
                        Assert.Null(users.Last().Value);
                    }

                    await store2.Smuggler.ImportIncrementalAsync(new DatabaseSmugglerImportOptions(), backupToMovePath);

                    using (var session = store2.OpenAsyncSession())
                    {
                        var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                        Assert.Null(users.First().Value);
                        var keyValuePair = users.Last();
                        Assert.NotNull(keyValuePair.Value);
                        Assert.True(keyValuePair.Value.Name == "ayende" && keyValuePair.Key == "users/2");
                    }
                }
        }
        public async Task can_backup_to_directory_multiple_backups()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                var value     = WaitForValue(() =>
                {
                    var status = store.Maintenance.Send(operation).Status;
                    return(status?.LastEtag);
                }, 1);
                Assert.Equal(1, value);

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    await session.SaveChangesAsync();
                }

                var lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                value = WaitForValue(() => store.Maintenance.Send(operation).Status.LastEtag, lastEtag);
                Assert.Equal(lastEtag, value);
            }

            using (var store = GetDocumentStore(new Options
            {
                ModifyDatabaseName = s => $"{s}_2"
            }))
            {
                await store.Smuggler.ImportIncrementalAsync(new DatabaseSmugglerImportOptions(),
                                                            Directory.GetDirectories(backupPath).First());

                using (var session = store.OpenAsyncSession())
                {
                    var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                    Assert.True(users.Any(x => x.Value.Name == "oren"));
                    Assert.True(users.Any(x => x.Value.Name == "ayende"));
                }
            }
        }
Beispiel #25
0
        public async Task restore_settings_tests()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore(new Options
            {
                ModifyDatabaseName = s => $"{s}_2"
            }))
            {
                var restoreConfiguration = new RestoreBackupConfiguration();

                var restoreBackupTask = new RestoreBackupOperation(restoreConfiguration);
                var e = Assert.Throws <RavenException>(() => store.Maintenance.Server.Send(restoreBackupTask));
                Assert.Contains("Database name can't be null or empty", e.InnerException.Message);

                restoreConfiguration.DatabaseName = store.Database;
                restoreBackupTask = new RestoreBackupOperation(restoreConfiguration);
                e = Assert.Throws <RavenException>(() => store.Maintenance.Server.Send(restoreBackupTask));
                Assert.Contains("Cannot restore data to an existing database", e.InnerException.Message);

                restoreConfiguration.DatabaseName = "test-" + Guid.NewGuid();
                restoreBackupTask = new RestoreBackupOperation(restoreConfiguration);
                e = Assert.Throws <RavenException>(() => store.Maintenance.Server.Send(restoreBackupTask));
                Assert.Contains("Backup location can't be null or empty", e.InnerException.Message);

                restoreConfiguration.BackupLocation = "this-path-doesn't-exist\\";
                restoreBackupTask = new RestoreBackupOperation(restoreConfiguration);
                e = Assert.Throws <RavenException>(() => store.Maintenance.Server.Send(restoreBackupTask));
                Assert.Contains("Backup location doesn't exist", e.InnerException.Message);

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType    = BackupType.Backup,
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                SpinWait.SpinUntil(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(operation);
                    return(getPeriodicBackupResult.Status?.LastEtag > 0);
                }, TimeSpan.FromSeconds(15));

                restoreConfiguration.BackupLocation = backupPath;
                restoreConfiguration.DataDirectory  = backupPath;
                restoreBackupTask = new RestoreBackupOperation(restoreConfiguration);
                e = Assert.Throws <RavenException>(() => store.Maintenance.Server.Send(restoreBackupTask));
                Assert.Contains("New data directory must be empty of any files or folders", e.InnerException.Message);

                var emptyFolder = NewDataPath(suffix: "BackupFolderRestore");
                restoreConfiguration.BackupLocation = backupPath;
                restoreConfiguration.DataDirectory  = emptyFolder;
            }
        }
        public async Task CanImportTombstonesFromIncrementalBackup()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "fitzchak" }, "users/1");

                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                var backupStatus = await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                var value     = WaitForValue(() =>
                {
                    var status = store.Maintenance.Send(operation).Status;
                    return(status?.LastEtag);
                }, 1);
                Assert.Equal(1, value);

                using (var session = store.OpenAsyncSession())
                {
                    session.Delete("users/1");
                    await session.SaveChangesAsync();
                }

                StartBackupOperationResult newBackupStatus;
                do
                {
                    newBackupStatus = await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));
                }
                //Race condition between reading the backup status and creating new backup
                while (newBackupStatus.OperationId == backupStatus.OperationId);

                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                value = WaitForValue(() => store.Maintenance.Send(operation).Status.LastEtag, 2);
                Assert.Equal(2, value);
            }

            using (var store = GetDocumentStore(new Options
            {
                ModifyDatabaseName = s => $"{s}_2"
            }))
            {
                await store.Smuggler.ImportIncrementalAsync(new DatabaseSmugglerImportOptions(),
                                                            Directory.GetDirectories(backupPath).First());

                using (var session = store.OpenAsyncSession())
                {
                    var user = await session.LoadAsync <User>("users/1");

                    Assert.Null(user);
                }
            }
        }
Beispiel #27
0
        protected async Task can_backup_and_restore_snapshot_internal()
        {
            var defaultS3Settings = GetS3Settings();

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    await session.SaveChangesAsync();
                }

                using (var session = store.OpenAsyncSession())
                {
                    await session
                    .Query <User>()
                    .Where(x => x.Name == "oren")
                    .ToListAsync();     // create an index to backup

                    await session
                    .Query <Order>()
                    .Where(x => x.Freight > 20)
                    .ToListAsync();                                         // create an index to backup

                    session.CountersFor("users/1").Increment("likes", 100); //create a counter to backup
                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType = BackupType.Snapshot,
                    S3Settings = defaultS3Settings,
                    IncrementalBackupFrequency = "0 0 1 1 *"
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                PeriodicBackupStatus backupStatus = null;
                var value = WaitForValue(() =>
                {
                    backupStatus = store.Maintenance.Send(operation).Status;
                    return(backupStatus?.LastEtag);
                }, expectedVal: 4, timeout: 30_000);
                Assert.True(4 == value, $"gotStatus? {backupStatus != null}, Status Error: {backupStatus?.Error?.Exception}," +
                            $" S3 Error: {backupStatus?.UploadToS3?.Exception}, LocalBackup Exception: {backupStatus?.LocalBackup?.Exception}");
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    await session.StoreAsync(new User { Name = "ayende" }, "users/3");

                    session.CountersFor("users/2").Increment("downloads", 200);

                    await session.SaveChangesAsync();
                }

                var lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                value = WaitForValue(() =>
                {
                    backupStatus = store.Maintenance.Send(operation).Status;
                    return(backupStatus?.LastEtag);
                }, expectedVal: lastEtag, timeout: 30_000);
                Assert.True(lastEtag == value, $"gotStatus? {backupStatus != null}, Status Error: {backupStatus?.Error?.Exception}," +
                            $" S3 Error: {backupStatus?.UploadToS3?.Exception}, LocalBackup Exception: {backupStatus?.LocalBackup?.Exception}");

                // restore the database with a different name
                string restoredDatabaseName = $"restored_database_snapshot-{Guid.NewGuid()}";

                var subfolderS3Settings = GetS3Settings(backupStatus.FolderName);

                using (RestoreDatabaseFromCloud(store,
                                                new RestoreFromS3Configuration
                {
                    DatabaseName = restoredDatabaseName,
                    Settings = subfolderS3Settings
                },
                                                TimeSpan.FromSeconds(60)))
                {
                    using (var session = store.OpenAsyncSession(restoredDatabaseName))
                    {
                        var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                        Assert.NotNull(users["users/1"]);
                        Assert.NotNull(users["users/2"]);
                        Assert.True(users.Any(x => x.Value.Name == "oren"));
                        Assert.True(users.Any(x => x.Value.Name == "ayende"));

                        var val = await session.CountersFor("users/1").GetAsync("likes");

                        Assert.Equal(100, val);
                        val = await session.CountersFor("users/2").GetAsync("downloads");

                        Assert.Equal(200, val);
                    }

                    var stats = await store.Maintenance.SendAsync(new GetStatisticsOperation());

                    Assert.Equal(2, stats.CountOfIndexes);

                    var originalDatabase = await Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                    var restoredDatabase = await Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(restoredDatabaseName);

                    using (restoredDatabase.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx))
                        using (ctx.OpenReadTransaction())
                        {
                            var databaseChangeVector = DocumentsStorage.GetDatabaseChangeVector(ctx);
                            Assert.Equal($"A:8-{originalDatabase.DbBase64Id}, A:10-{restoredDatabase.DbBase64Id}", databaseChangeVector);
                        }
                }
            }
        }
        public async Task can_backup_and_restore_snapshot()
        {
            var backupPath = NewDataPath(suffix: "BackupFolder");

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    await session.SaveChangesAsync();
                }

                using (var session = store.OpenAsyncSession())
                {
                    await session
                    .Query <User>()
                    .Where(x => x.Name == "oren")
                    .ToListAsync();     // create an index to backup

                    await session
                    .Query <User>()
                    .Where(x => x.Age > 20)
                    .ToListAsync();                                         // create an index to backup

                    session.CountersFor("users/1").Increment("likes", 100); //create a counter to backup
                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType    = BackupType.Snapshot,
                    LocalSettings = new LocalSettings
                    {
                        FolderPath = backupPath
                    },
                    IncrementalBackupFrequency = "* * * * *" //every minute
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                var value     = WaitForValue(() =>
                {
                    var status = store.Maintenance.Send(operation).Status;
                    return(status?.LastEtag);
                }, 3);
                Assert.Equal(3, value);

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    await session.StoreAsync(new User { Name = "ayende" }, "users/3");

                    session.CountersFor("users/2").Increment("downloads", 200);

                    await session.SaveChangesAsync();
                }

                var lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                value = WaitForValue(() => store.Maintenance.Send(operation).Status.LastEtag, lastEtag);
                Assert.Equal(lastEtag, value);

                // restore the database with a different name
                string restoredDatabaseName = $"restored_database_snapshot-{Guid.NewGuid()}";
                using (RestoreDatabase(store, new RestoreBackupConfiguration
                {
                    BackupLocation = Directory.GetDirectories(backupPath).First(),
                    DatabaseName = restoredDatabaseName
                }))
                {
                    using (var session = store.OpenAsyncSession(restoredDatabaseName))
                    {
                        var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                        Assert.NotNull(users["users/1"]);
                        Assert.NotNull(users["users/2"]);
                        Assert.True(users.Any(x => x.Value.Name == "oren"));
                        Assert.True(users.Any(x => x.Value.Name == "ayende"));

                        var val = await session.CountersFor("users/1").GetAsync("likes");

                        Assert.Equal(100, val);
                        val = await session.CountersFor("users/2").GetAsync("downloads");

                        Assert.Equal(200, val);
                    }

                    var stats = await store.Maintenance.SendAsync(new GetStatisticsOperation());

                    Assert.Equal(2, stats.CountOfIndexes);

                    var originalDatabase = await Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                    var restoredDatabase = await Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(restoredDatabaseName);

                    using (restoredDatabase.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx))
                        using (ctx.OpenReadTransaction())
                        {
                            var databaseChangeVector = DocumentsStorage.GetDatabaseChangeVector(ctx);
                            Assert.Equal($"A:3-{originalDatabase.DbBase64Id}, A:9-{restoredDatabase.DbBase64Id}", databaseChangeVector);
                        }
                }
            }
        }
Beispiel #29
0
        protected async Task can_backup_and_restore_internal()
        {
            var defaultS3Settings = GetS3Settings();

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "oren" }, "users/1");

                    session.CountersFor("users/1").Increment("likes", 100);
                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType = BackupType.Backup,
                    S3Settings = defaultS3Settings,
                    IncrementalBackupFrequency = "0 0 1 1 *"
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));

                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);
                PeriodicBackupStatus status = null;
                var value = WaitForValue(() =>
                {
                    status = store.Maintenance.Send(operation).Status;
                    return(status?.LastEtag);
                }, expectedVal: 4, timeout: 30_000);
                Assert.True(4 == value, $"gotStatus? {status != null}, Status Error: {status?.Error?.Exception}," +
                            $" S3 Error: {status?.UploadToS3?.Exception}, LocalBackup Exception: {status?.LocalBackup?.Exception}");
                Assert.True(status.LastOperationId != null, $"status.LastOperationId != null, Got status: {status != null}, exception: {status?.Error?.Exception}");

                var backupOperation = store.Maintenance.Send(new GetOperationStateOperation(status.LastOperationId.Value));

                var backupResult = backupOperation.Result as BackupResult;
                Assert.True(backupResult != null && backupResult.Counters.Processed, "backupResult != null && backupResult.Counters.Processed");
                Assert.True(1 == backupResult.Counters.ReadCount, "1 == backupResult.Counters.ReadCount");

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "ayende" }, "users/2");

                    session.CountersFor("users/2").Increment("downloads", 200);

                    await session.SaveChangesAsync();
                }

                var lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));

                value = WaitForValue(() =>
                {
                    status = store.Maintenance.Send(operation).Status;
                    return(status?.LastEtag);
                }, expectedVal: lastEtag, timeout: 30_000);
                Assert.True(lastEtag == value, $"gotStatus? {status != null}, Status Error: {status?.Error?.Exception}," +
                            $" S3 Error: {status?.UploadToS3?.Exception}, LocalBackup Exception: {status?.LocalBackup?.Exception}");

                // restore the database with a different name
                var databaseName = $"restored_database-{Guid.NewGuid()}";

                var subfolderS3Settings = GetS3Settings(status.FolderName);

                using (RestoreDatabaseFromCloud(
                           store,
                           new RestoreFromS3Configuration {
                    DatabaseName = databaseName, Settings = subfolderS3Settings, DisableOngoingTasks = true
                },
                           TimeSpan.FromSeconds(60)))
                {
                    using (var session = store.OpenAsyncSession(databaseName))
                    {
                        var users = await session.LoadAsync <User>(new[] { "users/1", "users/2" });

                        Assert.True(users.Any(x => x.Value.Name == "oren"));
                        Assert.True(users.Any(x => x.Value.Name == "ayende"));

                        var val = await session.CountersFor("users/1").GetAsync("likes");

                        Assert.Equal(100, val);
                        val = await session.CountersFor("users/2").GetAsync("downloads");

                        Assert.Equal(200, val);
                    }

                    var originalDatabase = await Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                    var restoredDatabase = await Server.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(databaseName);

                    using (restoredDatabase.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx))
                        using (ctx.OpenReadTransaction())
                        {
                            var databaseChangeVector = DocumentsStorage.GetDatabaseChangeVector(ctx);
                            Assert.Equal($"A:7-{originalDatabase.DbBase64Id}, A:8-{restoredDatabase.DbBase64Id}", databaseChangeVector);
                        }
                }
            }
        }
Beispiel #30
0
        public async Task incremental_and_full_check_last_file_for_backup()
        {
            var defaultS3Settings = GetS3Settings();

            using (var store = GetDocumentStore())
            {
                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "user-1" }, "users/1");
                    await session.SaveChangesAsync();
                }

                var config = new PeriodicBackupConfiguration
                {
                    BackupType = BackupType.Backup,
                    S3Settings = defaultS3Settings,
                    IncrementalBackupFrequency = "0 */6 * * *",
                };

                var backupTaskId = (await store.Maintenance.SendAsync(new UpdatePeriodicBackupOperation(config))).TaskId;
                await store.Maintenance.SendAsync(new StartBackupOperation(true, backupTaskId));
                var operation = new GetPeriodicBackupStatusOperation(backupTaskId);

                var value = WaitForValue(() =>
                {
                    var getPeriodicBackupResult = store.Maintenance.Send(operation);
                    return getPeriodicBackupResult.Status?.LastEtag;
                }, 1);
                Assert.Equal(1, value);

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "user-2" }, "users/2");

                    await session.SaveChangesAsync();
                }

                var lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));
                value = WaitForValue(() => store.Maintenance.Send(operation).Status.LastEtag, lastEtag);
                Assert.Equal(lastEtag, value);

                string lastFileToRestore;
                var backupStatus = store.Maintenance.Send(operation);
                using (var client = new RavenAwsS3Client(AmazonS3FactAttribute.S3Settings))
                {
                    var fullBackupPath = $"{defaultS3Settings.RemoteFolderName}/{backupStatus.Status.FolderName}";
                    lastFileToRestore = (await client.ListObjectsAsync(fullBackupPath, string.Empty, false)).FileInfoDetails.Last().FullPath;
                }

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User { Name = "user-3" }, "users/3");

                    await session.SaveChangesAsync();
                }

                lastEtag = store.Maintenance.Send(new GetStatisticsOperation()).LastDocEtag;
                await store.Maintenance.SendAsync(new StartBackupOperation(false, backupTaskId));
                value = WaitForValue(() => store.Maintenance.Send(operation).Status.LastEtag, lastEtag);
                Assert.Equal(lastEtag, value);

                backupStatus = store.Maintenance.Send(operation);
                var databaseName = $"restored_database-{Guid.NewGuid()}";

                var subfolderS3Settings = GetS3Settings(backupStatus.Status.FolderName);

                using (RestoreDatabaseFromCloud(store,
                    new RestoreFromS3Configuration
                    {
                        Settings = subfolderS3Settings,
                        DatabaseName = databaseName,
                        LastFileNameToRestore = lastFileToRestore
                    }))
                {
                    using (var session = store.OpenSession(databaseName))
                    {
                        var users = session.Load<User>("users/1");
                        Assert.NotNull(users);
                        users = session.Load<User>("users/2");
                        Assert.NotNull(users);
                        users = session.Load<User>("users/3");
                        Assert.Null(users);
                    }
                }
            }
        }