diff --git a/src/NzbDrone.Api/Config/HostConfigResource.cs b/src/NzbDrone.Api/Config/HostConfigResource.cs index 74e7e0d62..5580e02ee 100644 --- a/src/NzbDrone.Api/Config/HostConfigResource.cs +++ b/src/NzbDrone.Api/Config/HostConfigResource.cs @@ -3,6 +3,7 @@ using NzbDrone.Core.Authentication; using NzbDrone.Core.Configuration; using NzbDrone.Core.Update; using NzbDrone.Common.Http.Proxy; +using NzbDrone.Core.Datastore; namespace NzbDrone.Api.Config { @@ -19,6 +20,7 @@ namespace NzbDrone.Api.Config public string Password { get; set; } public string LogLevel { get; set; } public string ConsoleLogLevel { get; set; } + public DatabaseJournalType DatabaseJournalMode { get; set; } public string Branch { get; set; } public string ApiKey { get; set; } public string SslCertHash { get; set; } diff --git a/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs b/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs index 599db635a..1e660bdf1 100644 --- a/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs +++ b/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Data.SQLite; using System.IO; using System.Linq; using System.Text.RegularExpressions; @@ -12,6 +13,7 @@ using NzbDrone.Common.Extensions; using NzbDrone.Common.Instrumentation; using NzbDrone.Core.Authentication; using NzbDrone.Core.Configuration.Events; +using NzbDrone.Core.Datastore; using NzbDrone.Core.Lifecycle; using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Events; @@ -34,6 +36,7 @@ namespace NzbDrone.Core.Configuration bool AnalyticsEnabled { get; } string LogLevel { get; } string ConsoleLogLevel { get; } + DatabaseJournalType DatabaseJournalMode { get; } string Branch { get; } string ApiKey { get; } string SslCertHash { get; } @@ -182,6 +185,8 @@ namespace NzbDrone.Core.Configuration public string LogLevel => GetValue("LogLevel", "Info"); public string ConsoleLogLevel => GetValue("ConsoleLogLevel", string.Empty, persist: false); + public DatabaseJournalType DatabaseJournalMode => GetValueEnum("DatabaseJournalMode", DatabaseJournalType.Wal, persist: false); + public string SslCertHash => GetValue("SslCertHash", ""); public string UrlBase diff --git a/src/NzbDrone.Core/Datastore/ConnectionStringFactory.cs b/src/NzbDrone.Core/Datastore/ConnectionStringFactory.cs index a69883dc1..abe408dfe 100644 --- a/src/NzbDrone.Core/Datastore/ConnectionStringFactory.cs +++ b/src/NzbDrone.Core/Datastore/ConnectionStringFactory.cs @@ -1,7 +1,11 @@ using System; using System.Data.SQLite; +using System.IO; +using NzbDrone.Common.Disk; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Configuration; +using NLog; namespace NzbDrone.Core.Datastore { @@ -14,8 +18,16 @@ namespace NzbDrone.Core.Datastore public class ConnectionStringFactory : IConnectionStringFactory { - public ConnectionStringFactory(IAppFolderInfo appFolderInfo) + private readonly IDiskProvider _diskProvider; + private readonly IConfigFileProvider _configFileProvider; + private readonly Logger _logger; + + public ConnectionStringFactory(IAppFolderInfo appFolderInfo, IDiskProvider diskProvider, IConfigFileProvider configFileProvider, Logger logger) { + _diskProvider = diskProvider; + _configFileProvider = configFileProvider; + _logger = logger; + MainDbConnectionString = GetConnectionString(appFolderInfo.GetDatabase()); LogDbConnectionString = GetConnectionString(appFolderInfo.GetLogDatabase()); } @@ -30,23 +42,50 @@ namespace NzbDrone.Core.Datastore return connectionBuilder.DataSource; } - private static string GetConnectionString(string dbPath) + private string GetConnectionString(string dbPath) { var connectionBuilder = new SQLiteConnectionStringBuilder(); connectionBuilder.DataSource = dbPath; connectionBuilder.CacheSize = (int)-10000; connectionBuilder.DateTimeKind = DateTimeKind.Utc; - connectionBuilder.JournalMode = OsInfo.IsOsx ? SQLiteJournalModeEnum.Truncate : SQLiteJournalModeEnum.Wal; - connectionBuilder.Pooling = true; - connectionBuilder.Version = 3; - - if (OsInfo.IsOsx) + + connectionBuilder.JournalMode = GetJournalMode(dbPath); + + if (connectionBuilder.JournalMode == SQLiteJournalModeEnum.Truncate) { connectionBuilder.Add("Full FSync", true); } + connectionBuilder.Pooling = true; + connectionBuilder.Version = 3; + return connectionBuilder.ConnectionString; } + + private SQLiteJournalModeEnum GetJournalMode(string path) + { + var driveType = _diskProvider.GetMount(path).DriveType; + + if (driveType == DriveType.Network || driveType == DriveType.Unknown) + { + _logger.Debug("Network filesystem store for application data detected, disabling WAL mode for SQLite"); + return SQLiteJournalModeEnum.Truncate; + } + + if (_configFileProvider.DatabaseJournalMode != (DatabaseJournalType)SQLiteJournalModeEnum.Wal) + { + _logger.Debug("DatabaseJournalMode tag detected in config.xml, disabling WAL mode for SQLite"); + return SQLiteJournalModeEnum.Truncate; + } + + if (OsInfo.IsOsx) + { + _logger.Debug("macOS operating system detected, disabling WAL mode for SQLite"); + return SQLiteJournalModeEnum.Truncate; + } + + return SQLiteJournalModeEnum.Wal; + } } } \ No newline at end of file diff --git a/src/NzbDrone.Core/Datastore/DatabaseJournalType.cs b/src/NzbDrone.Core/Datastore/DatabaseJournalType.cs new file mode 100644 index 000000000..94a7fec8d --- /dev/null +++ b/src/NzbDrone.Core/Datastore/DatabaseJournalType.cs @@ -0,0 +1,10 @@ +using System.Data.SQLite; + +namespace NzbDrone.Core.Datastore +{ + public enum DatabaseJournalType + { + Wal = SQLiteJournalModeEnum.Wal, + Truncate = SQLiteJournalModeEnum.Truncate + } +} diff --git a/src/Sonarr.Api.V3/Config/HostConfigResource.cs b/src/Sonarr.Api.V3/Config/HostConfigResource.cs index 8fd147dac..9fec66945 100644 --- a/src/Sonarr.Api.V3/Config/HostConfigResource.cs +++ b/src/Sonarr.Api.V3/Config/HostConfigResource.cs @@ -1,6 +1,7 @@ using NzbDrone.Common.Http.Proxy; using NzbDrone.Core.Authentication; using NzbDrone.Core.Configuration; +using NzbDrone.Core.Datastore; using NzbDrone.Core.Security; using NzbDrone.Core.Update; using Sonarr.Http.REST; @@ -20,6 +21,7 @@ namespace Sonarr.Api.V3.Config public string Password { get; set; } public string LogLevel { get; set; } public string ConsoleLogLevel { get; set; } + public DatabaseJournalType DatabaseJournalMode { get; set; } public string Branch { get; set; } public string ApiKey { get; set; } public string SslCertHash { get; set; }