Example #1
0
        public void Can_split_merged_transaction_to_multiple_tx()
        {
            _tempDir = Guid.NewGuid().ToString();
            var storageEnvironmentOptions = StorageEnvironmentOptions.ForPath(_tempDir);

            storageEnvironmentOptions.IncrementalBackupEnabled            = true;
            storageEnvironmentOptions.MaxNumberOfPagesInMergedTransaction = 8;
            using (var envToSnapshot = new StorageEnvironment(storageEnvironmentOptions))
            {
                for (int xi = 0; xi < 100; xi++)
                {
                    using (var tx = envToSnapshot.NewTransaction(TransactionFlags.ReadWrite))
                    {
                        var tree = envToSnapshot.CreateTree(tx, "test");

                        for (int i = 0; i < 1000; i++)
                        {
                            tree.Add("users/" + i, "john doe/" + i);
                        }

                        tx.Commit();
                    }
                }

                var snapshotWriter = new MinimalIncrementalBackup();
                var backupPath     = Path.Combine(_tempDir, "1.snapshot");
                snapshotWriter.ToFile(envToSnapshot, backupPath);

                using (var stream = File.OpenRead(backupPath))
                    using (var zip = new ZipArchive(stream, ZipArchiveMode.Read))
                    {
                        Assert.True(zip.Entries.Count > 1);
                    }
            }
        }
Example #2
0
        public void Can_make_multiple_min_inc_backups_and_then_restore()
        {
            const int UserCount = 5000;

            _tempDir = Guid.NewGuid().ToString();
            var storageEnvironmentOptions = StorageEnvironmentOptions.ForPath(_tempDir);

            storageEnvironmentOptions.IncrementalBackupEnabled = true;
            using (var envToSnapshot = new StorageEnvironment(storageEnvironmentOptions))
            {
                int index = 0;
                for (int xi = 0; xi < 5; xi++)
                {
                    for (int yi = 0; yi < 2; yi++)
                    {
                        using (var tx = envToSnapshot.NewTransaction(TransactionFlags.ReadWrite))
                        {
                            var tree = envToSnapshot.CreateTree(tx, "test");

                            for (int i = 0; i < UserCount / 10; i++)
                            {
                                tree.Add("users/" + index, "john doe/" + index);
                                index++;
                            }

                            tx.Commit();
                        }
                    }
                    var snapshotWriter = new MinimalIncrementalBackup();
                    snapshotWriter.ToFile(envToSnapshot, Path.Combine(_tempDir, xi + ".snapshot"));
                }
            }

            var incremental = new IncrementalBackup();

            var restoredOptions = StorageEnvironmentOptions.ForPath(Path.Combine(_tempDir, "restored"));

            incremental.Restore(restoredOptions, Enumerable.Range(0, 5).Select(i => Path.Combine(_tempDir, i + ".snapshot")));

            using (var snapshotRestoreEnv = new StorageEnvironment(restoredOptions))
            {
                using (var tx = snapshotRestoreEnv.NewTransaction(TransactionFlags.Read))
                {
                    var tree = tx.ReadTree("test");
                    Assert.NotNull(tree);

                    for (int i = 0; i < UserCount; i++)
                    {
                        var readResult = tree.Read("users/" + i);
                        Assert.NotNull(readResult);
                        Assert.Equal("john doe/" + i, readResult.Reader.ToStringValue());
                    }
                }
            }
        }
Example #3
0
        public void Can_write_minimal_incremental_backup()
        {
            _tempDir = Guid.NewGuid().ToString();
            Directory.CreateDirectory(_tempDir);

            var snapshotWriter = new MinimalIncrementalBackup();

            snapshotWriter.ToFile(Env, Path.Combine(_tempDir, "1.snapshot"));

            Assert.True(File.Exists(Path.Combine(_tempDir, "1.snapshot")), " Even empty minimal backup should create a file");

            var snapshotFileInfo = new FileInfo(Path.Combine(_tempDir, "1.snapshot"));

            Assert.True(snapshotFileInfo.Length > 0, " Even empty minimal backup should create a file with some information");
        }
Example #4
0
        public void CreateSnapshot(long index, long term, ManualResetEventSlim allowFurtherModifications)
        {
            // we have not snapshot files, so this is the first time that we create a snapshot
            // we handle that by asking voron to create a full backup
            var files = Directory.GetFiles(_storageEnvironment.Options.BasePath, "*.Snapshot");

            Array.Sort(files, StringComparer.OrdinalIgnoreCase);             // make sure we get it in sort order
            if (files.Any() == false)
            {
                DoFullBackup(index, term, allowFurtherModifications);
                return;
            }
            var fullBackupIndex = GetFullBackupIndex(files);

            if (fullBackupIndex == -1)
            {
                // this shouldn't be the case, we must always have at least one full backup.
                // maybe user deleted it? We'll do a full backup here to compensate
                DoFullBackup(index, term, allowFurtherModifications);
                return;
            }
            string lastFullBackup = files[fullBackupIndex];

            var fullBackupSize         = new FileInfo(lastFullBackup).Length;
            var incrementalBackupsSize = files.Skip(fullBackupIndex + 1).Sum(f => new FileInfo(f).Length);

            // now we need to decide whatever to do a full or incremental backup, doing incremental backups stop
            // making sense if they will take more space than the full backup. Our cutoff point is when it passes to 50%
            // size of the full backup.
            // If full backup size is 1 GB, and we have 25 incrmeental backups that are 600 MB in size, we need to transfer
            // 1.6 GB to restore. If we generate a new full backup, we'll only need to transfer 1 GB to restore.

            if (incrementalBackupsSize / 2 > fullBackupSize)
            {
                DoFullBackup(index, term, allowFurtherModifications);
                return;
            }

            DeleteOldSnapshots(files.Take(fullBackupIndex - 1));            // delete snapshots older than the current full backup

            var incrementalBackup = new MinimalIncrementalBackup();

            incrementalBackup.ToFile(_storageEnvironment,
                                     Path.Combine(_storageEnvironment.Options.BasePath, string.Format("Inc-{0:D19}-{1:D19}.Snapshot", index, term)),
                                     infoNotify: Console.WriteLine,
                                     backupStarted: allowFurtherModifications.Set);
        }
Example #5
0
        public void Mixed_small_and_overflow_changes()
        {
            _tempDir = Guid.NewGuid().ToString();
            var storageEnvironmentOptions = StorageEnvironmentOptions.ForPath(_tempDir);

            storageEnvironmentOptions.IncrementalBackupEnabled = true;
            using (var envToSnapshot = new StorageEnvironment(storageEnvironmentOptions))
            {
                using (var tx = envToSnapshot.NewTransaction(TransactionFlags.ReadWrite))
                {
                    var tree = envToSnapshot.CreateTree(tx, "test");
                    tree.Add("users/1", "john doe");
                    tree.Add("users/2", new String('a', 5000));

                    tx.Commit();
                }

                using (var tx = envToSnapshot.NewTransaction(TransactionFlags.ReadWrite))
                {
                    var tree = envToSnapshot.CreateTree(tx, "test");
                    tree.Add("users/2", "jane darling");
                    tree.Add("users/3", new String('b', 5000));

                    tx.Commit();
                }

                var snapshotWriter = new MinimalIncrementalBackup();
                snapshotWriter.ToFile(envToSnapshot, Path.Combine(_tempDir, "1.snapshot"));

                var restoredOptions = StorageEnvironmentOptions.ForPath(Path.Combine(_tempDir, "restored"));
                new IncrementalBackup().Restore(restoredOptions, new[] { Path.Combine(_tempDir, "1.snapshot") });

                using (var snapshotRestoreEnv = new StorageEnvironment(restoredOptions))
                {
                    using (var tx = snapshotRestoreEnv.NewTransaction(TransactionFlags.Read))
                    {
                        var tree = tx.ReadTree("test");
                        Assert.NotNull(tree);

                        Assert.Equal("john doe", tree.Read("users/1").Reader.ToStringValue());
                        Assert.Equal("jane darling", tree.Read("users/2").Reader.ToStringValue());
                        Assert.Equal(new String('b', 5000), tree.Read("users/3").Reader.ToStringValue());
                    }
                }
            }
        }
Example #6
0
        public unsafe void Min_inc_backup_is_smaller_than_normal_inc_backup()
        {
            const int UserCount = 5000;

            _tempDir = Guid.NewGuid().ToString();
            var storageEnvironmentOptions = StorageEnvironmentOptions.ForPath(_tempDir);

            storageEnvironmentOptions.IncrementalBackupEnabled = true;
            using (var envToSnapshot = new StorageEnvironment(storageEnvironmentOptions))
            {
                for (int xi = 0; xi < 10; xi++)
                {
                    using (var tx = envToSnapshot.NewTransaction(TransactionFlags.ReadWrite))
                    {
                        var tree = envToSnapshot.CreateTree(tx, "test");

                        for (int i = 0; i < UserCount / 10; i++)
                        {
                            tree.Add("users/" + i, "john doe/" + i);
                        }

                        tx.Commit();
                    }
                }

                var incrementalBackupInfo = envToSnapshot.HeaderAccessor.Get(ptr => ptr->IncrementalBackup);

                var snapshotWriter = new MinimalIncrementalBackup();
                snapshotWriter.ToFile(envToSnapshot, Path.Combine(_tempDir, "1.snapshot"));

                // reset the incremental backup stuff

                envToSnapshot.HeaderAccessor.Modify(ptr => ptr->IncrementalBackup = incrementalBackupInfo);

                var incBackup = new IncrementalBackup();
                incBackup.ToFile(envToSnapshot, Path.Combine(_tempDir, "2.snapshot"));

                var incLen   = new FileInfo(Path.Combine(_tempDir, "2.snapshot")).Length;
                var minInLen = new FileInfo(Path.Combine(_tempDir, "1.snapshot")).Length;

                Assert.True(incLen > minInLen);
            }
        }