Cache root folders and improve getting disk space for series path roots
This commit is contained in:
parent
e791f4b743
commit
63fdf8ca8f
|
@ -5,6 +5,7 @@ using Moq;
|
|||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.DiskSpace;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Test.Common;
|
||||
|
@ -16,14 +17,14 @@ namespace NzbDrone.Core.Test.DiskSpace
|
|||
{
|
||||
private string _seriesFolder;
|
||||
private string _seriesFolder2;
|
||||
private string _droneFactoryFolder;
|
||||
private string _rootFolder;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_seriesFolder = @"G:\fasdlfsdf\series".AsOsAgnostic();
|
||||
_seriesFolder2 = @"G:\fasdlfsdf\series2".AsOsAgnostic();
|
||||
_droneFactoryFolder = @"G:\dronefactory".AsOsAgnostic();
|
||||
_rootFolder = @"G:\fasdlfsdf".AsOsAgnostic();
|
||||
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
.Setup(v => v.GetMounts())
|
||||
|
@ -51,6 +52,13 @@ namespace NzbDrone.Core.Test.DiskSpace
|
|||
.Returns(new Dictionary<int, string>(seriesPaths.Select((value, i) => new KeyValuePair<int, string>(i, value))));
|
||||
}
|
||||
|
||||
private void GivenRootFolder(string seriesPath, string rootFolderPath)
|
||||
{
|
||||
Mocker.GetMock<IRootFolderService>()
|
||||
.Setup(v => v.GetBestRootFolderPath(seriesPath))
|
||||
.Returns(rootFolderPath);
|
||||
}
|
||||
|
||||
private void GivenExistingFolder(string folder)
|
||||
{
|
||||
Mocker.GetMock<IDiskProvider>()
|
||||
|
@ -62,8 +70,8 @@ namespace NzbDrone.Core.Test.DiskSpace
|
|||
public void should_check_diskspace_for_series_folders()
|
||||
{
|
||||
GivenSeries(_seriesFolder);
|
||||
|
||||
GivenExistingFolder(_seriesFolder);
|
||||
GivenRootFolder(_seriesFolder, _rootFolder);
|
||||
GivenExistingFolder(_rootFolder);
|
||||
|
||||
var freeSpace = Subject.GetFreeSpace();
|
||||
|
||||
|
@ -74,9 +82,9 @@ namespace NzbDrone.Core.Test.DiskSpace
|
|||
public void should_check_diskspace_for_same_root_folder_only_once()
|
||||
{
|
||||
GivenSeries(_seriesFolder, _seriesFolder2);
|
||||
|
||||
GivenExistingFolder(_seriesFolder);
|
||||
GivenExistingFolder(_seriesFolder2);
|
||||
GivenRootFolder(_seriesFolder, _rootFolder);
|
||||
GivenRootFolder(_seriesFolder2, _rootFolder);
|
||||
GivenExistingFolder(_rootFolder);
|
||||
|
||||
var freeSpace = Subject.GetFreeSpace();
|
||||
|
||||
|
@ -87,9 +95,10 @@ namespace NzbDrone.Core.Test.DiskSpace
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_check_diskspace_for_missing_series_folders()
|
||||
public void should_not_check_diskspace_for_missing_series_root_folders()
|
||||
{
|
||||
GivenSeries(_seriesFolder);
|
||||
GivenRootFolder(_seriesFolder, _rootFolder);
|
||||
|
||||
var freeSpace = Subject.GetFreeSpace();
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Text.RegularExpressions;
|
|||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.DiskSpace
|
||||
|
@ -18,14 +19,16 @@ namespace NzbDrone.Core.DiskSpace
|
|||
public class DiskSpaceService : IDiskSpaceService
|
||||
{
|
||||
private readonly ISeriesService _seriesService;
|
||||
private readonly IRootFolderService _rootFolderService;
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly Logger _logger;
|
||||
|
||||
private static readonly Regex _regexSpecialDrive = new Regex("^/var/lib/(docker|rancher|kubelet)(/|$)|^/(boot|etc)(/|$)|/docker(/var)?/aufs(/|$)", RegexOptions.Compiled);
|
||||
|
||||
public DiskSpaceService(ISeriesService seriesService, IDiskProvider diskProvider, Logger logger)
|
||||
public DiskSpaceService(ISeriesService seriesService, IRootFolderService rootFolderService, IDiskProvider diskProvider, Logger logger)
|
||||
{
|
||||
_seriesService = seriesService;
|
||||
_rootFolderService = rootFolderService;
|
||||
_diskProvider = diskProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
@ -43,9 +46,15 @@ namespace NzbDrone.Core.DiskSpace
|
|||
|
||||
private IEnumerable<string> GetSeriesRootPaths()
|
||||
{
|
||||
// Get all series paths and find the correct root folder for each. For each unique root folder path,
|
||||
// ensure the path exists and get its path root and return all unique path roots.
|
||||
|
||||
return _seriesService.GetAllSeriesPaths()
|
||||
.Where(s => s.Value.IsPathValid(PathValidationType.CurrentOs) && _diskProvider.FolderExists(s.Value))
|
||||
.Select(s => _diskProvider.GetPathRoot(s.Value))
|
||||
.Where(s => s.Value.IsPathValid(PathValidationType.CurrentOs))
|
||||
.Select(s => _rootFolderService.GetBestRootFolderPath(s.Value))
|
||||
.Distinct()
|
||||
.Where(r => _diskProvider.FolderExists(r))
|
||||
.Select(r => _diskProvider.GetPathRoot(r))
|
||||
.Distinct();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Organizer;
|
||||
|
@ -30,6 +31,8 @@ namespace NzbDrone.Core.RootFolders
|
|||
private readonly INamingConfigService _namingConfigService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
private readonly ICached<string> _cache;
|
||||
|
||||
private static readonly HashSet<string> SpecialFolders = new HashSet<string>
|
||||
{
|
||||
"$recycle.bin",
|
||||
|
@ -47,6 +50,7 @@ namespace NzbDrone.Core.RootFolders
|
|||
IDiskProvider diskProvider,
|
||||
ISeriesRepository seriesRepository,
|
||||
INamingConfigService namingConfigService,
|
||||
ICacheManager cacheManager,
|
||||
Logger logger)
|
||||
{
|
||||
_rootFolderRepository = rootFolderRepository;
|
||||
|
@ -54,6 +58,8 @@ namespace NzbDrone.Core.RootFolders
|
|||
_seriesRepository = seriesRepository;
|
||||
_namingConfigService = namingConfigService;
|
||||
_logger = logger;
|
||||
|
||||
_cache = cacheManager.GetCache<string>(GetType());
|
||||
}
|
||||
|
||||
public List<RootFolder> All()
|
||||
|
@ -110,13 +116,14 @@ namespace NzbDrone.Core.RootFolders
|
|||
|
||||
if (!_diskProvider.FolderWritable(rootFolder.Path))
|
||||
{
|
||||
throw new UnauthorizedAccessException(string.Format("Root folder path '{0}' is not writable by user '{1}'", rootFolder.Path, Environment.UserName));
|
||||
throw new UnauthorizedAccessException($"Root folder path '{rootFolder.Path}' is not writable by user '{Environment.UserName}'");
|
||||
}
|
||||
|
||||
_rootFolderRepository.Insert(rootFolder);
|
||||
var seriesPaths = _seriesRepository.AllSeriesPaths();
|
||||
|
||||
GetDetails(rootFolder, seriesPaths, true);
|
||||
_cache.Clear();
|
||||
|
||||
return rootFolder;
|
||||
}
|
||||
|
@ -124,6 +131,7 @@ namespace NzbDrone.Core.RootFolders
|
|||
public void Remove(int id)
|
||||
{
|
||||
_rootFolderRepository.Delete(id);
|
||||
_cache.Clear();
|
||||
}
|
||||
|
||||
private List<UnmappedFolder> GetUnmappedFolders(string path, Dictionary<int, string> seriesPaths)
|
||||
|
@ -186,16 +194,7 @@ namespace NzbDrone.Core.RootFolders
|
|||
|
||||
public string GetBestRootFolderPath(string path)
|
||||
{
|
||||
var possibleRootFolder = All().Where(r => r.Path.IsParentPath(path)).MaxBy(r => r.Path.Length);
|
||||
|
||||
if (possibleRootFolder == null)
|
||||
{
|
||||
var osPath = new OsPath(path);
|
||||
|
||||
return osPath.Directory.ToString().TrimEnd(osPath.IsUnixPath ? '/' : '\\');
|
||||
}
|
||||
|
||||
return possibleRootFolder?.Path;
|
||||
return _cache.Get(path, () => GetBestRootFolderPathInternal(path), TimeSpan.FromDays(1));
|
||||
}
|
||||
|
||||
private void GetDetails(RootFolder rootFolder, Dictionary<int, string> seriesPaths, bool timeout)
|
||||
|
@ -211,5 +210,19 @@ namespace NzbDrone.Core.RootFolders
|
|||
}
|
||||
}).Wait(timeout ? 5000 : -1);
|
||||
}
|
||||
|
||||
private string GetBestRootFolderPathInternal(string path)
|
||||
{
|
||||
var possibleRootFolder = All().Where(r => r.Path.IsParentPath(path)).MaxBy(r => r.Path.Length);
|
||||
|
||||
if (possibleRootFolder == null)
|
||||
{
|
||||
var osPath = new OsPath(path);
|
||||
|
||||
return osPath.Directory.ToString().TrimEnd(osPath.IsUnixPath ? '/' : '\\');
|
||||
}
|
||||
|
||||
return possibleRootFolder.Path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue