You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
5.6 KiB
156 lines
5.6 KiB
using System;
|
|
using System.Data.SQLite;
|
|
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;
|
|
|
|
|
|
namespace NzbDrone.Core.Datastore
|
|
{
|
|
public interface IDbFactory
|
|
{
|
|
IDatabase Create(MigrationType migrationType = MigrationType.Main);
|
|
IDatabase Create(MigrationContext migrationContext);
|
|
}
|
|
|
|
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;
|
|
private readonly IRestoreDatabase _restoreDatabaseService;
|
|
|
|
static DbFactory()
|
|
{
|
|
MapRepository.Instance.ReflectionStrategy = new SimpleReflectionStrategy();
|
|
TableMapping.Map();
|
|
}
|
|
|
|
public static void RegisterDatabase(IContainer container)
|
|
{
|
|
var mainDb = new MainDatabase(container.Resolve<IDbFactory>().Create());
|
|
|
|
container.Register<IMainDatabase>(mainDb);
|
|
|
|
var logDb = new LogDatabase(container.Resolve<IDbFactory>().Create(MigrationType.Log));
|
|
|
|
container.Register<ILogDatabase>(logDb);
|
|
}
|
|
|
|
public DbFactory(IMigrationController migrationController,
|
|
IConnectionStringFactory connectionStringFactory,
|
|
IDiskProvider diskProvider,
|
|
IRestoreDatabase restoreDatabaseService)
|
|
{
|
|
_migrationController = migrationController;
|
|
_connectionStringFactory = connectionStringFactory;
|
|
_diskProvider = diskProvider;
|
|
_restoreDatabaseService = restoreDatabaseService;
|
|
}
|
|
|
|
public IDatabase Create(MigrationType migrationType = MigrationType.Main)
|
|
{
|
|
return Create(new MigrationContext(migrationType));
|
|
}
|
|
|
|
public IDatabase Create(MigrationContext migrationContext)
|
|
{
|
|
string connectionString;
|
|
|
|
switch (migrationContext.MigrationType)
|
|
{
|
|
case MigrationType.Main:
|
|
{
|
|
connectionString = _connectionStringFactory.MainDbConnectionString;
|
|
CreateMain(connectionString, migrationContext);
|
|
|
|
break;
|
|
}
|
|
case MigrationType.Log:
|
|
{
|
|
connectionString = _connectionStringFactory.LogDbConnectionString;
|
|
CreateLog(connectionString, migrationContext);
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
throw new ArgumentException("Invalid MigrationType");
|
|
}
|
|
}
|
|
|
|
var db = new Database(migrationContext.MigrationType.ToString(), () =>
|
|
{
|
|
var dataMapper = new DataMapper(SQLiteFactory.Instance, connectionString)
|
|
{
|
|
SqlMode = SqlModes.Text,
|
|
};
|
|
|
|
return dataMapper;
|
|
});
|
|
|
|
if (db.Migration > 100) //Quick DB Migration Check. This should get rid of users on old DB format
|
|
{
|
|
throw new CorruptDatabaseException("Invalid DB, Please Delete and Restart Lidarr");
|
|
}
|
|
|
|
return db;
|
|
}
|
|
|
|
private void CreateMain(string connectionString, MigrationContext migrationContext)
|
|
{
|
|
|
|
try
|
|
{
|
|
_restoreDatabaseService.Restore();
|
|
_migrationController.Migrate(connectionString, migrationContext);
|
|
}
|
|
catch (SQLiteException e)
|
|
{
|
|
var fileName = _connectionStringFactory.GetDatabasePath(connectionString);
|
|
|
|
if (OsInfo.IsOsx)
|
|
{
|
|
throw new CorruptDatabaseException("Database file: {0} is corrupt, restore from backup if available. See: https://github.com/Lidarr/Lidarr/wiki/FAQ#i-use-lidarr-on-a-mac-and-it-suddenly-stopped-working-what-happened", e, fileName);
|
|
}
|
|
|
|
throw new CorruptDatabaseException("Database file: {0} is corrupt, restore from backup if available. See: https://github.com/Lidarr/Lidarr/wiki/FAQ#i-am-getting-an-error-database-disk-image-is-malformed", e, fileName);
|
|
}
|
|
}
|
|
|
|
private void CreateLog(string connectionString, MigrationContext migrationContext)
|
|
{
|
|
try
|
|
{
|
|
_migrationController.Migrate(connectionString, migrationContext);
|
|
}
|
|
catch (SQLiteException e)
|
|
{
|
|
var fileName = _connectionStringFactory.GetDatabasePath(connectionString);
|
|
|
|
Logger.Error(e, "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);
|
|
}
|
|
}
|
|
}
|
|
}
|