1
0
Fork 0
mirror of https://github.com/lidarr/Lidarr synced 2025-02-27 00:02:25 +00:00

Fixed: Improved database backup journal handling

This commit is contained in:
Qstick 2017-10-28 23:54:26 -04:00
parent 99ab61fac6
commit f09ef025c5
4 changed files with 73 additions and 15 deletions

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Data.SQLite;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@ -25,6 +26,7 @@ public interface IBackupService
public class BackupService : IBackupService, IExecute<BackupCommand> public class BackupService : IBackupService, IExecute<BackupCommand>
{ {
private readonly IMainDatabase _maindDb; private readonly IMainDatabase _maindDb;
private readonly IMakeDatabaseBackup _makeDatabaseBackup;
private readonly IDiskTransferService _diskTransferService; private readonly IDiskTransferService _diskTransferService;
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly IAppFolderInfo _appFolderInfo; private readonly IAppFolderInfo _appFolderInfo;
@ -36,6 +38,7 @@ public class BackupService : IBackupService, IExecute<BackupCommand>
private static readonly Regex BackupFileRegex = new Regex(@"nzbdrone_backup_[._0-9]+\.zip", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex BackupFileRegex = new Regex(@"nzbdrone_backup_[._0-9]+\.zip", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public BackupService(IMainDatabase maindDb, public BackupService(IMainDatabase maindDb,
IMakeDatabaseBackup makeDatabaseBackup,
IDiskTransferService diskTransferService, IDiskTransferService diskTransferService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IAppFolderInfo appFolderInfo, IAppFolderInfo appFolderInfo,
@ -43,6 +46,7 @@ public BackupService(IMainDatabase maindDb,
Logger logger) Logger logger)
{ {
_maindDb = maindDb; _maindDb = maindDb;
_makeDatabaseBackup = makeDatabaseBackup;
_diskTransferService = diskTransferService; _diskTransferService = diskTransferService;
_diskProvider = diskProvider; _diskProvider = diskProvider;
_appFolderInfo = appFolderInfo; _appFolderInfo = appFolderInfo;
@ -111,17 +115,7 @@ private void BackupDatabase()
{ {
_logger.ProgressDebug("Backing up database"); _logger.ProgressDebug("Backing up database");
using (var unitOfWork = new UnitOfWork(() => _maindDb.GetDataMapper())) _makeDatabaseBackup.BackupDatabase(_maindDb, _backupTempFolder);
{
unitOfWork.BeginTransaction(IsolationLevel.Serializable);
var databaseFile = _appFolderInfo.GetDatabase();
var tempDatabaseFile = Path.Combine(_backupTempFolder, Path.GetFileName(databaseFile));
_diskTransferService.TransferFile(databaseFile, tempDatabaseFile, TransferMode.Copy);
unitOfWork.Commit();
}
} }
private void BackupConfigFile() private void BackupConfigFile()

View file

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.IO;
using System.Linq;
using System.Text;
using NLog;
using NzbDrone.Core.Datastore;
using System.Data;
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));
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);
// Make sure there are no lingering connections so the wal gets truncated.
SQLiteConnection.ClearAllPools();
}
var backupWalPath = backupConnectionStringBuilder.DataSource + "-wal";
if (backupConnectionStringBuilder.JournalMode == SQLiteJournalModeEnum.Wal && !File.Exists(backupWalPath))
{
// Make sure the wal gets created in the backup so users are less likely to make an error during restore.
File.WriteAllBytes(backupWalPath, new byte[0]);
}
var backupJournalPath = backupConnectionStringBuilder.DataSource + "-journal";
if (backupConnectionStringBuilder.JournalMode != SQLiteJournalModeEnum.Wal && !File.Exists(backupJournalPath))
{
// Make sure the journal gets created in the backup so users are less likely to make an error during restore.
File.WriteAllBytes(backupJournalPath, new byte[0]);
}
}
}
}

View file

@ -1,4 +1,4 @@
using System; using System;
using Marr.Data; using Marr.Data;
using NLog; using NLog;
using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Instrumentation;
@ -25,7 +25,6 @@ public Database(string databaseName, Func<IDataMapper> datamapperFactory)
_datamapperFactory = datamapperFactory; _datamapperFactory = datamapperFactory;
} }
public IDataMapper GetDataMapper() public IDataMapper GetDataMapper()
{ {
return _datamapperFactory(); return _datamapperFactory();
@ -54,4 +53,4 @@ public void Vacuum()
} }
} }
} }
} }

View file

@ -127,6 +127,7 @@
<Compile Include="Backup\Backup.cs" /> <Compile Include="Backup\Backup.cs" />
<Compile Include="Backup\BackupCommand.cs" /> <Compile Include="Backup\BackupCommand.cs" />
<Compile Include="Backup\BackupService.cs" /> <Compile Include="Backup\BackupService.cs" />
<Compile Include="Backup\MakeDatabaseBackup.cs" />
<Compile Include="Blacklisting\Blacklist.cs" /> <Compile Include="Blacklisting\Blacklist.cs" />
<Compile Include="Blacklisting\BlacklistRepository.cs" /> <Compile Include="Blacklisting\BlacklistRepository.cs" />
<Compile Include="Blacklisting\BlacklistService.cs" /> <Compile Include="Blacklisting\BlacklistService.cs" />