diff --git a/Emby.Server.Implementations/Activity/ActivityRepository.cs b/Emby.Server.Implementations/Activity/ActivityRepository.cs index 3dcc50ba38..1ae8e5e667 100644 --- a/Emby.Server.Implementations/Activity/ActivityRepository.cs +++ b/Emby.Server.Implementations/Activity/ActivityRepository.cs @@ -10,20 +10,39 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.Querying; using SQLitePCL.pretty; using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Activity { public class ActivityRepository : BaseSqliteRepository, IActivityRepository { private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + protected IFileSystem FileSystem { get; private set; } - public ActivityRepository(ILogger logger, IServerApplicationPaths appPaths) + public ActivityRepository(ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem) : base(logger) { DbFilePath = Path.Combine(appPaths.DataPath, "activitylog.db"); + FileSystem = fileSystem; } public void Initialize() + { + try + { + InitializeInternal(); + } + catch (Exception ex) + { + Logger.ErrorException("Error loading database file. Will reset and retry.", ex); + + FileSystem.DeleteFile(DbFilePath); + + InitializeInternal(); + } + } + + private void InitializeInternal() { using (var connection = CreateConnection()) { diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 47b969ecac..ba43c7f350 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -879,7 +879,7 @@ namespace Emby.Server.Implementations // This is only needed for disposal purposes. If removing this, make sure to have the manager handle disposing it RegisterSingleInstance(UserRepository); - var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LogManager.GetLogger("SqliteDisplayPreferencesRepository"), JsonSerializer, ApplicationPaths, MemoryStreamFactory); + var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LogManager.GetLogger("SqliteDisplayPreferencesRepository"), JsonSerializer, ApplicationPaths, MemoryStreamFactory, FileSystemManager); DisplayPreferencesRepository = displayPreferencesRepo; RegisterSingleInstance(DisplayPreferencesRepository); @@ -997,7 +997,7 @@ namespace Emby.Server.Implementations EncodingManager = new EncodingManager(FileSystemManager, Logger, MediaEncoder, ChapterManager, LibraryManager); RegisterSingleInstance(EncodingManager); - var sharingRepo = new SharingRepository(LogManager.GetLogger("SharingRepository"), ApplicationPaths); + var sharingRepo = new SharingRepository(LogManager.GetLogger("SharingRepository"), ApplicationPaths, FileSystemManager); sharingRepo.Initialize(); // This is only needed for disposal purposes. If removing this, make sure to have the manager handle disposing it RegisterSingleInstance(sharingRepo); @@ -1351,7 +1351,7 @@ namespace Emby.Server.Implementations private IActivityRepository GetActivityLogRepository() { - var repo = new ActivityRepository(LogManager.GetLogger("ActivityRepository"), ServerConfigurationManager.ApplicationPaths); + var repo = new ActivityRepository(LogManager.GetLogger("ActivityRepository"), ServerConfigurationManager.ApplicationPaths, FileSystemManager); repo.Initialize(); diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index a34c90cb41..d207c8d4f7 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -108,37 +108,49 @@ namespace Emby.Server.Implementations.Data var db = SQLite3.Open(DbFilePath, connectionFlags, null); - if (string.IsNullOrWhiteSpace(_defaultWal)) + try { - _defaultWal = db.Query("PRAGMA journal_mode").SelectScalarString().First(); + if (string.IsNullOrWhiteSpace(_defaultWal)) + { + _defaultWal = db.Query("PRAGMA journal_mode").SelectScalarString().First(); - Logger.Info("Default journal_mode for {0} is {1}", DbFilePath, _defaultWal); - } + Logger.Info("Default journal_mode for {0} is {1}", DbFilePath, _defaultWal); + } - var queries = new List - { - //"PRAGMA cache size=-10000" - //"PRAGMA read_uncommitted = true", - "PRAGMA synchronous=Normal" - }; + var queries = new List + { + //"PRAGMA cache size=-10000" + //"PRAGMA read_uncommitted = true", + "PRAGMA synchronous=Normal" + }; - if (CacheSize.HasValue) - { - queries.Add("PRAGMA cache_size=" + CacheSize.Value.ToString(CultureInfo.InvariantCulture)); - } + if (CacheSize.HasValue) + { + queries.Add("PRAGMA cache_size=" + CacheSize.Value.ToString(CultureInfo.InvariantCulture)); + } - if (EnableTempStoreMemory) - { - queries.Add("PRAGMA temp_store = memory"); + if (EnableTempStoreMemory) + { + queries.Add("PRAGMA temp_store = memory"); + } + else + { + queries.Add("PRAGMA temp_store = file"); + } + + foreach (var query in queries) + { + db.Execute(query); + } } - else + catch { - queries.Add("PRAGMA temp_store = file"); - } + using (db) + { - foreach (var query in queries) - { - db.Execute(query); + } + + throw; } _connection = new ManagedConnection(db, false); @@ -265,29 +277,34 @@ namespace Emby.Server.Implementations.Data { if (dispose) { - try + DisposeConnection(); + } + } + + private void DisposeConnection() + { + try + { + lock (_disposeLock) { - lock (_disposeLock) + using (WriteLock.Write()) { - using (WriteLock.Write()) + if (_connection != null) { - if (_connection != null) + using (_connection) { - using (_connection) - { - - } - _connection = null; + _connection.Close(); } - - CloseConnection(); + _connection = null; } + + CloseConnection(); } } - catch (Exception ex) - { - Logger.ErrorException("Error disposing database", ex); - } + } + catch (Exception ex) + { + Logger.ErrorException("Error disposing database", ex); } } diff --git a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs index 89664d158e..1901ce848a 100644 --- a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs @@ -19,12 +19,14 @@ namespace Emby.Server.Implementations.Data public class SqliteDisplayPreferencesRepository : BaseSqliteRepository, IDisplayPreferencesRepository { private readonly IMemoryStreamFactory _memoryStreamProvider; + protected IFileSystem FileSystem { get; private set; } - public SqliteDisplayPreferencesRepository(ILogger logger, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IMemoryStreamFactory memoryStreamProvider) + public SqliteDisplayPreferencesRepository(ILogger logger, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IMemoryStreamFactory memoryStreamProvider, IFileSystem fileSystem) : base(logger) { _jsonSerializer = jsonSerializer; _memoryStreamProvider = memoryStreamProvider; + FileSystem = fileSystem; DbFilePath = Path.Combine(appPaths.DataPath, "displaypreferences.db"); } @@ -45,11 +47,27 @@ namespace Emby.Server.Implementations.Data /// private readonly IJsonSerializer _jsonSerializer; + public void Initialize() + { + try + { + InitializeInternal(); + } + catch (Exception ex) + { + Logger.ErrorException("Error loading database file. Will reset and retry.", ex); + + FileSystem.DeleteFile(DbFilePath); + + InitializeInternal(); + } + } + /// /// Opens the connection to the database /// /// Task. - public void Initialize() + private void InitializeInternal() { using (var connection = CreateConnection()) { diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 89ffb0fce3..987b1df39b 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -120,13 +120,13 @@ namespace Emby.Server.Implementations.Data protected override void CloseConnection() { - base.CloseConnection(); - if (_shrinkMemoryTimer != null) { _shrinkMemoryTimer.Dispose(); _shrinkMemoryTimer = null; } + + base.CloseConnection(); } /// diff --git a/Emby.Server.Implementations/Notifications/SqliteNotificationsRepository.cs b/Emby.Server.Implementations/Notifications/SqliteNotificationsRepository.cs index ff152c9e9c..f3a8a18eeb 100644 --- a/Emby.Server.Implementations/Notifications/SqliteNotificationsRepository.cs +++ b/Emby.Server.Implementations/Notifications/SqliteNotificationsRepository.cs @@ -38,7 +38,7 @@ namespace Emby.Server.Implementations.Notifications } catch (Exception ex) { - Logger.ErrorException("Error loading notifications database file. Will reset and retry.", ex); + Logger.ErrorException("Error loading database file. Will reset and retry.", ex); FileSystem.DeleteFile(DbFilePath); diff --git a/Emby.Server.Implementations/Social/SharingRepository.cs b/Emby.Server.Implementations/Social/SharingRepository.cs index f306e76c49..f0b8cbd30f 100644 --- a/Emby.Server.Implementations/Social/SharingRepository.cs +++ b/Emby.Server.Implementations/Social/SharingRepository.cs @@ -7,22 +7,42 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.Social; using SQLitePCL.pretty; using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Social { public class SharingRepository : BaseSqliteRepository, ISharingRepository { - public SharingRepository(ILogger logger, IApplicationPaths appPaths) + protected IFileSystem FileSystem { get; private set; } + + public SharingRepository(ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem) : base(logger) { + FileSystem = fileSystem; DbFilePath = Path.Combine(appPaths.DataPath, "shares.db"); } + public void Initialize() + { + try + { + InitializeInternal(); + } + catch (Exception ex) + { + Logger.ErrorException("Error loading database file. Will reset and retry.", ex); + + FileSystem.DeleteFile(DbFilePath); + + InitializeInternal(); + } + } + /// /// Opens the connection to the database /// /// Task. - public void Initialize() + private void InitializeInternal() { using (var connection = CreateConnection()) {