Lidarr/src/NzbDrone.Core/Datastore/DbFactory.cs

166 lines
6.0 KiB
C#
Raw Normal View History

using System;
using System.Data.SQLite;
using NLog;
2013-06-28 01:03:04 +00:00
using NzbDrone.Common.Composition;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Exceptions;
using NzbDrone.Common.Instrumentation;
2013-03-25 06:13:53 +00:00
using NzbDrone.Core.Datastore.Migration.Framework;
2013-03-25 03:51:32 +00:00
2013-03-24 00:08:23 +00:00
namespace NzbDrone.Core.Datastore
{
public interface IDbFactory
{
IDatabase Create(MigrationType migrationType = MigrationType.Main);
IDatabase Create(MigrationContext migrationContext);
2013-03-24 00:08:23 +00:00
}
public class DbFactory : IDbFactory
{
private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(DbFactory));
2013-03-25 06:13:53 +00:00
private readonly IMigrationController _migrationController;
2013-07-05 03:56:27 +00:00
private readonly IConnectionStringFactory _connectionStringFactory;
private readonly IDiskProvider _diskProvider;
private readonly IRestoreDatabase _restoreDatabaseService;
2013-03-24 00:08:23 +00:00
static DbFactory()
2013-03-24 00:08:23 +00:00
{
InitializeEnvironment();
2013-03-25 06:13:53 +00:00
TableMapping.Map();
}
private static void InitializeEnvironment()
{
// Speed up sqlite3 initialization since we don't use the config file and can't rely on preloading.
Environment.SetEnvironmentVariable("No_Expand", "true");
Environment.SetEnvironmentVariable("No_SQLiteXmlConfigFile", "true");
Environment.SetEnvironmentVariable("No_PreLoadSQLite", "true");
}
public static void RegisterDatabase(IContainer container)
2013-06-28 01:03:04 +00:00
{
var mainDb = new MainDatabase(container.Resolve<IDbFactory>().Create());
2013-09-05 01:03:41 +00:00
container.Register<IMainDatabase>(mainDb);
2013-06-28 01:03:04 +00:00
var logDb = new LogDatabase(container.Resolve<IDbFactory>().Create(MigrationType.Log));
2013-09-05 01:03:41 +00:00
container.Register<ILogDatabase>(logDb);
2013-06-28 01:03:04 +00:00
}
public DbFactory(IMigrationController migrationController,
IConnectionStringFactory connectionStringFactory,
IDiskProvider diskProvider,
IRestoreDatabase restoreDatabaseService)
{
2013-03-25 06:13:53 +00:00
_migrationController = migrationController;
2013-07-05 03:56:27 +00:00
_connectionStringFactory = connectionStringFactory;
_diskProvider = diskProvider;
_restoreDatabaseService = restoreDatabaseService;
2013-03-25 06:13:53 +00:00
}
2013-03-24 04:56:59 +00:00
public IDatabase Create(MigrationType migrationType = MigrationType.Main)
{
return Create(new MigrationContext(migrationType));
}
public IDatabase Create(MigrationContext migrationContext)
2013-03-25 06:13:53 +00:00
{
2013-07-05 03:56:27 +00:00
string connectionString;
switch (migrationContext.MigrationType)
2013-06-28 01:03:04 +00:00
{
case MigrationType.Main:
{
2013-07-05 03:56:27 +00:00
connectionString = _connectionStringFactory.MainDbConnectionString;
CreateMain(connectionString, migrationContext);
2013-06-28 01:03:04 +00:00
break;
}
2013-06-28 01:03:04 +00:00
case MigrationType.Log:
{
2013-07-05 03:56:27 +00:00
connectionString = _connectionStringFactory.LogDbConnectionString;
CreateLog(connectionString, migrationContext);
2013-06-28 01:03:04 +00:00
break;
}
2013-06-28 01:03:04 +00:00
default:
{
throw new ArgumentException("Invalid MigrationType");
}
}
var db = new Database(migrationContext.MigrationType.ToString(), () =>
{
2020-08-18 20:11:44 +00:00
var conn = SQLiteFactory.Instance.CreateConnection();
conn.ConnectionString = connectionString;
conn.Open();
2020-08-18 20:11:44 +00:00
return conn;
});
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)
{
2021-08-04 22:47:40 +00:00
throw new CorruptDatabaseException("Database file: {0} is corrupt, restore from backup if available. See: https://wiki.servarr.com/lidarr/faq#i-use-lidarr-on-a-mac-and-it-suddenly-stopped-working-what-happened", e, fileName);
}
2021-08-04 22:47:40 +00:00
throw new CorruptDatabaseException("Database file: {0} is corrupt, restore from backup if available. See: https://wiki.servarr.com/lidarr/faq#i-am-getting-an-error-database-disk-image-is-malformed", e, fileName);
}
catch (Exception e)
{
throw new LidarrStartupException(e, "Error creating main database");
}
}
private void CreateLog(string connectionString, MigrationContext migrationContext)
{
try
{
_migrationController.Migrate(connectionString, migrationContext);
}
catch (SQLiteException e)
{
var fileName = _connectionStringFactory.GetDatabasePath(connectionString);
2013-05-11 20:06:57 +00:00
Logger.Error(e, "Logging database is corrupt, attempting to recreate it automatically");
2013-11-28 07:52:22 +00:00
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);
}
catch (Exception e)
{
throw new LidarrStartupException(e, "Error creating log database");
}
2013-03-25 03:51:32 +00:00
}
2013-03-24 00:08:23 +00:00
}
}