Fixed: Recreate log database if migration fails

Fixes: #1050
pull/1381/head
Mark McDowall 8 years ago committed by GitHub
parent 8255fb0b28
commit 857d661ff1

@ -9,6 +9,7 @@ namespace NzbDrone.Core.Datastore
{
string MainDbConnectionString { get; }
string LogDbConnectionString { get; }
string GetDatabasePath(string connectionString);
}
public class ConnectionStringFactory : IConnectionStringFactory
@ -22,6 +23,13 @@ namespace NzbDrone.Core.Datastore
public string MainDbConnectionString { get; private set; }
public string LogDbConnectionString { get; private set; }
public string GetDatabasePath(string connectionString)
{
var connectionBuilder = new SQLiteConnectionStringBuilder(connectionString);
return connectionBuilder.DataSource;
}
private static string GetConnectionString(string dbPath)
{
var connectionBuilder = new SQLiteConnectionStringBuilder();

@ -0,0 +1,24 @@
using System;
using NzbDrone.Common.Exceptions;
namespace NzbDrone.Core.Datastore
{
public class CorruptDatabaseException : NzbDroneException
{
public CorruptDatabaseException(string message, params object[] args) : base(message, args)
{
}
public CorruptDatabaseException(string message) : base(message)
{
}
public CorruptDatabaseException(string message, Exception innerException, params object[] args) : base(message, innerException, args)
{
}
public CorruptDatabaseException(string message, Exception innerException) : base(message, innerException)
{
}
}
}

@ -1,11 +1,14 @@
using System;
using System.Data.SQLite;
using System.IO;
using Marr.Data;
using Marr.Data.Reflection;
using NLog;
using NzbDrone.Common.Composition;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Instrumentation;
using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Datastore
@ -18,8 +21,10 @@ namespace NzbDrone.Core.Datastore
public class DbFactory : IDbFactory
{
private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(DbFactory));
private readonly IMigrationController _migrationController;
private readonly IConnectionStringFactory _connectionStringFactory;
private readonly IDiskProvider _diskProvider;
static DbFactory()
{
@ -38,10 +43,13 @@ namespace NzbDrone.Core.Datastore
container.Register<ILogDatabase>(logDb);
}
public DbFactory(IMigrationController migrationController, IConnectionStringFactory connectionStringFactory)
public DbFactory(IMigrationController migrationController,
IConnectionStringFactory connectionStringFactory,
IDiskProvider diskProvider)
{
_migrationController = migrationController;
_connectionStringFactory = connectionStringFactory;
_diskProvider = diskProvider;
}
public IDatabase Create(MigrationType migrationType = MigrationType.Main)
@ -72,7 +80,43 @@ namespace NzbDrone.Core.Datastore
}
}
_migrationController.Migrate(connectionString, migrationContext);
try
{
_migrationController.Migrate(connectionString, migrationContext);
}
catch (SQLiteException ex)
{
var fileName = _connectionStringFactory.GetDatabasePath(connectionString);
if (migrationContext.MigrationType == MigrationType.Log)
{
Logger.Error(ex, "Logging database is corrupt, attempting to recreate it automatically");
try
{
_diskProvider.DeleteFile(fileName + "-shm");
_diskProvider.DeleteFile(fileName + "-wal");
_diskProvider.DeleteFile(fileName + "-journal");
_diskProvider.DeleteFile(fileName);
}
catch (Exception)
{
Logger.Error("Unable to recreate logging database automatically. It will need to be removed manually.");
}
_migrationController.Migrate(connectionString, migrationContext);
}
else
{
if (OsInfo.IsOsx)
{
throw new CorruptDatabaseException("Database file: {0} is corrupt, restore from backup if available. See: https://github.com/Sonarr/Sonarr/wiki/FAQ#i-use-sonarr-on-a-mac-and-it-suddenly-stopped-working-what-happened", ex, fileName);
}
throw new CorruptDatabaseException("Database file: {0} is corrupt, restore from backup if available. See: https://github.com/Sonarr/Sonarr/wiki/FAQ#i-am-getting-an-error-database-disk-image-is-malformed", ex, fileName);
}
}
var db = new Database(migrationContext.MigrationType.ToString(), () =>
{

@ -1,4 +1,4 @@
using System;
using System.Data.SQLite;
using System.Diagnostics;
using System.Reflection;
using FluentMigrator.Runner;
@ -37,16 +37,27 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
var options = new MigrationOptions { PreviewOnly = false, Timeout = 60 };
var factory = new NzbDroneSqliteProcessorFactory();
var processor = factory.Create(connectionString, _announcer, options);
var runner = new MigrationRunner(assembly, runnerContext, processor);
if (migrationContext.DesiredVersion.HasValue)
try
{
runner.MigrateUp(migrationContext.DesiredVersion.Value, true);
var runner = new MigrationRunner(assembly, runnerContext, processor);
if (migrationContext.DesiredVersion.HasValue)
{
runner.MigrateUp(migrationContext.DesiredVersion.Value, true);
}
else
{
runner.MigrateUp(true);
}
}
else
catch (SQLiteException)
{
runner.MigrateUp(true);
processor.Dispose();
SQLiteConnection.ClearAllPools();
throw;
}
sw.Stop();

@ -171,6 +171,7 @@
<Compile Include="Datastore\Converters\ProviderSettingConverter.cs" />
<Compile Include="Datastore\Converters\QualityIntConverter.cs" />
<Compile Include="Datastore\Converters\UtcConverter.cs" />
<Compile Include="Datastore\CorruptDatabaseException.cs" />
<Compile Include="Datastore\Database.cs" />
<Compile Include="Datastore\DbFactory.cs" />
<Compile Include="Datastore\Events\ModelEvent.cs" />

Loading…
Cancel
Save