using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; using NLog; using NzbDrone.Common.Disk; using NzbDrone.Common.Extensions; using NzbDrone.Core.Movies; namespace NzbDrone.Core.DiskSpace { public interface IDiskSpaceService { List GetFreeSpace(); } public class DiskSpaceService : IDiskSpaceService { private readonly IMovieService _movieService; 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(IMovieService movieService, IDiskProvider diskProvider, Logger logger) { _movieService = movieService; _diskProvider = diskProvider; _logger = logger; } public List GetFreeSpace() { var importantRootFolders = GetMoviesRootPaths().Distinct().ToList(); var optionalRootFolders = GetFixedDisksRootPaths().Except(importantRootFolders).Distinct().ToList(); var diskSpace = GetDiskSpace(importantRootFolders).Concat(GetDiskSpace(optionalRootFolders, true)).ToList(); return diskSpace; } private IEnumerable GetMoviesRootPaths() { return _movieService.AllMoviePaths() .Where(s => s.Value.IsPathValid(PathValidationType.CurrentOs) && _diskProvider.FolderExists(s.Value)) .Select(s => _diskProvider.GetPathRoot(s.Value)) .Distinct(); } private IEnumerable GetFixedDisksRootPaths() { return _diskProvider.GetMounts() .Where(d => d.DriveType == DriveType.Fixed) .Where(d => !_regexSpecialDrive.IsMatch(d.RootDirectory)) .Select(d => d.RootDirectory); } private IEnumerable GetDiskSpace(IEnumerable paths, bool suppressWarnings = false) { foreach (var path in paths) { DiskSpace diskSpace = null; try { var freeSpace = _diskProvider.GetAvailableSpace(path); var totalSpace = _diskProvider.GetTotalSize(path); if (!freeSpace.HasValue || !totalSpace.HasValue) { continue; } diskSpace = new DiskSpace { Path = path, FreeSpace = freeSpace.Value, TotalSpace = totalSpace.Value }; diskSpace.Label = _diskProvider.GetVolumeLabel(path); } catch (Exception ex) { if (!suppressWarnings) { _logger.Warn(ex, "Unable to get free space for: " + path); } } if (diskSpace != null) { yield return diskSpace; } } } } }