2017-11-26 04:31:41 +00:00
using System ;
2013-03-26 05:51:56 +00:00
using System.Data.SQLite ;
2013-03-25 03:51:32 +00:00
using Marr.Data ;
2013-04-01 23:55:09 +00:00
using Marr.Data.Reflection ;
2016-07-20 01:57:36 +00:00
using NLog ;
2013-06-28 01:03:04 +00:00
using NzbDrone.Common.Composition ;
2016-07-20 01:57:36 +00:00
using NzbDrone.Common.Disk ;
using NzbDrone.Common.EnvironmentInfo ;
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
{
2016-02-13 21:23:37 +00:00
IDatabase Create ( MigrationType migrationType = MigrationType . Main ) ;
IDatabase Create ( MigrationContext migrationContext ) ;
2013-03-24 00:08:23 +00:00
}
public class DbFactory : IDbFactory
{
2016-07-20 01:57:36 +00:00
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 ;
2016-07-20 01:57:36 +00:00
private readonly IDiskProvider _diskProvider ;
2013-03-24 00:08:23 +00:00
2013-03-30 22:14:33 +00:00
static DbFactory ( )
2013-03-24 00:08:23 +00:00
{
2013-06-03 03:15:56 +00:00
MapRepository . Instance . ReflectionStrategy = new SimpleReflectionStrategy ( ) ;
2013-03-25 06:13:53 +00:00
TableMapping . Map ( ) ;
2013-03-30 22:14:33 +00:00
}
2013-06-28 01:03:04 +00:00
public static void RegisterDatabase ( IContainer container )
{
2015-05-03 19:46:21 +00:00
var mainDb = new MainDatabase ( container . Resolve < IDbFactory > ( ) . Create ( ) ) ;
2013-09-05 01:03:41 +00:00
2015-05-03 19:46:21 +00:00
container . Register < IMainDatabase > ( mainDb ) ;
2013-06-28 01:03:04 +00:00
2015-05-03 19:46:21 +00:00
var logDb = new LogDatabase ( container . Resolve < IDbFactory > ( ) . Create ( MigrationType . Log ) ) ;
2013-09-05 01:03:41 +00:00
2015-05-03 19:46:21 +00:00
container . Register < ILogDatabase > ( logDb ) ;
2013-06-28 01:03:04 +00:00
}
2016-07-20 01:57:36 +00:00
public DbFactory ( IMigrationController migrationController ,
IConnectionStringFactory connectionStringFactory ,
IDiskProvider diskProvider )
2013-03-30 22:14:33 +00:00
{
2013-03-25 06:13:53 +00:00
_migrationController = migrationController ;
2013-07-05 03:56:27 +00:00
_connectionStringFactory = connectionStringFactory ;
2016-07-20 01:57:36 +00:00
_diskProvider = diskProvider ;
2013-03-25 06:13:53 +00:00
}
2013-03-24 04:56:59 +00:00
2016-02-13 21:23:37 +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 ;
2013-06-28 01:03:04 +00:00
2016-02-13 21:23:37 +00:00
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 ;
2013-06-28 01:03:04 +00:00
break ;
}
case MigrationType . Log :
{
2013-07-05 03:56:27 +00:00
connectionString = _connectionStringFactory . LogDbConnectionString ;
2013-06-28 01:03:04 +00:00
break ;
}
default :
{
throw new ArgumentException ( "Invalid MigrationType" ) ;
}
}
2016-07-20 01:57:36 +00:00
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 )
{
2017-03-30 03:49:38 +00:00
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" , ex , fileName ) ;
2016-07-20 01:57:36 +00:00
}
2017-03-30 03:49:38 +00:00
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" , ex , fileName ) ;
2016-07-20 01:57:36 +00:00
}
}
2013-05-11 20:06:57 +00:00
2016-02-13 21:23:37 +00:00
var db = new Database ( migrationContext . MigrationType . ToString ( ) , ( ) = >
2013-11-28 07:52:22 +00:00
{
var dataMapper = new DataMapper ( SQLiteFactory . Instance , connectionString )
{
SqlMode = SqlModes . Text ,
} ;
return dataMapper ;
} ) ;
2013-11-28 07:11:05 +00:00
2017-11-26 04:31:41 +00:00
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" ) ;
}
2013-11-28 07:11:05 +00:00
return db ;
2013-03-25 03:51:32 +00:00
}
2013-03-24 00:08:23 +00:00
}
}