using System.Data.SQLite; using System.IO; using NLog; using NzbDrone.Core.Datastore; namespace NzbDrone.Core.Backup { public interface IMakeDatabaseBackup { void BackupDatabase(IDatabase database, string targetDirectory); } public class MakeDatabaseBackup : IMakeDatabaseBackup { private readonly Logger _logger; public MakeDatabaseBackup(Logger logger) { _logger = logger; } public void BackupDatabase(IDatabase database, string targetDirectory) { var sourceConnectionString = ""; using (var db = database.OpenConnection()) { sourceConnectionString = db.ConnectionString; } var backupConnectionStringBuilder = new SQLiteConnectionStringBuilder(sourceConnectionString); backupConnectionStringBuilder.DataSource = Path.Combine(targetDirectory, Path.GetFileName(backupConnectionStringBuilder.DataSource)); // We MUST use journal mode instead of WAL coz WAL has issues when page sizes change. This should also automatically deal with the -journal and -wal files during restore. backupConnectionStringBuilder.JournalMode = SQLiteJournalModeEnum.Truncate; using (var sourceConnection = (SQLiteConnection)SQLiteFactory.Instance.CreateConnection()) using (var backupConnection = (SQLiteConnection)SQLiteFactory.Instance.CreateConnection()) { sourceConnection.ConnectionString = sourceConnectionString; backupConnection.ConnectionString = backupConnectionStringBuilder.ToString(); sourceConnection.Open(); backupConnection.Open(); sourceConnection.BackupDatabase(backupConnection, "main", "main", -1, null, 500); // The backup changes the journal_mode, force it to truncate again. using (var command = backupConnection.CreateCommand()) { command.CommandText = "pragma journal_mode=truncate"; command.ExecuteNonQuery(); } // Make sure there are no lingering connections. SQLiteConnection.ClearAllPools(); } } } }