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 = database . GetDataMapper ( ) . 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 ( ) ;
}
}
}
}